Deprecate and remove use of alpha metadata.initializers field, remove IncludeUninitialized options

This commit is contained in:
Jordan Liggitt
2019-01-17 09:19:28 -05:00
parent dc1fa870bf
commit 17aa60686e
77 changed files with 236 additions and 3868 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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)

View File

@@ -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.

View File

@@ -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

View File

@@ -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.

View File

@@ -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