Deprecate and remove use of alpha metadata.initializers field, remove IncludeUninitialized options
This commit is contained in:
@@ -34,7 +34,6 @@ import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/kubeapiserver/admission/util"
|
||||
)
|
||||
|
||||
// The annotation key scheduler.alpha.kubernetes.io/node-selector is for assigning
|
||||
@@ -99,14 +98,6 @@ func (p *podNodeSelector) Admit(a admission.Attributes) error {
|
||||
if shouldIgnore(a) {
|
||||
return nil
|
||||
}
|
||||
updateInitialized, err := util.IsUpdatingInitializedObject(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if updateInitialized {
|
||||
// node selector of an initialized pod is immutable
|
||||
return nil
|
||||
}
|
||||
if !p.WaitForReady() {
|
||||
return admission.NewForbidden(a, fmt.Errorf("not yet ready to handle request"))
|
||||
}
|
||||
@@ -199,7 +190,7 @@ func shouldIgnore(a admission.Attributes) bool {
|
||||
|
||||
func NewPodNodeSelector(clusterNodeSelectors map[string]string) *podNodeSelector {
|
||||
return &podNodeSelector{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
Handler: admission.NewHandler(admission.Create),
|
||||
clusterNodeSelectors: clusterNodeSelectors,
|
||||
}
|
||||
}
|
||||
|
@@ -53,12 +53,6 @@ func TestPodAdmission(t *testing.T) {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "testPod", Namespace: "testNamespace"},
|
||||
}
|
||||
|
||||
oldPod := *pod
|
||||
oldPod.Initializers = &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init"}}}
|
||||
oldPod.Spec.NodeSelector = map[string]string{
|
||||
"old": "true",
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
defaultNodeSelector string
|
||||
namespaceNodeSelector string
|
||||
@@ -182,30 +176,13 @@ func TestPodAdmission(t *testing.T) {
|
||||
} else if !test.admit && err == nil {
|
||||
t.Errorf("Test: %s, expected an error", test.testName)
|
||||
}
|
||||
|
||||
// handles update of uninitialized pod like it's newly created.
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, &oldPod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
|
||||
if test.admit && err != nil {
|
||||
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
|
||||
} else if !test.admit && err == nil {
|
||||
t.Errorf("Test: %s, expected an error", test.testName)
|
||||
}
|
||||
if test.admit && !labels.Equals(test.mergedNodeSelector, labels.Set(pod.Spec.NodeSelector)) {
|
||||
t.Errorf("Test: %s, expected: %s but got: %s", test.testName, test.mergedNodeSelector, pod.Spec.NodeSelector)
|
||||
}
|
||||
err = handler.Validate(admission.NewAttributesRecord(pod, &oldPod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
|
||||
if test.admit && err != nil {
|
||||
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
|
||||
} else if !test.admit && err == nil {
|
||||
t.Errorf("Test: %s, expected an error", test.testName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandles(t *testing.T) {
|
||||
for op, shouldHandle := range map[admission.Operation]bool{
|
||||
admission.Create: true,
|
||||
admission.Update: true,
|
||||
admission.Update: false,
|
||||
admission.Connect: false,
|
||||
admission.Delete: false,
|
||||
} {
|
||||
@@ -216,40 +193,6 @@ func TestHandles(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIgnoreUpdatingInitializedPod(t *testing.T) {
|
||||
namespaceNodeSelector := "infra=true"
|
||||
namespace := &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "testNamespace",
|
||||
Namespace: "",
|
||||
Annotations: map[string]string{"scheduler.alpha.kubernetes.io/node-selector": namespaceNodeSelector},
|
||||
},
|
||||
}
|
||||
mockClient := fake.NewSimpleClientset(namespace)
|
||||
handler, informerFactory, err := newHandlerForTest(mockClient)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error initializing handler: %v", err)
|
||||
}
|
||||
handler.SetReadyFunc(func() bool { return true })
|
||||
|
||||
podNodeSelector := map[string]string{"infra": "false"}
|
||||
pod := &api.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "testPod", Namespace: "testNamespace"},
|
||||
Spec: api.PodSpec{NodeSelector: podNodeSelector},
|
||||
}
|
||||
// this conflicts with podNodeSelector
|
||||
err = informerFactory.Core().V1().Namespaces().Informer().GetStore().Update(namespace)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// if the update of initialized pod is not ignored, an error will be returned because the pod's nodeSelector conflicts with namespace's nodeSelector.
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, pod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// newHandlerForTest returns the admission controller configured for testing.
|
||||
func newHandlerForTest(c kubernetes.Interface) (*podNodeSelector, informers.SharedInformerFactory, error) {
|
||||
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
||||
|
@@ -35,7 +35,6 @@ import (
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
qoshelper "k8s.io/kubernetes/pkg/apis/core/helper/qos"
|
||||
k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
||||
"k8s.io/kubernetes/pkg/kubeapiserver/admission/util"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
|
||||
"k8s.io/kubernetes/pkg/util/tolerations"
|
||||
pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
|
||||
@@ -93,11 +92,7 @@ func (p *podTolerationsPlugin) Admit(a admission.Attributes) error {
|
||||
|
||||
pod := a.GetObject().(*api.Pod)
|
||||
var finalTolerations []api.Toleration
|
||||
updateUninitialized, err := util.IsUpdatingUninitializedObject(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if a.GetOperation() == admission.Create || updateUninitialized {
|
||||
if a.GetOperation() == admission.Create {
|
||||
ts, err := p.getNamespaceDefaultTolerations(a.GetNamespace())
|
||||
if err != nil {
|
||||
return err
|
||||
|
@@ -254,11 +254,6 @@ func TestPodAdmission(t *testing.T) {
|
||||
pod := test.pod
|
||||
pod.Spec.Tolerations = test.podTolerations
|
||||
|
||||
// copy the original pod for tests of uninitialized pod updates.
|
||||
oldPod := *pod
|
||||
oldPod.Initializers = &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init"}}}
|
||||
oldPod.Spec.Tolerations = []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}}
|
||||
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if test.admit && err != nil {
|
||||
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
|
||||
@@ -270,19 +265,6 @@ func TestPodAdmission(t *testing.T) {
|
||||
if test.admit && !tolerations.EqualTolerations(updatedPodTolerations, test.mergedTolerations) {
|
||||
t.Errorf("Test: %s, expected: %#v but got: %#v", test.testName, test.mergedTolerations, updatedPodTolerations)
|
||||
}
|
||||
|
||||
// handles update of uninitialized pod like it's newly created.
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, &oldPod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
|
||||
if test.admit && err != nil {
|
||||
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
|
||||
} else if !test.admit && err == nil {
|
||||
t.Errorf("Test: %s, expected an error", test.testName)
|
||||
}
|
||||
|
||||
updatedPodTolerations = pod.Spec.Tolerations
|
||||
if test.admit && !tolerations.EqualTolerations(updatedPodTolerations, test.mergedTolerations) {
|
||||
t.Errorf("Test: %s, expected: %#v but got: %#v", test.testName, test.mergedTolerations, updatedPodTolerations)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -40,7 +40,6 @@ import (
|
||||
podutil "k8s.io/kubernetes/pkg/api/pod"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
kubefeatures "k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/kubeapiserver/admission/util"
|
||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||
)
|
||||
|
||||
@@ -105,7 +104,7 @@ var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&serviceAcc
|
||||
// 5. If MountServiceAccountToken is true, it adds a VolumeMount with the pod's ServiceAccount's api token secret to containers
|
||||
func NewServiceAccount() *serviceAccount {
|
||||
return &serviceAccount{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
Handler: admission.NewHandler(admission.Create),
|
||||
// TODO: enable this once we've swept secret usage to account for adding secret references to service accounts
|
||||
LimitSecretReferences: false,
|
||||
// Auto mount service account API token secrets
|
||||
@@ -153,14 +152,6 @@ func (s *serviceAccount) Admit(a admission.Attributes) (err error) {
|
||||
if shouldIgnore(a) {
|
||||
return nil
|
||||
}
|
||||
updateInitialized, err := util.IsUpdatingInitializedObject(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if updateInitialized {
|
||||
// related pod spec fields are immutable after the pod is initialized
|
||||
return nil
|
||||
}
|
||||
|
||||
pod := a.GetObject().(*api.Pod)
|
||||
|
||||
@@ -202,14 +193,6 @@ func (s *serviceAccount) Validate(a admission.Attributes) (err error) {
|
||||
if shouldIgnore(a) {
|
||||
return nil
|
||||
}
|
||||
updateInitialized, err := util.IsUpdatingInitializedObject(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if updateInitialized {
|
||||
// related pod spec fields are immutable after the pod is initialized
|
||||
return nil
|
||||
}
|
||||
|
||||
pod := a.GetObject().(*api.Pod)
|
||||
|
||||
@@ -257,6 +240,9 @@ func shouldIgnore(a admission.Attributes) bool {
|
||||
if a.GetResource().GroupResource() != api.Resource("pods") {
|
||||
return true
|
||||
}
|
||||
if a.GetSubresource() != "" {
|
||||
return true
|
||||
}
|
||||
obj := a.GetObject()
|
||||
if obj == nil {
|
||||
return true
|
||||
|
@@ -62,17 +62,6 @@ func TestIgnoresNonCreate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIgnoresUpdateOfInitializedPod(t *testing.T) {
|
||||
pod := &api.Pod{}
|
||||
oldPod := &api.Pod{}
|
||||
attrs := admission.NewAttributesRecord(pod, oldPod, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil)
|
||||
handler := NewServiceAccount()
|
||||
err := handler.Admit(attrs)
|
||||
if err != nil {
|
||||
t.Errorf("Expected update of initialized pod allowed, got err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIgnoresNonPodResource(t *testing.T) {
|
||||
pod := &api.Pod{}
|
||||
attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "myns", "myname", api.Resource("CustomResource").WithVersion("version"), "", admission.Create, false, nil)
|
||||
@@ -362,54 +351,6 @@ func TestAutomountsAPIToken(t *testing.T) {
|
||||
t.Fatalf("Expected\n\t%#v\ngot\n\t%#v", expectedVolumeMount, pod.Spec.Containers[0].VolumeMounts[0])
|
||||
}
|
||||
|
||||
// Test ServiceAccount admission plugin applies the same changes if the
|
||||
// operation is an update to an uninitialized pod.
|
||||
oldPod := &api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
// the volumeMount in the oldPod shouldn't affect the result.
|
||||
VolumeMounts: []api.VolumeMount{
|
||||
{
|
||||
Name: "wrong-" + tokenName,
|
||||
ReadOnly: true,
|
||||
MountPath: DefaultAPITokenMountPath,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
// oldPod is not intialized.
|
||||
oldPod.Initializers = &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init"}}}
|
||||
pod = &api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{},
|
||||
},
|
||||
},
|
||||
}
|
||||
attrs = admission.NewAttributesRecord(pod, oldPod, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil)
|
||||
err = admit.Admit(attrs)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if pod.Spec.ServiceAccountName != DefaultServiceAccountName {
|
||||
t.Errorf("Expected service account %s assigned, got %s", DefaultServiceAccountName, pod.Spec.ServiceAccountName)
|
||||
}
|
||||
if len(pod.Spec.Volumes) != 1 {
|
||||
t.Fatalf("Expected 1 volume, got %d", len(pod.Spec.Volumes))
|
||||
}
|
||||
if !reflect.DeepEqual(expectedVolume, pod.Spec.Volumes[0]) {
|
||||
t.Fatalf("Expected\n\t%#v\ngot\n\t%#v", expectedVolume, pod.Spec.Volumes[0])
|
||||
}
|
||||
if len(pod.Spec.Containers[0].VolumeMounts) != 1 {
|
||||
t.Fatalf("Expected 1 volume mount, got %d", len(pod.Spec.Containers[0].VolumeMounts))
|
||||
}
|
||||
if !reflect.DeepEqual(expectedVolumeMount, pod.Spec.Containers[0].VolumeMounts[0]) {
|
||||
t.Fatalf("Expected\n\t%#v\ngot\n\t%#v", expectedVolumeMount, pod.Spec.Containers[0].VolumeMounts[0])
|
||||
}
|
||||
|
||||
// testing InitContainers
|
||||
pod = &api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
|
Reference in New Issue
Block a user