mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-13 11:25:19 +00:00
Merge pull request #64267 from sttts/sttts-crd-objectmeta-pruning
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. apiextensions: add ObjectMeta validation and pruning This is a critical pre-requisite for further multi-version support and especially for GA of CRDs: ObjectMeta must be schema-validated and pruned, like `json.Unmarshal` does this. This PR adds this in the incoming request serializer and the storage decoder. The former errors when schema validation fails, the later just drops invalid typed fields. Fixes #59451 ```release-note Meta data of CustomResources is now pruned and schema checked during deserialization of requests and when read from etcd. In the former case, invalid meta data is rejected, in the later it is dropped from the CustomResource objects. ```
This commit is contained in:
@@ -12,6 +12,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/apis/apps:go_default_library",
|
||||
"//vendor/github.com/google/gofuzz:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -19,6 +19,7 @@ package fuzzer
|
||||
import (
|
||||
fuzz "github.com/google/gofuzz"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
)
|
||||
@@ -46,6 +47,12 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
if s.Status.CollisionCount == nil {
|
||||
s.Status.CollisionCount = new(int32)
|
||||
}
|
||||
if s.Spec.Selector == nil {
|
||||
s.Spec.Selector = &metav1.LabelSelector{MatchLabels: s.Spec.Template.Labels}
|
||||
}
|
||||
if len(s.Labels) == 0 {
|
||||
s.Labels = s.Spec.Template.Labels
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +182,7 @@ func Convert_v1_Deployment_To_extensions_Deployment(in *appsv1.Deployment, out *
|
||||
out.Spec.RollbackTo = new(extensions.RollbackConfig)
|
||||
out.Spec.RollbackTo.Revision = revision64
|
||||
}
|
||||
out.Annotations = deepCopyStringMap(out.Annotations)
|
||||
delete(out.Annotations, appsv1.DeprecatedRollbackTo)
|
||||
} else {
|
||||
out.Spec.RollbackTo = nil
|
||||
@@ -195,6 +196,8 @@ func Convert_v1_Deployment_To_extensions_Deployment(in *appsv1.Deployment, out *
|
||||
|
||||
func Convert_extensions_Deployment_To_v1_Deployment(in *extensions.Deployment, out *appsv1.Deployment, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
out.Annotations = deepCopyStringMap(out.Annotations) // deep copy because we modify it below
|
||||
|
||||
if err := Convert_extensions_DeploymentSpec_To_v1_DeploymentSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -235,9 +238,8 @@ func Convert_v1_RollingUpdateDaemonSet_To_extensions_RollingUpdateDaemonSet(in *
|
||||
|
||||
func Convert_extensions_DaemonSet_To_v1_DaemonSet(in *extensions.DaemonSet, out *appsv1.DaemonSet, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if out.Annotations == nil {
|
||||
out.Annotations = make(map[string]string)
|
||||
}
|
||||
out.Annotations = deepCopyStringMap(out.Annotations) // deep copy annotations because we change them below
|
||||
|
||||
out.Annotations[appsv1.DeprecatedTemplateGeneration] = strconv.FormatInt(in.Spec.TemplateGeneration, 10)
|
||||
if err := Convert_extensions_DaemonSetSpec_To_v1_DaemonSetSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
@@ -287,6 +289,7 @@ func Convert_v1_DaemonSet_To_extensions_DaemonSet(in *appsv1.DaemonSet, out *ext
|
||||
return err
|
||||
} else {
|
||||
out.Spec.TemplateGeneration = value64
|
||||
out.Annotations = deepCopyStringMap(out.Annotations)
|
||||
delete(out.Annotations, appsv1.DeprecatedTemplateGeneration)
|
||||
}
|
||||
}
|
||||
@@ -496,3 +499,11 @@ func Convert_apps_StatefulSetStatus_To_v1_StatefulSetStatus(in *apps.StatefulSet
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopyStringMap(m map[string]string) map[string]string {
|
||||
ret := make(map[string]string, len(m))
|
||||
for k, v := range m {
|
||||
ret[k] = v
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -415,6 +415,7 @@ func Convert_v1beta2_Deployment_To_extensions_Deployment(in *appsv1beta2.Deploym
|
||||
out.Spec.RollbackTo = new(extensions.RollbackConfig)
|
||||
out.Spec.RollbackTo.Revision = revision64
|
||||
}
|
||||
out.Annotations = deepCopyStringMap(out.Annotations)
|
||||
delete(out.Annotations, appsv1beta2.DeprecatedRollbackTo)
|
||||
} else {
|
||||
out.Spec.RollbackTo = nil
|
||||
@@ -440,6 +441,8 @@ func Convert_v1beta2_ReplicaSetSpec_To_extensions_ReplicaSetSpec(in *appsv1beta2
|
||||
|
||||
func Convert_extensions_Deployment_To_v1beta2_Deployment(in *extensions.Deployment, out *appsv1beta2.Deployment, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
out.Annotations = deepCopyStringMap(out.Annotations) // deep copy because we modify annotations below
|
||||
|
||||
if err := Convert_extensions_DeploymentSpec_To_v1beta2_DeploymentSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -463,9 +466,7 @@ func Convert_extensions_Deployment_To_v1beta2_Deployment(in *extensions.Deployme
|
||||
|
||||
func Convert_extensions_DaemonSet_To_v1beta2_DaemonSet(in *extensions.DaemonSet, out *appsv1beta2.DaemonSet, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if out.Annotations == nil {
|
||||
out.Annotations = make(map[string]string)
|
||||
}
|
||||
out.Annotations = deepCopyStringMap(out.Annotations)
|
||||
out.Annotations[appsv1beta2.DeprecatedTemplateGeneration] = strconv.FormatInt(in.Spec.TemplateGeneration, 10)
|
||||
if err := Convert_extensions_DaemonSetSpec_To_v1beta2_DaemonSetSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
@@ -515,6 +516,7 @@ func Convert_v1beta2_DaemonSet_To_extensions_DaemonSet(in *appsv1beta2.DaemonSet
|
||||
return err
|
||||
} else {
|
||||
out.Spec.TemplateGeneration = value64
|
||||
out.Annotations = deepCopyStringMap(out.Annotations)
|
||||
delete(out.Annotations, appsv1beta2.DeprecatedTemplateGeneration)
|
||||
}
|
||||
}
|
||||
@@ -552,3 +554,11 @@ func Convert_v1beta2_DaemonSetUpdateStrategy_To_extensions_DaemonSetUpdateStrate
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopyStringMap(m map[string]string) map[string]string {
|
||||
ret := make(map[string]string, len(m))
|
||||
for k, v := range m {
|
||||
ret[k] = v
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -32,6 +32,14 @@ func newBool(val bool) *bool {
|
||||
// Funcs returns the fuzzer functions for the batch api group.
|
||||
var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
return []interface{}{
|
||||
func(j *batch.Job, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
||||
|
||||
// match defaulting
|
||||
if len(j.Labels) == 0 {
|
||||
j.Labels = j.Spec.Template.Labels
|
||||
}
|
||||
},
|
||||
func(j *batch.JobSpec, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
||||
completions := int32(c.Rand.Int31())
|
||||
|
||||
@@ -93,6 +93,19 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
c.Fuzz(&j.ObjectMeta)
|
||||
j.Target.Name = c.RandString()
|
||||
},
|
||||
func(j *core.ReplicationController, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(j)
|
||||
|
||||
// match defaulting
|
||||
if j.Spec.Template != nil {
|
||||
if len(j.Labels) == 0 {
|
||||
j.Labels = j.Spec.Template.Labels
|
||||
}
|
||||
if len(j.Spec.Selector) == 0 {
|
||||
j.Spec.Selector = j.Spec.Template.Labels
|
||||
}
|
||||
}
|
||||
},
|
||||
func(j *core.ReplicationControllerSpec, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
||||
//j.TemplateRef = nil // this is required for round trip
|
||||
|
||||
@@ -12,6 +12,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//vendor/github.com/google/gofuzz:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
],
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
|
||||
fuzz "github.com/google/gofuzz"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
@@ -29,6 +30,17 @@ import (
|
||||
// Funcs returns the fuzzer functions for the extensions api group.
|
||||
var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
return []interface{}{
|
||||
func(j *extensions.Deployment, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(j)
|
||||
|
||||
// match defaulting
|
||||
if j.Spec.Selector == nil {
|
||||
j.Spec.Selector = &metav1.LabelSelector{MatchLabels: j.Spec.Template.Labels}
|
||||
}
|
||||
if len(j.Labels) == 0 {
|
||||
j.Labels = j.Spec.Template.Labels
|
||||
}
|
||||
},
|
||||
func(j *extensions.DeploymentSpec, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
||||
rhl := int32(c.Rand.Int31())
|
||||
@@ -54,6 +66,15 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
j.RollingUpdate = &rollingUpdate
|
||||
}
|
||||
},
|
||||
func(j *extensions.DaemonSet, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(j)
|
||||
|
||||
// match defaulter
|
||||
j.Spec.Template.Generation = 0
|
||||
if len(j.ObjectMeta.Labels) == 0 {
|
||||
j.ObjectMeta.Labels = j.Spec.Template.ObjectMeta.Labels
|
||||
}
|
||||
},
|
||||
func(j *extensions.DaemonSetSpec, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(j) // fuzz self without calling this function again
|
||||
rhl := int32(c.Rand.Int31())
|
||||
@@ -78,5 +99,16 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
j.RollingUpdate = &rollingUpdate
|
||||
}
|
||||
},
|
||||
func(j *extensions.ReplicaSet, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(j)
|
||||
|
||||
// match defaulter
|
||||
if j.Spec.Selector == nil {
|
||||
j.Spec.Selector = &metav1.LabelSelector{MatchLabels: j.Spec.Template.Labels}
|
||||
}
|
||||
if len(j.Labels) == 0 {
|
||||
j.Labels = j.Spec.Template.Labels
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user