123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- /*
- Copyright 2016 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package gc
- import (
- "context"
- "fmt"
- "strings"
- "testing"
- appsv1 "k8s.io/api/apps/v1"
- corev1 "k8s.io/api/core/v1"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/apimachinery/pkg/runtime"
- "k8s.io/apimachinery/pkg/runtime/schema"
- "k8s.io/apiserver/pkg/admission"
- "k8s.io/apiserver/pkg/admission/initializer"
- "k8s.io/apiserver/pkg/authentication/user"
- "k8s.io/apiserver/pkg/authorization/authorizer"
- fakediscovery "k8s.io/client-go/discovery/fake"
- "k8s.io/client-go/restmapper"
- coretesting "k8s.io/client-go/testing"
- api "k8s.io/kubernetes/pkg/apis/core"
- kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
- )
- type fakeAuthorizer struct{}
- func (fakeAuthorizer) Authorize(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
- username := a.GetUser().GetName()
- if username == "non-deleter" {
- if a.GetVerb() == "delete" {
- return authorizer.DecisionNoOpinion, "", nil
- }
- if a.GetVerb() == "update" && a.GetSubresource() == "finalizers" {
- return authorizer.DecisionNoOpinion, "", nil
- }
- return authorizer.DecisionAllow, "", nil
- }
- if username == "non-pod-deleter" {
- if a.GetVerb() == "delete" && a.GetResource() == "pods" {
- return authorizer.DecisionNoOpinion, "", nil
- }
- if a.GetVerb() == "update" && a.GetResource() == "pods" && a.GetSubresource() == "finalizers" {
- return authorizer.DecisionNoOpinion, "", nil
- }
- return authorizer.DecisionAllow, "", nil
- }
- if username == "non-rc-deleter" {
- if a.GetVerb() == "delete" && a.GetResource() == "replicationcontrollers" {
- return authorizer.DecisionNoOpinion, "", nil
- }
- if a.GetVerb() == "update" && a.GetResource() == "replicationcontrollers" && a.GetSubresource() == "finalizers" {
- return authorizer.DecisionNoOpinion, "", nil
- }
- return authorizer.DecisionAllow, "", nil
- }
- if username == "non-node-deleter" {
- if a.GetVerb() == "delete" && a.GetResource() == "nodes" {
- return authorizer.DecisionNoOpinion, "", nil
- }
- if a.GetVerb() == "update" && a.GetResource() == "nodes" && a.GetSubresource() == "finalizers" {
- return authorizer.DecisionNoOpinion, "", nil
- }
- return authorizer.DecisionAllow, "", nil
- }
- return authorizer.DecisionAllow, "", nil
- }
- // newGCPermissionsEnforcement returns the admission controller configured for testing.
- func newGCPermissionsEnforcement() (*gcPermissionsEnforcement, error) {
- // the pods/status endpoint is ignored by this plugin since old kubelets
- // corrupt them. the pod status strategy ensures status updates cannot mutate
- // ownerRef.
- whiteList := []whiteListItem{
- {
- groupResource: schema.GroupResource{Resource: "pods"},
- subresource: "status",
- },
- }
- gcAdmit := &gcPermissionsEnforcement{
- Handler: admission.NewHandler(admission.Create, admission.Update),
- whiteList: whiteList,
- }
- genericPluginInitializer := initializer.New(nil, nil, fakeAuthorizer{}, nil)
- fakeDiscoveryClient := &fakediscovery.FakeDiscovery{Fake: &coretesting.Fake{}}
- fakeDiscoveryClient.Resources = []*metav1.APIResourceList{
- {
- GroupVersion: corev1.SchemeGroupVersion.String(),
- APIResources: []metav1.APIResource{
- {Name: "nodes", Namespaced: false, Kind: "Node"},
- {Name: "pods", Namespaced: true, Kind: "Pod"},
- {Name: "replicationcontrollers", Namespaced: true, Kind: "ReplicationController"},
- },
- },
- {
- GroupVersion: appsv1.SchemeGroupVersion.String(),
- APIResources: []metav1.APIResource{
- {Name: "daemonsets", Namespaced: true, Kind: "DaemonSet"},
- },
- },
- }
- restMapperRes, err := restmapper.GetAPIGroupResources(fakeDiscoveryClient)
- if err != nil {
- return nil, fmt.Errorf("unexpected error while constructing resource list from fake discovery client: %v", err)
- }
- restMapper := restmapper.NewDiscoveryRESTMapper(restMapperRes)
- pluginInitializer := kubeadmission.NewPluginInitializer(nil, restMapper, nil)
- initializersChain := admission.PluginInitializers{}
- initializersChain = append(initializersChain, genericPluginInitializer)
- initializersChain = append(initializersChain, pluginInitializer)
- initializersChain.Initialize(gcAdmit)
- return gcAdmit, nil
- }
- func TestGCAdmission(t *testing.T) {
- expectNoError := func(err error) bool {
- return err == nil
- }
- expectCantSetOwnerRefError := func(err error) bool {
- if err == nil {
- return false
- }
- return strings.Contains(err.Error(), "cannot set an ownerRef on a resource you can't delete")
- }
- tests := []struct {
- name string
- username string
- resource schema.GroupVersionResource
- subresource string
- oldObj runtime.Object
- newObj runtime.Object
- checkError func(error) bool
- }{
- {
- name: "super-user, create, no objectref change",
- username: "super",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: &api.Pod{},
- checkError: expectNoError,
- },
- {
- name: "super-user, create, objectref change",
- username: "super",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- checkError: expectNoError,
- },
- {
- name: "non-deleter, create, no objectref change",
- username: "non-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: &api.Pod{},
- checkError: expectNoError,
- },
- {
- name: "non-deleter, create, objectref change",
- username: "non-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- checkError: expectNoError,
- },
- {
- name: "non-pod-deleter, create, no objectref change",
- username: "non-pod-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: &api.Pod{},
- checkError: expectNoError,
- },
- {
- name: "non-pod-deleter, create, objectref change",
- username: "non-pod-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- checkError: expectNoError,
- },
- {
- name: "non-pod-deleter, create, objectref change, but not a pod",
- username: "non-pod-deleter",
- resource: api.SchemeGroupVersion.WithResource("not-pods"),
- newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- checkError: expectNoError,
- },
- {
- name: "super-user, update, no objectref change",
- username: "super",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: &api.Pod{},
- newObj: &api.Pod{},
- checkError: expectNoError,
- },
- {
- name: "super-user, update, no objectref change two",
- username: "super",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- checkError: expectNoError,
- },
- {
- name: "super-user, update, objectref change",
- username: "super",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: &api.Pod{},
- newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- checkError: expectNoError,
- },
- {
- name: "non-deleter, update, no objectref change",
- username: "non-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: &api.Pod{},
- newObj: &api.Pod{},
- checkError: expectNoError,
- },
- {
- name: "non-deleter, update, no objectref change two",
- username: "non-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- checkError: expectNoError,
- },
- {
- name: "non-deleter, update, objectref change",
- username: "non-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: &api.Pod{},
- newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- checkError: expectCantSetOwnerRefError,
- },
- {
- name: "non-deleter, update, objectref change two",
- username: "non-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}, {Name: "second"}}}},
- checkError: expectCantSetOwnerRefError,
- },
- {
- name: "non-pod-deleter, update, no objectref change",
- username: "non-pod-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: &api.Pod{},
- newObj: &api.Pod{},
- checkError: expectNoError,
- },
- {
- name: "non-pod-deleter, update status, objectref change",
- username: "non-pod-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- subresource: "status",
- oldObj: &api.Pod{},
- newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- checkError: expectNoError,
- },
- {
- name: "non-pod-deleter, update, objectref change",
- username: "non-pod-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: &api.Pod{},
- newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- checkError: expectCantSetOwnerRefError,
- },
- {
- name: "non-pod-deleter, update, objectref change, but not a pod",
- username: "non-pod-deleter",
- resource: api.SchemeGroupVersion.WithResource("not-pods"),
- oldObj: &api.Pod{},
- newObj: &api.Pod{ObjectMeta: metav1.ObjectMeta{OwnerReferences: []metav1.OwnerReference{{Name: "first"}}}},
- checkError: expectNoError,
- },
- }
- for _, tc := range tests {
- t.Run(tc.name, func(t *testing.T) {
- gcAdmit, err := newGCPermissionsEnforcement()
- if err != nil {
- t.Error(err)
- }
- operation := admission.Create
- var options runtime.Object = &metav1.CreateOptions{}
- if tc.oldObj != nil {
- operation = admission.Update
- options = &metav1.UpdateOptions{}
- }
- user := &user.DefaultInfo{Name: tc.username}
- attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, options, false, user)
- err = gcAdmit.Validate(context.TODO(), attributes, nil)
- if !tc.checkError(err) {
- t.Errorf("unexpected err: %v", err)
- }
- })
- }
- }
- func TestBlockOwnerDeletionAdmission(t *testing.T) {
- podWithOwnerRefs := func(refs ...metav1.OwnerReference) *api.Pod {
- var refSlice []metav1.OwnerReference
- refSlice = append(refSlice, refs...)
- return &api.Pod{
- ObjectMeta: metav1.ObjectMeta{
- OwnerReferences: refSlice,
- },
- }
- }
- getTrueVar := func() *bool {
- ret := true
- return &ret
- }
- getFalseVar := func() *bool {
- ret := false
- return &ret
- }
- blockRC1 := metav1.OwnerReference{
- APIVersion: "v1",
- Kind: "ReplicationController",
- Name: "rc1",
- BlockOwnerDeletion: getTrueVar(),
- }
- blockRC2 := metav1.OwnerReference{
- APIVersion: "v1",
- Kind: "ReplicationController",
- Name: "rc2",
- BlockOwnerDeletion: getTrueVar(),
- }
- notBlockRC1 := metav1.OwnerReference{
- APIVersion: "v1",
- Kind: "ReplicationController",
- Name: "rc1",
- BlockOwnerDeletion: getFalseVar(),
- }
- notBlockRC2 := metav1.OwnerReference{
- APIVersion: "v1",
- Kind: "ReplicationController",
- Name: "rc2",
- BlockOwnerDeletion: getFalseVar(),
- }
- nilBlockRC1 := metav1.OwnerReference{
- APIVersion: "v1",
- Kind: "ReplicationController",
- Name: "rc1",
- }
- nilBlockRC2 := metav1.OwnerReference{
- APIVersion: "v1",
- Kind: "ReplicationController",
- Name: "rc2",
- }
- blockDS1 := metav1.OwnerReference{
- APIVersion: "apps/v1",
- Kind: "DaemonSet",
- Name: "ds1",
- BlockOwnerDeletion: getTrueVar(),
- }
- notBlockDS1 := metav1.OwnerReference{
- APIVersion: "apps/v1",
- Kind: "DaemonSet",
- Name: "ds1",
- BlockOwnerDeletion: getFalseVar(),
- }
- blockNode := metav1.OwnerReference{
- APIVersion: "v1",
- Kind: "Node",
- Name: "node1",
- BlockOwnerDeletion: getTrueVar(),
- }
- notBlockNode := metav1.OwnerReference{
- APIVersion: "v1",
- Kind: "Node",
- Name: "node",
- BlockOwnerDeletion: getFalseVar(),
- }
- nilBlockNode := metav1.OwnerReference{
- APIVersion: "v1",
- Kind: "Node",
- Name: "node",
- }
- expectNoError := func(err error) bool {
- return err == nil
- }
- expectCantSetBlockOwnerDeletionError := func(err error) bool {
- if err == nil {
- return false
- }
- return strings.Contains(err.Error(), "cannot set blockOwnerDeletion if an ownerReference refers to a resource you can't set finalizers on")
- }
- tests := []struct {
- name string
- username string
- resource schema.GroupVersionResource
- subresource string
- oldObj runtime.Object
- newObj runtime.Object
- checkError func(error) bool
- }{
- // cases for create
- {
- name: "super-user, create, no ownerReferences",
- username: "super",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: podWithOwnerRefs(),
- checkError: expectNoError,
- },
- {
- name: "super-user, create, all ownerReferences have blockOwnerDeletion=false",
- username: "super",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: podWithOwnerRefs(notBlockRC1, notBlockRC2),
- checkError: expectNoError,
- },
- {
- name: "super-user, create, some ownerReferences have blockOwnerDeletion=true",
- username: "super",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: podWithOwnerRefs(blockRC1, blockRC2, blockNode),
- checkError: expectNoError,
- },
- {
- name: "non-rc-deleter, create, no ownerReferences",
- username: "non-rc-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: podWithOwnerRefs(),
- checkError: expectNoError,
- },
- {
- name: "non-rc-deleter, create, all ownerReferences have blockOwnerDeletion=false or nil",
- username: "non-rc-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: podWithOwnerRefs(notBlockRC1, nilBlockRC2),
- checkError: expectNoError,
- },
- {
- name: "non-node-deleter, create, all ownerReferences have blockOwnerDeletion=false",
- username: "non-node-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: podWithOwnerRefs(notBlockNode),
- checkError: expectNoError,
- },
- {
- name: "non-rc-deleter, create, some ownerReferences have blockOwnerDeletion=true",
- username: "non-rc-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: podWithOwnerRefs(blockRC1, notBlockRC2),
- checkError: expectCantSetBlockOwnerDeletionError,
- },
- {
- name: "non-rc-deleter, create, some ownerReferences have blockOwnerDeletion=true, but are pointing to daemonset",
- username: "non-rc-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: podWithOwnerRefs(blockDS1),
- checkError: expectNoError,
- },
- {
- name: "non-node-deleter, create, some ownerReferences have blockOwnerDeletion=true",
- username: "non-node-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- newObj: podWithOwnerRefs(blockNode),
- checkError: expectCantSetBlockOwnerDeletionError,
- },
- // cases are for update
- {
- name: "super-user, update, no ownerReferences change blockOwnerDeletion",
- username: "super",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(nilBlockRC1, nilBlockNode),
- newObj: podWithOwnerRefs(notBlockRC1, notBlockNode),
- checkError: expectNoError,
- },
- {
- name: "super-user, update, some ownerReferences change to blockOwnerDeletion=true",
- username: "super",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(notBlockRC1, notBlockNode),
- newObj: podWithOwnerRefs(blockRC1, blockNode),
- checkError: expectNoError,
- },
- {
- name: "super-user, update, add new ownerReferences with blockOwnerDeletion=true",
- username: "super",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(),
- newObj: podWithOwnerRefs(blockRC1, blockNode),
- checkError: expectNoError,
- },
- {
- name: "non-rc-deleter, update, no ownerReferences change blockOwnerDeletion",
- username: "non-rc-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(nilBlockRC1),
- newObj: podWithOwnerRefs(notBlockRC1),
- checkError: expectNoError,
- },
- {
- name: "non-rc-deleter, update, some ownerReferences change from blockOwnerDeletion=false to true",
- username: "non-rc-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(notBlockRC1),
- newObj: podWithOwnerRefs(blockRC1),
- checkError: expectCantSetBlockOwnerDeletionError,
- },
- {
- name: "non-rc-deleter, update, some ownerReferences change from blockOwnerDeletion=nil to true",
- username: "non-rc-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(nilBlockRC1),
- newObj: podWithOwnerRefs(blockRC1),
- checkError: expectCantSetBlockOwnerDeletionError,
- },
- {
- name: "non-node-deleter, update, some ownerReferences change from blockOwnerDeletion=nil to true",
- username: "non-node-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(nilBlockNode),
- newObj: podWithOwnerRefs(blockNode),
- checkError: expectCantSetBlockOwnerDeletionError,
- },
- {
- name: "non-rc-deleter, update, some ownerReferences change from blockOwnerDeletion=true to false",
- username: "non-rc-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(blockRC1),
- newObj: podWithOwnerRefs(notBlockRC1),
- checkError: expectNoError,
- },
- {
- name: "non-node-deleter, update, some ownerReferences change from blockOwnerDeletion=true to false",
- username: "non-node-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(blockNode),
- newObj: podWithOwnerRefs(notBlockNode),
- checkError: expectNoError,
- },
- {
- name: "non-rc-deleter, update, some ownerReferences change blockOwnerDeletion, but all such references are to daemonset",
- username: "non-rc-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(notBlockDS1),
- newObj: podWithOwnerRefs(blockDS1),
- checkError: expectNoError,
- },
- {
- name: "non-rc-deleter, update, add new ownerReferences with blockOwnerDeletion=nil or false",
- username: "non-rc-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(),
- newObj: podWithOwnerRefs(notBlockRC1, nilBlockRC2),
- checkError: expectNoError,
- },
- {
- name: "non-rc-deleter, update, add new ownerReferences with blockOwnerDeletion=true",
- username: "non-rc-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(),
- newObj: podWithOwnerRefs(blockRC1),
- checkError: expectCantSetBlockOwnerDeletionError,
- },
- {
- name: "non-rc-deleter, update, add new ownerReferences with blockOwnerDeletion=true, but the references are to daemonset",
- username: "non-rc-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(),
- newObj: podWithOwnerRefs(blockDS1),
- checkError: expectNoError,
- },
- {
- name: "non-node-deleter, update, add ownerReferences with blockOwnerDeletion=true",
- username: "non-node-deleter",
- resource: api.SchemeGroupVersion.WithResource("pods"),
- oldObj: podWithOwnerRefs(),
- newObj: podWithOwnerRefs(blockNode),
- checkError: expectCantSetBlockOwnerDeletionError,
- },
- }
- gcAdmit, err := newGCPermissionsEnforcement()
- if err != nil {
- t.Error(err)
- }
- for _, tc := range tests {
- operation := admission.Create
- var options runtime.Object = &metav1.CreateOptions{}
- if tc.oldObj != nil {
- operation = admission.Update
- options = &metav1.UpdateOptions{}
- }
- user := &user.DefaultInfo{Name: tc.username}
- attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, options, false, user)
- err := gcAdmit.Validate(context.TODO(), attributes, nil)
- if !tc.checkError(err) {
- t.Errorf("%v: unexpected err: %v", tc.name, err)
- }
- }
- }
|