mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-10-22 06:59:03 +00:00
Deprecate and remove use of alpha metadata.initializers field, remove IncludeUninitialized options
This commit is contained in:
@@ -160,12 +160,12 @@ func ReplicaSetToSelectableFields(rs *apps.ReplicaSet) fields.Set {
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
rs, ok := obj.(*apps.ReplicaSet)
|
||||
if !ok {
|
||||
return nil, nil, false, fmt.Errorf("given object is not a ReplicaSet.")
|
||||
return nil, nil, fmt.Errorf("given object is not a ReplicaSet.")
|
||||
}
|
||||
return labels.Set(rs.ObjectMeta.Labels), ReplicaSetToSelectableFields(rs), rs.Initializers != nil, nil
|
||||
return labels.Set(rs.ObjectMeta.Labels), ReplicaSetToSelectableFields(rs), nil
|
||||
}
|
||||
|
||||
// MatchReplicaSet is the filter used by the generic etcd backend to route
|
||||
|
@@ -202,12 +202,12 @@ func JobToSelectableFields(job *batch.Job) fields.Set {
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
job, ok := obj.(*batch.Job)
|
||||
if !ok {
|
||||
return nil, nil, false, fmt.Errorf("given object is not a job.")
|
||||
return nil, nil, fmt.Errorf("given object is not a job.")
|
||||
}
|
||||
return labels.Set(job.ObjectMeta.Labels), JobToSelectableFields(job), job.Initializers != nil, nil
|
||||
return labels.Set(job.ObjectMeta.Labels), JobToSelectableFields(job), nil
|
||||
}
|
||||
|
||||
// MatchJob is the filter used by the generic etcd backend to route
|
||||
|
@@ -79,12 +79,12 @@ func (eventStrategy) AllowUnconditionalUpdate() bool {
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
event, ok := obj.(*api.Event)
|
||||
if !ok {
|
||||
return nil, nil, false, fmt.Errorf("not an event")
|
||||
return nil, nil, fmt.Errorf("not an event")
|
||||
}
|
||||
return labels.Set(event.Labels), EventToSelectableFields(event), event.Initializers != nil, nil
|
||||
return labels.Set(event.Labels), EventToSelectableFields(event), nil
|
||||
}
|
||||
|
||||
func MatchEvent(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
|
||||
|
@@ -139,12 +139,12 @@ func (namespaceFinalizeStrategy) PrepareForUpdate(ctx context.Context, obj, old
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
namespaceObj, ok := obj.(*api.Namespace)
|
||||
if !ok {
|
||||
return nil, nil, false, fmt.Errorf("not a namespace")
|
||||
return nil, nil, fmt.Errorf("not a namespace")
|
||||
}
|
||||
return labels.Set(namespaceObj.Labels), NamespaceToSelectableFields(namespaceObj), namespaceObj.Initializers != nil, nil
|
||||
return labels.Set(namespaceObj.Labels), NamespaceToSelectableFields(namespaceObj), nil
|
||||
}
|
||||
|
||||
// MatchNamespace returns a generic matcher for a given label and field selector.
|
||||
|
@@ -181,12 +181,12 @@ func NodeToSelectableFields(node *api.Node) fields.Set {
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
nodeObj, ok := obj.(*api.Node)
|
||||
if !ok {
|
||||
return nil, nil, false, fmt.Errorf("not a node")
|
||||
return nil, nil, fmt.Errorf("not a node")
|
||||
}
|
||||
return labels.Set(nodeObj.ObjectMeta.Labels), NodeToSelectableFields(nodeObj), nodeObj.Initializers != nil, nil
|
||||
return labels.Set(nodeObj.ObjectMeta.Labels), NodeToSelectableFields(nodeObj), nil
|
||||
}
|
||||
|
||||
// MatchNode returns a generic matcher for a given label and field selector.
|
||||
|
@@ -108,12 +108,12 @@ func (persistentvolumeStatusStrategy) ValidateUpdate(ctx context.Context, obj, o
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
persistentvolumeObj, ok := obj.(*api.PersistentVolume)
|
||||
if !ok {
|
||||
return nil, nil, false, fmt.Errorf("not a persistentvolume")
|
||||
return nil, nil, fmt.Errorf("not a persistentvolume")
|
||||
}
|
||||
return labels.Set(persistentvolumeObj.Labels), PersistentVolumeToSelectableFields(persistentvolumeObj), persistentvolumeObj.Initializers != nil, nil
|
||||
return labels.Set(persistentvolumeObj.Labels), PersistentVolumeToSelectableFields(persistentvolumeObj), nil
|
||||
}
|
||||
|
||||
// MatchPersistentVolume returns a generic matcher for a given label and field selector.
|
||||
|
@@ -109,12 +109,12 @@ func (persistentvolumeclaimStatusStrategy) ValidateUpdate(ctx context.Context, o
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
persistentvolumeclaimObj, ok := obj.(*api.PersistentVolumeClaim)
|
||||
if !ok {
|
||||
return nil, nil, false, fmt.Errorf("not a persistentvolumeclaim")
|
||||
return nil, nil, fmt.Errorf("not a persistentvolumeclaim")
|
||||
}
|
||||
return labels.Set(persistentvolumeclaimObj.Labels), PersistentVolumeClaimToSelectableFields(persistentvolumeclaimObj), persistentvolumeclaimObj.Initializers != nil, nil
|
||||
return labels.Set(persistentvolumeclaimObj.Labels), PersistentVolumeClaimToSelectableFields(persistentvolumeclaimObj), nil
|
||||
}
|
||||
|
||||
// MatchPersistentVolumeClaim returns a generic matcher for a given label and field selector.
|
||||
|
@@ -32,7 +32,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
||||
genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing"
|
||||
@@ -40,8 +39,6 @@ import (
|
||||
"k8s.io/apiserver/pkg/storage"
|
||||
storeerr "k8s.io/apiserver/pkg/storage/errors"
|
||||
etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/registry/registrytest"
|
||||
"k8s.io/kubernetes/pkg/securitycontext"
|
||||
@@ -729,76 +726,6 @@ func TestEtcdCreateBinding(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEtcdUpdateUninitialized(t *testing.T) {
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.Initializers, true)()
|
||||
storage, _, _, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.Store.DestroyFunc()
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
|
||||
pod := validNewPod()
|
||||
// add pending initializers to the pod
|
||||
pod.ObjectMeta.Initializers = &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init.k8s.io"}}}
|
||||
if _, err := storage.Create(ctx, pod, rest.ValidateAllObjectFunc, &metav1.CreateOptions{IncludeUninitialized: true}); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
podIn := *pod
|
||||
// only uninitialized pod is allowed to add containers via update
|
||||
podIn.Spec.Containers = append(podIn.Spec.Containers, api.Container{
|
||||
Name: "foo2",
|
||||
Image: "test",
|
||||
ImagePullPolicy: api.PullAlways,
|
||||
TerminationMessagePath: api.TerminationMessagePathDefault,
|
||||
TerminationMessagePolicy: api.TerminationMessageReadFile,
|
||||
SecurityContext: securitycontext.ValidInternalSecurityContextWithContainerDefaults(),
|
||||
})
|
||||
podIn.ObjectMeta.Initializers = nil
|
||||
|
||||
_, _, err := storage.Update(ctx, podIn.Name, rest.DefaultUpdatedObjectInfo(&podIn), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
obj, err := storage.Get(ctx, podIn.ObjectMeta.Name, &metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
podOut := obj.(*api.Pod)
|
||||
if podOut.GetInitializers() != nil {
|
||||
t.Errorf("expect nil initializers, got %v", podOut.ObjectMeta.Initializers)
|
||||
}
|
||||
if !apiequality.Semantic.DeepEqual(podIn.Spec.Containers, podOut.Spec.Containers) {
|
||||
t.Errorf("objects differ: %v", diff.ObjectDiff(podOut, &podIn))
|
||||
}
|
||||
}
|
||||
|
||||
func TestEtcdStatusUpdateUninitialized(t *testing.T) {
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.Initializers, true)()
|
||||
storage, _, statusStorage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.Store.DestroyFunc()
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
|
||||
pod := validNewPod()
|
||||
// add pending initializers to the pod
|
||||
pod.ObjectMeta.Initializers = &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init.k8s.io"}}}
|
||||
if _, err := storage.Create(ctx, pod, rest.ValidateAllObjectFunc, &metav1.CreateOptions{IncludeUninitialized: true}); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
podIn := *pod
|
||||
// only uninitialized pod is allowed to add containers via update
|
||||
podIn.Status.Phase = api.PodRunning
|
||||
podIn.ObjectMeta.Initializers = nil
|
||||
|
||||
_, _, err := statusStorage.Update(ctx, podIn.Name, rest.DefaultUpdatedObjectInfo(&podIn), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{})
|
||||
expected := "Forbidden: must not update status when the object is uninitialized"
|
||||
if err == nil {
|
||||
t.Fatalf("Unexpected no err, expected %q", expected)
|
||||
}
|
||||
if !strings.Contains(err.Error(), expected) {
|
||||
t.Errorf("unexpected error: %v, expected %q", err, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEtcdUpdateNotScheduled(t *testing.T) {
|
||||
storage, _, _, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
|
@@ -27,20 +27,16 @@ import (
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
apimachineryvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
"k8s.io/apiserver/pkg/storage"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
podutil "k8s.io/kubernetes/pkg/api/pod"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
@@ -100,31 +96,9 @@ func (podStrategy) AllowCreateOnUpdate() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func isUpdatingUninitializedPod(old runtime.Object) (bool, error) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.Initializers) {
|
||||
return false, nil
|
||||
}
|
||||
oldMeta, err := meta.Accessor(old)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
oldInitializers := oldMeta.GetInitializers()
|
||||
if oldInitializers != nil && len(oldInitializers.Pending) != 0 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// ValidateUpdate is the default update validation for an end user.
|
||||
func (podStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
|
||||
errorList := validation.ValidatePod(obj.(*api.Pod))
|
||||
uninitializedUpdate, err := isUpdatingUninitializedPod(old)
|
||||
if err != nil {
|
||||
return append(errorList, field.InternalError(field.NewPath("metadata"), err))
|
||||
}
|
||||
if uninitializedUpdate {
|
||||
return errorList
|
||||
}
|
||||
return append(errorList, validation.ValidatePodUpdate(obj.(*api.Pod), old.(*api.Pod))...)
|
||||
}
|
||||
|
||||
@@ -193,25 +167,16 @@ func (podStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
|
||||
}
|
||||
|
||||
func (podStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
|
||||
var errorList field.ErrorList
|
||||
uninitializedUpdate, err := isUpdatingUninitializedPod(old)
|
||||
if err != nil {
|
||||
return append(errorList, field.InternalError(field.NewPath("metadata"), err))
|
||||
}
|
||||
if uninitializedUpdate {
|
||||
return append(errorList, field.Forbidden(field.NewPath("status"), apimachineryvalidation.UninitializedStatusUpdateErrorMsg))
|
||||
}
|
||||
// TODO: merge valid fields after update
|
||||
return validation.ValidatePodStatusUpdate(obj.(*api.Pod), old.(*api.Pod))
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
pod, ok := obj.(*api.Pod)
|
||||
if !ok {
|
||||
return nil, nil, false, fmt.Errorf("not a pod")
|
||||
return nil, nil, fmt.Errorf("not a pod")
|
||||
}
|
||||
return labels.Set(pod.ObjectMeta.Labels), PodToSelectableFields(pod), pod.Initializers != nil, nil
|
||||
return labels.Set(pod.ObjectMeta.Labels), PodToSelectableFields(pod), nil
|
||||
}
|
||||
|
||||
// MatchPod returns a generic matcher for a given label and field selector.
|
||||
|
@@ -164,12 +164,12 @@ func ControllerToSelectableFields(controller *api.ReplicationController) fields.
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
rc, ok := obj.(*api.ReplicationController)
|
||||
if !ok {
|
||||
return nil, nil, false, fmt.Errorf("given object is not a replication controller.")
|
||||
return nil, nil, fmt.Errorf("given object is not a replication controller.")
|
||||
}
|
||||
return labels.Set(rc.ObjectMeta.Labels), ControllerToSelectableFields(rc), rc.Initializers != nil, nil
|
||||
return labels.Set(rc.ObjectMeta.Labels), ControllerToSelectableFields(rc), nil
|
||||
}
|
||||
|
||||
// MatchController is the filter used by the generic etcd backend to route
|
||||
|
@@ -98,12 +98,12 @@ func (s strategy) Export(ctx context.Context, obj runtime.Object, exact bool) er
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
secret, ok := obj.(*api.Secret)
|
||||
if !ok {
|
||||
return nil, nil, false, fmt.Errorf("not a secret")
|
||||
return nil, nil, fmt.Errorf("not a secret")
|
||||
}
|
||||
return labels.Set(secret.Labels), SelectableFields(secret), secret.Initializers != nil, nil
|
||||
return labels.Set(secret.Labels), SelectableFields(secret), nil
|
||||
}
|
||||
|
||||
// Matcher returns a generic matcher for a given label and field selector.
|
||||
|
@@ -85,12 +85,12 @@ func SelectableFields(pip *api.Event) fields.Set {
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
pip, ok := obj.(*api.Event)
|
||||
if !ok {
|
||||
return nil, nil, false, fmt.Errorf("given object is not a Event")
|
||||
return nil, nil, fmt.Errorf("given object is not a Event")
|
||||
}
|
||||
return labels.Set(pip.ObjectMeta.Labels), SelectableFields(pip), pip.Initializers != nil, nil
|
||||
return labels.Set(pip.ObjectMeta.Labels), SelectableFields(pip), nil
|
||||
}
|
||||
|
||||
// Matcher is the filter used by the generic etcd backend to watch events
|
||||
|
Reference in New Issue
Block a user