Unverified Commit 6fe7f9f4 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #66391 from jennybuckley/dry-run-admission

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>. Support dry run in admission plugins **What this PR does / why we need it**: Adds support for dry run to admission controllers as outlined by https://github.com/kubernetes/community/pull/2387 - [x] add IsDryRun() to admission.Attributes interface - [x] add dry run support to NamespaceAutoProvision - [x] add dry run support to ResourceQuota - [x] add dry run support to EventRateLimit The following is being done in a follow up PR: - [x] add DryRun to ```admission.k8s.io/v1beta1.AdmissionReview``` - [x] add DryRunnable to ```admissionregistration.k8s.io/v1beta1.(Valid|Mut)atingWebhookConfiguration``` - [x] add dry run support to (Valid|Mut)atingAdmissionWebhook /sig api-machinery **Release note**: ```release-note In clusters where the DryRun feature is enabled, dry-run requests will go through the normal admission chain. Because of this, ImagePolicyWebhook authors should especially make sure that their webhooks do not rely on side effects. ``` Here is a list of the admission controllers that were considered when making this PR: - AlwaysAdmit: No side effects - AlwaysPullImages: No side effects - LimitPodHardAntiAffinityTopology: No side effects - DefaultTolerationSeconds: No side effects - AlwaysDeny: No side effects - EventRateLimit: Has side possible effect of affecting the rate, skipping this entire plugin in dry-run case since it won't correspond to an actual write to etcd anyway - DenyEscalatingExec: No side effects - DenyExecOnPrivileged: Deprecated, and has no side effects - ExtendedResourceToleration: No side effects - OwnerReferencesPermissionEnforcement: No side effects - ImagePolicyWebhook: No side effects* (*this uses a webhook but it is very specialized. It only sees pod container images, for the purpose of accepting or rejecting certain image sources, so it is very unlikely that it would rely on side effects.) - LimitRanger: No side effects - NamespaceAutoProvision: Has possible side effect of creating a namespace, skipping the create in the dry-run case - NamespaceExists: No side effects - NodeRestriction: No side effects - PodNodeSelector: No side effects - PodPreset: No side effects - PodTolerationRestriction: No side effects - Priority: No side effects - ResourceQuota: Has side possible effect of taking up quota, will only check quota but skip changing quota in the dry-run case - PodSecurityPolicy: No side effects - SecurityContextDeny: No side effects - ServiceAccount: No side effects - PersistentVolumeLabel: No side effects - PersistentVolumeClaimResize: No side effects - DefaultStorageClass: No side effects - StorageObjectInUseProtection: No side effects - Initializers: No side effects - NamespaceLifecycle: No side effects - MutatingAdmissionWebhook: Same as below - ValidatingAdmissionWebhook: Has possible side effects depending on if webhook authors depend on side effects and a reconciliation mechanism. To fix this we will expose whether or not a request is dry-run to webhooks through AdmissionReview, and require that all called webhooks understand the field by checking if DryRunnable true is specified in the webhook config. This will be done in a separate PR because it requires an api-change
parents f04a7fa9 adafb136
...@@ -25,7 +25,7 @@ import ( ...@@ -25,7 +25,7 @@ import (
func TestAdmissionNonNilAttribute(t *testing.T) { func TestAdmissionNonNilAttribute(t *testing.T) {
handler := NewAlwaysAdmit() handler := NewAlwaysAdmit()
err := handler.(*alwaysAdmit).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, nil)) err := handler.(*alwaysAdmit).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, false, nil))
if err != nil { if err != nil {
t.Errorf("Unexpected error returned from admission handler") t.Errorf("Unexpected error returned from admission handler")
} }
......
...@@ -47,7 +47,7 @@ func TestAdmission(t *testing.T) { ...@@ -47,7 +47,7 @@ func TestAdmission(t *testing.T) {
}, },
}, },
} }
err := handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil)) err := handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
if err != nil { if err != nil {
t.Errorf("Unexpected error returned from admission handler") t.Errorf("Unexpected error returned from admission handler")
} }
...@@ -84,7 +84,7 @@ func TestValidate(t *testing.T) { ...@@ -84,7 +84,7 @@ func TestValidate(t *testing.T) {
}, },
} }
expectedError := `pods "123" is forbidden: spec.initContainers[0].imagePullPolicy: Unsupported value: "": supported values: "Always"` expectedError := `pods "123" is forbidden: spec.initContainers[0].imagePullPolicy: Unsupported value: "": supported values: "Always"`
err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil)) err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
if err == nil { if err == nil {
t.Fatal("missing expected error") t.Fatal("missing expected error")
} }
...@@ -139,7 +139,7 @@ func TestOtherResources(t *testing.T) { ...@@ -139,7 +139,7 @@ func TestOtherResources(t *testing.T) {
for _, tc := range tests { for _, tc := range tests {
handler := &AlwaysPullImages{} handler := &AlwaysPullImages{}
err := handler.Admit(admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, nil)) err := handler.Admit(admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, false, nil))
if tc.expectError { if tc.expectError {
if err == nil { if err == nil {
......
...@@ -199,7 +199,7 @@ func TestInterPodAffinityAdmission(t *testing.T) { ...@@ -199,7 +199,7 @@ func TestInterPodAffinityAdmission(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
pod.Spec.Affinity = test.affinity pod.Spec.Affinity = test.affinity
err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil)) err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil))
if test.errorExpected && err == nil { if test.errorExpected && err == nil {
t.Errorf("Expected error for Anti Affinity %+v but did not get an error", test.affinity) t.Errorf("Expected error for Anti Affinity %+v but did not get an error", test.affinity)
...@@ -267,7 +267,7 @@ func TestOtherResources(t *testing.T) { ...@@ -267,7 +267,7 @@ func TestOtherResources(t *testing.T) {
for _, tc := range tests { for _, tc := range tests {
handler := &Plugin{} handler := &Plugin{}
err := handler.Validate(admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, nil)) err := handler.Validate(admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, false, nil))
if tc.expectError { if tc.expectError {
if err == nil { if err == nil {
......
...@@ -395,7 +395,7 @@ func TestForgivenessAdmission(t *testing.T) { ...@@ -395,7 +395,7 @@ func TestForgivenessAdmission(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
err := handler.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil)) err := handler.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil))
if err != nil { if err != nil {
t.Errorf("[%s]: unexpected error %v for pod %+v", test.description, err, test.requestedPod) t.Errorf("[%s]: unexpected error %v for pod %+v", test.description, err, test.requestedPod)
} }
......
...@@ -25,7 +25,7 @@ import ( ...@@ -25,7 +25,7 @@ import (
func TestAdmission(t *testing.T) { func TestAdmission(t *testing.T) {
handler := NewAlwaysDeny() handler := NewAlwaysDeny()
err := handler.(*alwaysDeny).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, nil)) err := handler.(*alwaysDeny).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, false, nil))
if err == nil { if err == nil {
t.Error("Expected error returned from admission handler") t.Error("Expected error returned from admission handler")
} }
......
...@@ -87,6 +87,13 @@ func (a *Plugin) Validate(attr admission.Attributes) (err error) { ...@@ -87,6 +87,13 @@ func (a *Plugin) Validate(attr admission.Attributes) (err error) {
return nil return nil
} }
// ignore all requests that specify dry-run
// because they don't correspond to any calls to etcd,
// they should not be affected by the ratelimit
if attr.IsDryRun() {
return nil
}
var errors []error var errors []error
// give each limit enforcer a chance to reject the event // give each limit enforcer a chance to reject the event
for _, enforcer := range a.limitEnforcers { for _, enforcer := range a.limitEnforcers {
......
...@@ -46,6 +46,7 @@ func attributesForRequest(rq request) admission.Attributes { ...@@ -46,6 +46,7 @@ func attributesForRequest(rq request) admission.Attributes {
api.Resource("resource").WithVersion("version"), api.Resource("resource").WithVersion("version"),
"", "",
admission.Create, admission.Create,
rq.dryRun,
&user.DefaultInfo{Name: rq.username}) &user.DefaultInfo{Name: rq.username})
} }
...@@ -56,6 +57,7 @@ type request struct { ...@@ -56,6 +57,7 @@ type request struct {
event *api.Event event *api.Event
delay time.Duration delay time.Duration
accepted bool accepted bool
dryRun bool
} }
func newRequest(kind string) request { func newRequest(kind string) request {
...@@ -91,6 +93,11 @@ func (r request) withEventComponent(component string) request { ...@@ -91,6 +93,11 @@ func (r request) withEventComponent(component string) request {
}) })
} }
func (r request) withDryRun(dryRun bool) request {
r.dryRun = dryRun
return r
}
func (r request) withUser(name string) request { func (r request) withUser(name string) request {
r.username = name r.username = name
return r return r
...@@ -154,6 +161,21 @@ func TestEventRateLimiting(t *testing.T) { ...@@ -154,6 +161,21 @@ func TestEventRateLimiting(t *testing.T) {
}, },
}, },
{ {
name: "event not blocked by dry-run requests",
serverBurst: 3,
requests: []request{
newEventRequest(),
newEventRequest(),
newEventRequest().withDryRun(true),
newEventRequest().withDryRun(true),
newEventRequest().withDryRun(true),
newEventRequest().withDryRun(true),
newEventRequest(),
newEventRequest().blocked(),
newEventRequest().withDryRun(true),
},
},
{
name: "non-event not blocked after tokens exhausted", name: "non-event not blocked after tokens exhausted",
serverBurst: 3, serverBurst: 3,
requests: []request{ requests: []request{
......
...@@ -123,7 +123,7 @@ func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept b ...@@ -123,7 +123,7 @@ func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept b
// pods/exec // pods/exec
{ {
req := &rest.ConnectRequest{Name: pod.Name, ResourcePath: "pods/exec"} req := &rest.ConnectRequest{Name: pod.Name, ResourcePath: "pods/exec"}
err := handler.Validate(admission.NewAttributesRecord(req, nil, api.Kind("Pod").WithVersion("version"), "test", "name", api.Resource("pods").WithVersion("version"), "exec", admission.Connect, nil)) err := handler.Validate(admission.NewAttributesRecord(req, nil, api.Kind("Pod").WithVersion("version"), "test", "name", api.Resource("pods").WithVersion("version"), "exec", admission.Connect, false, nil))
if shouldAccept && err != nil { if shouldAccept && err != nil {
t.Errorf("Unexpected error returned from admission handler: %v", err) t.Errorf("Unexpected error returned from admission handler: %v", err)
} }
...@@ -135,7 +135,7 @@ func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept b ...@@ -135,7 +135,7 @@ func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept b
// pods/attach // pods/attach
{ {
req := &rest.ConnectRequest{Name: pod.Name, ResourcePath: "pods/attach"} req := &rest.ConnectRequest{Name: pod.Name, ResourcePath: "pods/attach"}
err := handler.Validate(admission.NewAttributesRecord(req, nil, api.Kind("Pod").WithVersion("version"), "test", "name", api.Resource("pods").WithVersion("version"), "attach", admission.Connect, nil)) err := handler.Validate(admission.NewAttributesRecord(req, nil, api.Kind("Pod").WithVersion("version"), "test", "name", api.Resource("pods").WithVersion("version"), "attach", admission.Connect, false, nil))
if shouldAccept && err != nil { if shouldAccept && err != nil {
t.Errorf("Unexpected error returned from admission handler: %v", err) t.Errorf("Unexpected error returned from admission handler: %v", err)
} }
......
...@@ -354,7 +354,7 @@ func TestAdmit(t *testing.T) { ...@@ -354,7 +354,7 @@ func TestAdmit(t *testing.T) {
}, },
} }
for i, test := range tests { for i, test := range tests {
err := plugin.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, core.Kind("Pod").WithVersion("version"), "foo", "name", core.Resource("pods").WithVersion("version"), "", "ignored", nil)) err := plugin.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, core.Kind("Pod").WithVersion("version"), "foo", "name", core.Resource("pods").WithVersion("version"), "", "ignored", false, nil))
if err != nil { if err != nil {
t.Errorf("[%d: %s] unexpected error %v for pod %+v", i, test.description, err, test.requestedPod) t.Errorf("[%d: %s] unexpected error %v for pod %+v", i, test.description, err, test.requestedPod)
} }
......
...@@ -270,7 +270,7 @@ func TestGCAdmission(t *testing.T) { ...@@ -270,7 +270,7 @@ func TestGCAdmission(t *testing.T) {
operation = admission.Update operation = admission.Update
} }
user := &user.DefaultInfo{Name: tc.username} user := &user.DefaultInfo{Name: tc.username}
attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, user) attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, false, user)
err = gcAdmit.Validate(attributes) err = gcAdmit.Validate(attributes)
if !tc.checkError(err) { if !tc.checkError(err) {
...@@ -518,7 +518,7 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) { ...@@ -518,7 +518,7 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) {
operation = admission.Update operation = admission.Update
} }
user := &user.DefaultInfo{Name: tc.username} user := &user.DefaultInfo{Name: tc.username}
attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, user) attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, false, user)
err := gcAdmit.Validate(attributes) err := gcAdmit.Validate(attributes)
if !tc.checkError(err) { if !tc.checkError(err) {
......
...@@ -472,7 +472,7 @@ func TestTLSConfig(t *testing.T) { ...@@ -472,7 +472,7 @@ func TestTLSConfig(t *testing.T) {
return return
} }
pod := goodPod(strconv.Itoa(rand.Intn(1000))) pod := goodPod(strconv.Itoa(rand.Intn(1000)))
attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &user.DefaultInfo{}) attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{})
// Allow all and see if we get an error. // Allow all and see if we get an error.
service.Allow() service.Allow()
...@@ -561,7 +561,7 @@ func TestWebhookCache(t *testing.T) { ...@@ -561,7 +561,7 @@ func TestWebhookCache(t *testing.T) {
{statusCode: 500, expectedErr: false, expectedAuthorized: true, expectedCached: true}, {statusCode: 500, expectedErr: false, expectedAuthorized: true, expectedCached: true},
} }
attr := admission.NewAttributesRecord(goodPod("test"), nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &user.DefaultInfo{}) attr := admission.NewAttributesRecord(goodPod("test"), nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{})
serv.allow = true serv.allow = true
...@@ -573,7 +573,7 @@ func TestWebhookCache(t *testing.T) { ...@@ -573,7 +573,7 @@ func TestWebhookCache(t *testing.T) {
{statusCode: 200, expectedErr: false, expectedAuthorized: true, expectedCached: false}, {statusCode: 200, expectedErr: false, expectedAuthorized: true, expectedCached: false},
{statusCode: 500, expectedErr: false, expectedAuthorized: true, expectedCached: true}, {statusCode: 500, expectedErr: false, expectedAuthorized: true, expectedCached: true},
} }
attr = admission.NewAttributesRecord(goodPod("test2"), nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &user.DefaultInfo{}) attr = admission.NewAttributesRecord(goodPod("test2"), nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{})
testWebhookCacheCases(t, serv, wh, attr, tests) testWebhookCacheCases(t, serv, wh, attr, tests)
} }
...@@ -747,7 +747,7 @@ func TestContainerCombinations(t *testing.T) { ...@@ -747,7 +747,7 @@ func TestContainerCombinations(t *testing.T) {
return return
} }
attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &user.DefaultInfo{}) attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{})
err = wh.Validate(attr) err = wh.Validate(attr)
if tt.wantAllowed { if tt.wantAllowed {
...@@ -825,7 +825,7 @@ func TestDefaultAllow(t *testing.T) { ...@@ -825,7 +825,7 @@ func TestDefaultAllow(t *testing.T) {
return return
} }
attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &user.DefaultInfo{}) attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{})
err = wh.Validate(attr) err = wh.Validate(attr)
if tt.wantAllowed { if tt.wantAllowed {
...@@ -917,7 +917,7 @@ func TestAnnotationFiltering(t *testing.T) { ...@@ -917,7 +917,7 @@ func TestAnnotationFiltering(t *testing.T) {
pod := goodPod("test") pod := goodPod("test")
pod.Annotations = tt.annotations pod.Annotations = tt.annotations
attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &user.DefaultInfo{}) attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{})
err = wh.Validate(attr) err = wh.Validate(attr)
if err != nil { if err != nil {
......
...@@ -694,16 +694,16 @@ func TestLimitRangerIgnoresSubresource(t *testing.T) { ...@@ -694,16 +694,16 @@ func TestLimitRangerIgnoresSubresource(t *testing.T) {
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
testPod := validPod("testPod", 1, api.ResourceRequirements{}) testPod := validPod("testPod", 1, api.ResourceRequirements{})
err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, nil)) err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, nil)) err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
if err == nil { if err == nil {
t.Errorf("Expected an error since the pod did not specify resource limits in its update call") t.Errorf("Expected an error since the pod did not specify resource limits in its update call")
} }
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "status", admission.Update, nil)) err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "status", admission.Update, false, nil))
if err != nil { if err != nil {
t.Errorf("Should have ignored calls to any subresource of pod %v", err) t.Errorf("Should have ignored calls to any subresource of pod %v", err)
} }
...@@ -720,16 +720,16 @@ func TestLimitRangerAdmitPod(t *testing.T) { ...@@ -720,16 +720,16 @@ func TestLimitRangerAdmitPod(t *testing.T) {
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
testPod := validPod("testPod", 1, api.ResourceRequirements{}) testPod := validPod("testPod", 1, api.ResourceRequirements{})
err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, nil)) err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, nil)) err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
if err == nil { if err == nil {
t.Errorf("Expected an error since the pod did not specify resource limits in its update call") t.Errorf("Expected an error since the pod did not specify resource limits in its update call")
} }
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "status", admission.Update, nil)) err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "status", admission.Update, false, nil))
if err != nil { if err != nil {
t.Errorf("Should have ignored calls to any subresource of pod %v", err) t.Errorf("Should have ignored calls to any subresource of pod %v", err)
} }
...@@ -738,7 +738,7 @@ func TestLimitRangerAdmitPod(t *testing.T) { ...@@ -738,7 +738,7 @@ func TestLimitRangerAdmitPod(t *testing.T) {
terminatingPod := validPod("terminatingPod", 1, api.ResourceRequirements{}) terminatingPod := validPod("terminatingPod", 1, api.ResourceRequirements{})
now := metav1.Now() now := metav1.Now()
terminatingPod.DeletionTimestamp = &now terminatingPod.DeletionTimestamp = &now
err = handler.Validate(admission.NewAttributesRecord(&terminatingPod, &terminatingPod, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "terminatingPod", api.Resource("pods").WithVersion("version"), "", admission.Update, nil)) err = handler.Validate(admission.NewAttributesRecord(&terminatingPod, &terminatingPod, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "terminatingPod", api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
if err != nil { if err != nil {
t.Errorf("LimitRange should ignore a pod marked for termination") t.Errorf("LimitRange should ignore a pod marked for termination")
} }
......
...@@ -55,6 +55,11 @@ var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&Provision{}) ...@@ -55,6 +55,11 @@ var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&Provision{})
// Admit makes an admission decision based on the request attributes // Admit makes an admission decision based on the request attributes
func (p *Provision) Admit(a admission.Attributes) error { func (p *Provision) Admit(a admission.Attributes) error {
// Don't create a namespace if the request is for a dry-run.
if a.IsDryRun() {
return nil
}
// if we're here, then we've already passed authentication, so we're allowed to do what we're trying to do // if we're here, then we've already passed authentication, so we're allowed to do what we're trying to do
// if we're here, then the API server has found a route, which means that if we have a non-empty namespace // if we're here, then the API server has found a route, which means that if we have a non-empty namespace
// its a namespaced resource. // its a namespaced resource.
......
...@@ -98,7 +98,7 @@ func TestAdmission(t *testing.T) { ...@@ -98,7 +98,7 @@ func TestAdmission(t *testing.T) {
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
pod := newPod(namespace) pod := newPod(namespace)
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil)) err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
if err != nil { if err != nil {
t.Errorf("unexpected error returned from admission handler") t.Errorf("unexpected error returned from admission handler")
} }
...@@ -118,7 +118,27 @@ func TestAdmissionNamespaceExists(t *testing.T) { ...@@ -118,7 +118,27 @@ func TestAdmissionNamespaceExists(t *testing.T) {
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
pod := newPod(namespace) pod := newPod(namespace)
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil)) err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
if err != nil {
t.Errorf("unexpected error returned from admission handler")
}
if hasCreateNamespaceAction(mockClient) {
t.Errorf("unexpected create namespace action")
}
}
// TestAdmissionDryRun verifies that no client call is made on a dry run request
func TestAdmissionDryRun(t *testing.T) {
namespace := "test"
mockClient := newMockClientForTest([]string{})
handler, informerFactory, err := newHandlerForTest(mockClient)
if err != nil {
t.Errorf("unexpected error initializing handler: %v", err)
}
informerFactory.Start(wait.NeverStop)
pod := newPod(namespace)
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, true, nil))
if err != nil { if err != nil {
t.Errorf("unexpected error returned from admission handler") t.Errorf("unexpected error returned from admission handler")
} }
...@@ -139,7 +159,7 @@ func TestIgnoreAdmission(t *testing.T) { ...@@ -139,7 +159,7 @@ func TestIgnoreAdmission(t *testing.T) {
chainHandler := admission.NewChainHandler(handler) chainHandler := admission.NewChainHandler(handler)
pod := newPod(namespace) pod := newPod(namespace)
err = chainHandler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, nil)) err = chainHandler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
if err != nil { if err != nil {
t.Errorf("unexpected error returned from admission handler") t.Errorf("unexpected error returned from admission handler")
} }
...@@ -161,7 +181,7 @@ func TestAdmissionWithLatentCache(t *testing.T) { ...@@ -161,7 +181,7 @@ func TestAdmissionWithLatentCache(t *testing.T) {
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
pod := newPod(namespace) pod := newPod(namespace)
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil)) err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
if err != nil { if err != nil {
t.Errorf("unexpected error returned from admission handler") t.Errorf("unexpected error returned from admission handler")
} }
......
...@@ -87,7 +87,7 @@ func TestAdmissionNamespaceExists(t *testing.T) { ...@@ -87,7 +87,7 @@ func TestAdmissionNamespaceExists(t *testing.T) {
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
pod := newPod(namespace) pod := newPod(namespace)
err = handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil)) err = handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
if err != nil { if err != nil {
t.Errorf("unexpected error returned from admission handler") t.Errorf("unexpected error returned from admission handler")
} }
...@@ -107,7 +107,7 @@ func TestAdmissionNamespaceDoesNotExist(t *testing.T) { ...@@ -107,7 +107,7 @@ func TestAdmissionNamespaceDoesNotExist(t *testing.T) {
informerFactory.Start(wait.NeverStop) informerFactory.Start(wait.NeverStop)
pod := newPod(namespace) pod := newPod(namespace)
err = handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil)) err = handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
if err == nil { if err == nil {
actions := "" actions := ""
for _, action := range mockClient.Actions() { for _, action := range mockClient.Actions() {
......
...@@ -166,7 +166,7 @@ func TestPodAdmission(t *testing.T) { ...@@ -166,7 +166,7 @@ func TestPodAdmission(t *testing.T) {
handler.clusterNodeSelectors[namespace.Name] = test.whitelist handler.clusterNodeSelectors[namespace.Name] = test.whitelist
pod.Spec = api.PodSpec{NodeSelector: test.podNodeSelector} pod.Spec = api.PodSpec{NodeSelector: test.podNodeSelector}
err := handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, 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 { if test.admit && err != nil {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil { } else if !test.admit && err == nil {
...@@ -175,7 +175,7 @@ func TestPodAdmission(t *testing.T) { ...@@ -175,7 +175,7 @@ func TestPodAdmission(t *testing.T) {
if test.admit && !labels.Equals(test.mergedNodeSelector, labels.Set(pod.Spec.NodeSelector)) { 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) t.Errorf("Test: %s, expected: %s but got: %s", test.testName, test.mergedNodeSelector, pod.Spec.NodeSelector)
} }
err = handler.Validate(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil)) err = handler.Validate(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 { if test.admit && err != nil {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil { } else if !test.admit && err == nil {
...@@ -183,7 +183,7 @@ func TestPodAdmission(t *testing.T) { ...@@ -183,7 +183,7 @@ func TestPodAdmission(t *testing.T) {
} }
// handles update of uninitialized pod like it's newly created. // 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, nil)) 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 { if test.admit && err != nil {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil { } else if !test.admit && err == nil {
...@@ -192,7 +192,7 @@ func TestPodAdmission(t *testing.T) { ...@@ -192,7 +192,7 @@ func TestPodAdmission(t *testing.T) {
if test.admit && !labels.Equals(test.mergedNodeSelector, labels.Set(pod.Spec.NodeSelector)) { 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) 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, nil)) 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 { if test.admit && err != nil {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil { } else if !test.admit && err == nil {
...@@ -243,7 +243,7 @@ func TestIgnoreUpdatingInitializedPod(t *testing.T) { ...@@ -243,7 +243,7 @@ func TestIgnoreUpdatingInitializedPod(t *testing.T) {
} }
// if the update of initialized pod is not ignored, an error will be returned because the pod's nodeSelector conflicts with namespace's nodeSelector. // 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, nil)) 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 { if err != nil {
t.Errorf("expected no error, got: %v", err) t.Errorf("expected no error, got: %v", err)
} }
......
...@@ -818,6 +818,7 @@ func admitPod(pod *api.Pod, pip *settings.PodPreset) error { ...@@ -818,6 +818,7 @@ func admitPod(pod *api.Pod, pip *settings.PodPreset) error {
api.Resource("pods").WithVersion("version"), api.Resource("pods").WithVersion("version"),
"", "",
kadmission.Create, kadmission.Create,
false,
&user.DefaultInfo{}, &user.DefaultInfo{},
) )
......
...@@ -258,7 +258,7 @@ func TestPodAdmission(t *testing.T) { ...@@ -258,7 +258,7 @@ func TestPodAdmission(t *testing.T) {
oldPod.Initializers = &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init"}}} oldPod.Initializers = &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init"}}}
oldPod.Spec.Tolerations = []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}} 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, 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 { if test.admit && err != nil {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil { } else if !test.admit && err == nil {
...@@ -271,7 +271,7 @@ func TestPodAdmission(t *testing.T) { ...@@ -271,7 +271,7 @@ func TestPodAdmission(t *testing.T) {
} }
// handles update of uninitialized pod like it's newly created. // 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, nil)) 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 { if test.admit && err != nil {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err) t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil { } else if !test.admit && err == nil {
...@@ -348,7 +348,7 @@ func TestIgnoreUpdatingInitializedPod(t *testing.T) { ...@@ -348,7 +348,7 @@ func TestIgnoreUpdatingInitializedPod(t *testing.T) {
} }
// if the update of initialized pod is not ignored, an error will be returned because the pod's Tolerations conflicts with namespace's Tolerations. // if the update of initialized pod is not ignored, an error will be returned because the pod's Tolerations conflicts with namespace's Tolerations.
err = handler.Admit(admission.NewAttributesRecord(pod, pod, api.Kind("Pod").WithVersion("version"), "testNamespace", pod.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, nil)) err = handler.Admit(admission.NewAttributesRecord(pod, pod, api.Kind("Pod").WithVersion("version"), "testNamespace", pod.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
if err != nil { if err != nil {
t.Errorf("expected no error, got: %v", err) t.Errorf("expected no error, got: %v", err)
} }
......
...@@ -146,6 +146,7 @@ func TestPriorityClassAdmission(t *testing.T) { ...@@ -146,6 +146,7 @@ func TestPriorityClassAdmission(t *testing.T) {
scheduling.Resource("priorityclasses").WithVersion("version"), scheduling.Resource("priorityclasses").WithVersion("version"),
"", "",
admission.Create, admission.Create,
false,
test.userInfo, test.userInfo,
) )
err := ctrl.Validate(attrs) err := ctrl.Validate(attrs)
...@@ -186,7 +187,7 @@ func TestDefaultPriority(t *testing.T) { ...@@ -186,7 +187,7 @@ func TestDefaultPriority(t *testing.T) {
name: "add a default class", name: "add a default class",
classesBefore: []*scheduling.PriorityClass{nondefaultClass1}, classesBefore: []*scheduling.PriorityClass{nondefaultClass1},
classesAfter: []*scheduling.PriorityClass{nondefaultClass1, defaultClass1}, classesAfter: []*scheduling.PriorityClass{nondefaultClass1, defaultClass1},
attributes: admission.NewAttributesRecord(defaultClass1, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Create, nil), attributes: admission.NewAttributesRecord(defaultClass1, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Create, false, nil),
expectedDefaultBefore: scheduling.DefaultPriorityWhenNoDefaultClassExists, expectedDefaultBefore: scheduling.DefaultPriorityWhenNoDefaultClassExists,
expectedDefaultAfter: defaultClass1.Value, expectedDefaultAfter: defaultClass1.Value,
}, },
...@@ -194,7 +195,7 @@ func TestDefaultPriority(t *testing.T) { ...@@ -194,7 +195,7 @@ func TestDefaultPriority(t *testing.T) {
name: "multiple default classes resolves to the minimum value among them", name: "multiple default classes resolves to the minimum value among them",
classesBefore: []*scheduling.PriorityClass{defaultClass1, defaultClass2}, classesBefore: []*scheduling.PriorityClass{defaultClass1, defaultClass2},
classesAfter: []*scheduling.PriorityClass{defaultClass2}, classesAfter: []*scheduling.PriorityClass{defaultClass2},
attributes: admission.NewAttributesRecord(nil, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Delete, nil), attributes: admission.NewAttributesRecord(nil, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Delete, false, nil),
expectedDefaultBefore: defaultClass1.Value, expectedDefaultBefore: defaultClass1.Value,
expectedDefaultAfter: defaultClass2.Value, expectedDefaultAfter: defaultClass2.Value,
}, },
...@@ -202,7 +203,7 @@ func TestDefaultPriority(t *testing.T) { ...@@ -202,7 +203,7 @@ func TestDefaultPriority(t *testing.T) {
name: "delete default priority class", name: "delete default priority class",
classesBefore: []*scheduling.PriorityClass{defaultClass1}, classesBefore: []*scheduling.PriorityClass{defaultClass1},
classesAfter: []*scheduling.PriorityClass{}, classesAfter: []*scheduling.PriorityClass{},
attributes: admission.NewAttributesRecord(nil, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Delete, nil), attributes: admission.NewAttributesRecord(nil, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Delete, false, nil),
expectedDefaultBefore: defaultClass1.Value, expectedDefaultBefore: defaultClass1.Value,
expectedDefaultAfter: scheduling.DefaultPriorityWhenNoDefaultClassExists, expectedDefaultAfter: scheduling.DefaultPriorityWhenNoDefaultClassExists,
}, },
...@@ -210,7 +211,7 @@ func TestDefaultPriority(t *testing.T) { ...@@ -210,7 +211,7 @@ func TestDefaultPriority(t *testing.T) {
name: "update default class and remove its global default", name: "update default class and remove its global default",
classesBefore: []*scheduling.PriorityClass{defaultClass1}, classesBefore: []*scheduling.PriorityClass{defaultClass1},
classesAfter: []*scheduling.PriorityClass{&updatedDefaultClass1}, classesAfter: []*scheduling.PriorityClass{&updatedDefaultClass1},
attributes: admission.NewAttributesRecord(&updatedDefaultClass1, defaultClass1, pcKind, "", defaultClass1.Name, pcResource, "", admission.Update, nil), attributes: admission.NewAttributesRecord(&updatedDefaultClass1, defaultClass1, pcKind, "", defaultClass1.Name, pcResource, "", admission.Update, false, nil),
expectedDefaultBefore: defaultClass1.Value, expectedDefaultBefore: defaultClass1.Value,
expectedDefaultAfter: scheduling.DefaultPriorityWhenNoDefaultClassExists, expectedDefaultAfter: scheduling.DefaultPriorityWhenNoDefaultClassExists,
}, },
...@@ -568,6 +569,7 @@ func TestPodAdmission(t *testing.T) { ...@@ -568,6 +569,7 @@ func TestPodAdmission(t *testing.T) {
api.Resource("pods").WithVersion("version"), api.Resource("pods").WithVersion("version"),
"", "",
admission.Create, admission.Create,
false,
nil, nil,
) )
err := ctrl.Admit(attrs) err := ctrl.Admit(attrs)
......
...@@ -231,6 +231,12 @@ func (e *quotaEvaluator) checkQuotas(quotas []api.ResourceQuota, admissionAttrib ...@@ -231,6 +231,12 @@ func (e *quotaEvaluator) checkQuotas(quotas []api.ResourceQuota, admissionAttrib
continue continue
} }
// Don't update quota for admissionAttributes that correspond to dry-run requests
if admissionAttribute.attributes.IsDryRun() {
admissionAttribute.result = nil
continue
}
// if the new quotas are the same as the old quotas, then this particular one doesn't issue any updates // if the new quotas are the same as the old quotas, then this particular one doesn't issue any updates
// that means that no quota docs applied, so it can get a pass // that means that no quota docs applied, so it can get a pass
atLeastOneChangeForThisWaiter := false atLeastOneChangeForThisWaiter := false
......
...@@ -472,7 +472,7 @@ func TestAdmitPreferNonmutating(t *testing.T) { ...@@ -472,7 +472,7 @@ func TestAdmitPreferNonmutating(t *testing.T) {
func TestFailClosedOnInvalidPod(t *testing.T) { func TestFailClosedOnInvalidPod(t *testing.T) {
plugin := NewTestAdmission(nil, nil) plugin := NewTestAdmission(nil, nil)
pod := &v1.Pod{} pod := &v1.Pod{}
attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, &user.DefaultInfo{}) attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, false, &user.DefaultInfo{})
err := plugin.Admit(attrs) err := plugin.Admit(attrs)
if err == nil { if err == nil {
...@@ -1769,7 +1769,7 @@ func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []* ...@@ -1769,7 +1769,7 @@ func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []*
originalPod := pod.DeepCopy() originalPod := pod.DeepCopy()
plugin := NewTestAdmission(psps, authz) plugin := NewTestAdmission(psps, authz)
attrs := kadmission.NewAttributesRecord(pod, oldPod, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, "", kapi.Resource("pods").WithVersion("version"), "", op, userInfo) attrs := kadmission.NewAttributesRecord(pod, oldPod, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, "", kapi.Resource("pods").WithVersion("version"), "", op, false, userInfo)
annotations := make(map[string]string) annotations := make(map[string]string)
attrs = &fakeAttributes{attrs, annotations} attrs = &fakeAttributes{attrs, annotations}
err := plugin.Admit(attrs) err := plugin.Admit(attrs)
...@@ -2227,7 +2227,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) { ...@@ -2227,7 +2227,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) {
pod.Spec.SecurityContext.HostPID = true pod.Spec.SecurityContext.HostPID = true
plugin := NewTestAdmission(tc.inPolicies, authz) plugin := NewTestAdmission(tc.inPolicies, authz)
attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), ns, "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, &user.DefaultInfo{Name: userName}) attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), ns, "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, false, &user.DefaultInfo{Name: userName})
allowedPod, _, validationErrs, err := plugin.computeSecurityContext(attrs, pod, true, "") allowedPod, _, validationErrs, err := plugin.computeSecurityContext(attrs, pod, true, "")
assert.Nil(t, allowedPod) assert.Nil(t, allowedPod)
...@@ -2320,7 +2320,7 @@ func TestPreferValidatedPSP(t *testing.T) { ...@@ -2320,7 +2320,7 @@ func TestPreferValidatedPSP(t *testing.T) {
pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = &allowPrivilegeEscalation pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = &allowPrivilegeEscalation
plugin := NewTestAdmission(tc.inPolicies, authz) plugin := NewTestAdmission(tc.inPolicies, authz)
attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), "ns", "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Update, &user.DefaultInfo{Name: "test"}) attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), "ns", "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Update, false, &user.DefaultInfo{Name: "test"})
_, pspName, validationErrs, err := plugin.computeSecurityContext(attrs, pod, false, tc.validatedPSPHint) _, pspName, validationErrs, err := plugin.computeSecurityContext(attrs, pod, false, tc.validatedPSPHint)
assert.NoError(t, err) assert.NoError(t, err)
......
...@@ -82,7 +82,7 @@ func TestAdmission(t *testing.T) { ...@@ -82,7 +82,7 @@ func TestAdmission(t *testing.T) {
p.Spec.SecurityContext = tc.podSc p.Spec.SecurityContext = tc.podSc
p.Spec.Containers[0].SecurityContext = tc.sc p.Spec.Containers[0].SecurityContext = tc.sc
err := handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil)) err := handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil))
if err != nil && !tc.expectError { if err != nil && !tc.expectError {
t.Errorf("%v: unexpected error: %v", tc.name, err) t.Errorf("%v: unexpected error: %v", tc.name, err)
} else if err == nil && tc.expectError { } else if err == nil && tc.expectError {
...@@ -96,7 +96,7 @@ func TestAdmission(t *testing.T) { ...@@ -96,7 +96,7 @@ func TestAdmission(t *testing.T) {
p.Spec.InitContainers = p.Spec.Containers p.Spec.InitContainers = p.Spec.Containers
p.Spec.Containers = nil p.Spec.Containers = nil
err = handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil)) err = handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil))
if err != nil && !tc.expectError { if err != nil && !tc.expectError {
t.Errorf("%v: unexpected error: %v", tc.name, err) t.Errorf("%v: unexpected error: %v", tc.name, err)
} else if err == nil && tc.expectError { } else if err == nil && tc.expectError {
...@@ -140,7 +140,7 @@ func TestPodSecurityContextAdmission(t *testing.T) { ...@@ -140,7 +140,7 @@ func TestPodSecurityContextAdmission(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
pod.Spec.SecurityContext = &test.securityContext pod.Spec.SecurityContext = &test.securityContext
err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil)) err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil))
if test.errorExpected && err == nil { if test.errorExpected && err == nil {
t.Errorf("Expected error for security context %+v but did not get an error", test.securityContext) t.Errorf("Expected error for security context %+v but did not get an error", test.securityContext)
......
...@@ -126,20 +126,20 @@ func TestAdmission(t *testing.T) { ...@@ -126,20 +126,20 @@ func TestAdmission(t *testing.T) {
defer utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false") defer utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false")
// Non-cloud PVs are ignored // Non-cloud PVs are ignored
err := handler.Admit(admission.NewAttributesRecord(&ignoredPV, nil, api.Kind("PersistentVolume").WithVersion("version"), ignoredPV.Namespace, ignoredPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) err := handler.Admit(admission.NewAttributesRecord(&ignoredPV, nil, api.Kind("PersistentVolume").WithVersion("version"), ignoredPV.Namespace, ignoredPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, false, nil))
if err != nil { if err != nil {
t.Errorf("Unexpected error returned from admission handler (on ignored pv): %v", err) t.Errorf("Unexpected error returned from admission handler (on ignored pv): %v", err)
} }
// We only add labels on creation // We only add labels on creation
err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Delete, nil)) err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Delete, false, nil))
if err != nil { if err != nil {
t.Errorf("Unexpected error returned from admission handler (when deleting aws pv): %v", err) t.Errorf("Unexpected error returned from admission handler (when deleting aws pv): %v", err)
} }
// Errors from the cloudprovider block creation of the volume // Errors from the cloudprovider block creation of the volume
pvHandler.ebsVolumes = mockVolumeFailure(fmt.Errorf("invalid volume")) pvHandler.ebsVolumes = mockVolumeFailure(fmt.Errorf("invalid volume"))
err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, false, nil))
if err == nil { if err == nil {
t.Errorf("Expected error when aws pv info fails") t.Errorf("Expected error when aws pv info fails")
} }
...@@ -147,7 +147,7 @@ func TestAdmission(t *testing.T) { ...@@ -147,7 +147,7 @@ func TestAdmission(t *testing.T) {
// Don't add labels if the cloudprovider doesn't return any // Don't add labels if the cloudprovider doesn't return any
labels := make(map[string]string) labels := make(map[string]string)
pvHandler.ebsVolumes = mockVolumeLabels(labels) pvHandler.ebsVolumes = mockVolumeLabels(labels)
err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, false, nil))
if err != nil { if err != nil {
t.Errorf("Expected no error when creating aws pv") t.Errorf("Expected no error when creating aws pv")
} }
...@@ -160,7 +160,7 @@ func TestAdmission(t *testing.T) { ...@@ -160,7 +160,7 @@ func TestAdmission(t *testing.T) {
// Don't panic if the cloudprovider returns nil, nil // Don't panic if the cloudprovider returns nil, nil
pvHandler.ebsVolumes = mockVolumeFailure(nil) pvHandler.ebsVolumes = mockVolumeFailure(nil)
err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, false, nil))
if err != nil { if err != nil {
t.Errorf("Expected no error when cloud provider returns empty labels") t.Errorf("Expected no error when cloud provider returns empty labels")
} }
...@@ -172,7 +172,7 @@ func TestAdmission(t *testing.T) { ...@@ -172,7 +172,7 @@ func TestAdmission(t *testing.T) {
zones, _ := volumeutil.ZonesToSet("1,2,3") zones, _ := volumeutil.ZonesToSet("1,2,3")
labels[kubeletapis.LabelZoneFailureDomain] = volumeutil.ZonesSetToLabelValue(zones) labels[kubeletapis.LabelZoneFailureDomain] = volumeutil.ZonesSetToLabelValue(zones)
pvHandler.ebsVolumes = mockVolumeLabels(labels) pvHandler.ebsVolumes = mockVolumeLabels(labels)
err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, false, nil))
if err != nil { if err != nil {
t.Errorf("Expected no error when creating aws pv") t.Errorf("Expected no error when creating aws pv")
} }
...@@ -210,7 +210,7 @@ func TestAdmission(t *testing.T) { ...@@ -210,7 +210,7 @@ func TestAdmission(t *testing.T) {
awsPV.ObjectMeta.Labels = make(map[string]string) awsPV.ObjectMeta.Labels = make(map[string]string)
awsPV.ObjectMeta.Labels["a"] = "not1" awsPV.ObjectMeta.Labels["a"] = "not1"
awsPV.ObjectMeta.Labels["c"] = "3" awsPV.ObjectMeta.Labels["c"] = "3"
err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, false, nil))
if err != nil { if err != nil {
t.Errorf("Expected no error when creating aws pv") t.Errorf("Expected no error when creating aws pv")
} }
...@@ -227,7 +227,7 @@ func TestAdmission(t *testing.T) { ...@@ -227,7 +227,7 @@ func TestAdmission(t *testing.T) {
labels["b"] = "2" labels["b"] = "2"
labels["c"] = "3" labels["c"] = "3"
pvHandler.ebsVolumes = mockVolumeLabels(labels) pvHandler.ebsVolumes = mockVolumeLabels(labels)
err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, false, nil))
if err != nil { if err != nil {
t.Errorf("Expected no error when creating aws pv") t.Errorf("Expected no error when creating aws pv")
} }
...@@ -248,7 +248,7 @@ func TestAdmission(t *testing.T) { ...@@ -248,7 +248,7 @@ func TestAdmission(t *testing.T) {
labels["f"] = "2" labels["f"] = "2"
labels["g"] = "3" labels["g"] = "3"
pvHandler.ebsVolumes = mockVolumeLabels(labels) pvHandler.ebsVolumes = mockVolumeLabels(labels)
err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, nil)) err = handler.Admit(admission.NewAttributesRecord(&awsPV, nil, api.Kind("PersistentVolume").WithVersion("version"), awsPV.Namespace, awsPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, false, nil))
if err != nil { if err != nil {
t.Errorf("Expected no error when creating aws pv") t.Errorf("Expected no error when creating aws pv")
} }
......
...@@ -321,7 +321,7 @@ func TestPVCResizeAdmission(t *testing.T) { ...@@ -321,7 +321,7 @@ func TestPVCResizeAdmission(t *testing.T) {
for _, tc := range tests { for _, tc := range tests {
operation := admission.Update operation := admission.Update
attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, nil) attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, false, nil)
err := ctrl.Validate(attributes) err := ctrl.Validate(attributes)
fmt.Println(tc.name) fmt.Println(tc.name)
......
...@@ -208,7 +208,8 @@ func TestAdmission(t *testing.T) { ...@@ -208,7 +208,8 @@ func TestAdmission(t *testing.T) {
api.Resource("persistentvolumeclaims").WithVersion("version"), api.Resource("persistentvolumeclaims").WithVersion("version"),
"", // subresource "", // subresource
admission.Create, admission.Create,
nil, // userInfo false, // dryRun
nil, // userInfo
) )
err := ctrl.Admit(attrs) err := ctrl.Admit(attrs)
glog.Infof("Got %v", err) glog.Infof("Got %v", err)
......
...@@ -133,7 +133,8 @@ func TestAdmit(t *testing.T) { ...@@ -133,7 +133,8 @@ func TestAdmit(t *testing.T) {
test.resource, test.resource,
"", // subresource "", // subresource
admission.Create, admission.Create,
nil, // userInfo false, // dryRun
nil, // userInfo
) )
err := ctrl.Admit(attrs) err := ctrl.Admit(attrs)
......
...@@ -34,6 +34,7 @@ type attributesRecord struct { ...@@ -34,6 +34,7 @@ type attributesRecord struct {
resource schema.GroupVersionResource resource schema.GroupVersionResource
subresource string subresource string
operation Operation operation Operation
dryRun bool
object runtime.Object object runtime.Object
oldObject runtime.Object oldObject runtime.Object
userInfo user.Info userInfo user.Info
...@@ -44,7 +45,7 @@ type attributesRecord struct { ...@@ -44,7 +45,7 @@ type attributesRecord struct {
annotationsLock sync.RWMutex annotationsLock sync.RWMutex
} }
func NewAttributesRecord(object runtime.Object, oldObject runtime.Object, kind schema.GroupVersionKind, namespace, name string, resource schema.GroupVersionResource, subresource string, operation Operation, userInfo user.Info) Attributes { func NewAttributesRecord(object runtime.Object, oldObject runtime.Object, kind schema.GroupVersionKind, namespace, name string, resource schema.GroupVersionResource, subresource string, operation Operation, dryRun bool, userInfo user.Info) Attributes {
return &attributesRecord{ return &attributesRecord{
kind: kind, kind: kind,
namespace: namespace, namespace: namespace,
...@@ -52,6 +53,7 @@ func NewAttributesRecord(object runtime.Object, oldObject runtime.Object, kind s ...@@ -52,6 +53,7 @@ func NewAttributesRecord(object runtime.Object, oldObject runtime.Object, kind s
resource: resource, resource: resource,
subresource: subresource, subresource: subresource,
operation: operation, operation: operation,
dryRun: dryRun,
object: object, object: object,
oldObject: oldObject, oldObject: oldObject,
userInfo: userInfo, userInfo: userInfo,
...@@ -82,6 +84,10 @@ func (record *attributesRecord) GetOperation() Operation { ...@@ -82,6 +84,10 @@ func (record *attributesRecord) GetOperation() Operation {
return record.operation return record.operation
} }
func (record *attributesRecord) IsDryRun() bool {
return record.dryRun
}
func (record *attributesRecord) GetObject() runtime.Object { func (record *attributesRecord) GetObject() runtime.Object {
return record.object return record.object
} }
......
...@@ -64,7 +64,7 @@ func (h fakeHandler) Handles(o Operation) bool { ...@@ -64,7 +64,7 @@ func (h fakeHandler) Handles(o Operation) bool {
} }
func attributes() Attributes { func attributes() Attributes {
return NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", "", nil) return NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", "", false, nil)
} }
func TestWithAudit(t *testing.T) { func TestWithAudit(t *testing.T) {
......
...@@ -119,7 +119,7 @@ func TestAdmitAndValidate(t *testing.T) { ...@@ -119,7 +119,7 @@ func TestAdmitAndValidate(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Logf("testcase = %s", test.name) t.Logf("testcase = %s", test.name)
// call admit and check that validate was not called at all // call admit and check that validate was not called at all
err := test.chain.Admit(NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, nil)) err := test.chain.Admit(NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, false, nil))
accepted := (err == nil) accepted := (err == nil)
if accepted != test.accept { if accepted != test.accept {
t.Errorf("unexpected result of admit call: %v", accepted) t.Errorf("unexpected result of admit call: %v", accepted)
...@@ -140,7 +140,7 @@ func TestAdmitAndValidate(t *testing.T) { ...@@ -140,7 +140,7 @@ func TestAdmitAndValidate(t *testing.T) {
} }
// call validate and check that admit was not called at all // call validate and check that admit was not called at all
err = test.chain.Validate(NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, nil)) err = test.chain.Validate(NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, false, nil))
accepted = (err == nil) accepted = (err == nil)
if accepted != test.accept { if accepted != test.accept {
t.Errorf("unexpected result of validate call: %v\n", accepted) t.Errorf("unexpected result of validate call: %v\n", accepted)
......
...@@ -36,6 +36,7 @@ func TestNewForbidden(t *testing.T) { ...@@ -36,6 +36,7 @@ func TestNewForbidden(t *testing.T) {
schema.GroupVersionResource{Group: "foo", Version: "bar", Resource: "baz"}, schema.GroupVersionResource{Group: "foo", Version: "bar", Resource: "baz"},
"", "",
Create, Create,
false,
nil) nil)
err := errors.New("some error") err := errors.New("some error")
expectedErr := `baz.foo "Unknown/errorGettingName" is forbidden: some error` expectedErr := `baz.foo "Unknown/errorGettingName" is forbidden: some error`
......
...@@ -41,6 +41,11 @@ type Attributes interface { ...@@ -41,6 +41,11 @@ type Attributes interface {
GetSubresource() string GetSubresource() string
// GetOperation is the operation being performed // GetOperation is the operation being performed
GetOperation() Operation GetOperation() Operation
// IsDryRun indicates that modifications will definitely not be persisted for this request. This is to prevent
// admission controllers with side effects and a method of reconciliation from being overwhelmed.
// However, a value of false for this does not mean that the modification will be persisted, because it
// could still be rejected by a subsequent validation step.
IsDryRun() bool
// GetObject is the object from the incoming request prior to default values being applied // GetObject is the object from the incoming request prior to default values being applied
GetObject() runtime.Object GetObject() runtime.Object
// GetOldObject is the existing object. Only populated for UPDATE requests. // GetOldObject is the existing object. Only populated for UPDATE requests.
......
...@@ -28,7 +28,7 @@ import ( ...@@ -28,7 +28,7 @@ import (
var ( var (
kind = schema.GroupVersionKind{Group: "kgroup", Version: "kversion", Kind: "kind"} kind = schema.GroupVersionKind{Group: "kgroup", Version: "kversion", Kind: "kind"}
resource = schema.GroupVersionResource{Group: "rgroup", Version: "rversion", Resource: "resource"} resource = schema.GroupVersionResource{Group: "rgroup", Version: "rversion", Resource: "resource"}
attr = admission.NewAttributesRecord(nil, nil, kind, "ns", "name", resource, "subresource", admission.Create, nil) attr = admission.NewAttributesRecord(nil, nil, kind, "ns", "name", resource, "subresource", admission.Create, false, nil)
) )
func TestObserveAdmissionStep(t *testing.T) { func TestObserveAdmissionStep(t *testing.T) {
...@@ -156,7 +156,7 @@ func TestWithMetrics(t *testing.T) { ...@@ -156,7 +156,7 @@ func TestWithMetrics(t *testing.T) {
h := WithMetrics(test.handler, Metrics.ObserveAdmissionController, test.name) h := WithMetrics(test.handler, Metrics.ObserveAdmissionController, test.name)
// test mutation // test mutation
err := h.(admission.MutationInterface).Admit(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, nil)) err := h.(admission.MutationInterface).Admit(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, false, nil))
if test.admit && err != nil { if test.admit && err != nil {
t.Errorf("expected admit to succeed, but failed: %v", err) t.Errorf("expected admit to succeed, but failed: %v", err)
continue continue
...@@ -181,7 +181,7 @@ func TestWithMetrics(t *testing.T) { ...@@ -181,7 +181,7 @@ func TestWithMetrics(t *testing.T) {
} }
// test validation // test validation
err = h.(admission.ValidationInterface).Validate(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, nil)) err = h.(admission.ValidationInterface).Validate(admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, test.ns, "", schema.GroupVersionResource{}, "", test.operation, false, nil))
if test.validate && err != nil { if test.validate && err != nil {
t.Errorf("expected admit to succeed, but failed: %v", err) t.Errorf("expected admit to succeed, but failed: %v", err)
continue continue
......
...@@ -179,7 +179,7 @@ func TestAdmitUpdate(t *testing.T) { ...@@ -179,7 +179,7 @@ func TestAdmitUpdate(t *testing.T) {
oldObj.Initializers = tc.oldInitializers oldObj.Initializers = tc.oldInitializers
newObj := &v1.Pod{} newObj := &v1.Pod{}
newObj.Initializers = tc.newInitializers newObj.Initializers = tc.newInitializers
a := admission.NewAttributesRecord(newObj, oldObj, schema.GroupVersionKind{}, "", "foo", schema.GroupVersionResource{}, "", admission.Update, nil) a := admission.NewAttributesRecord(newObj, oldObj, schema.GroupVersionKind{}, "", "foo", schema.GroupVersionResource{}, "", admission.Update, false, nil)
err := plugin.Admit(a) err := plugin.Admit(a)
switch { switch {
case tc.err == "" && err != nil: case tc.err == "" && err != nil:
......
...@@ -123,7 +123,7 @@ func TestDispatch(t *testing.T) { ...@@ -123,7 +123,7 @@ func TestDispatch(t *testing.T) {
}, },
} }
attr := generic.VersionedAttributes{ attr := generic.VersionedAttributes{
Attributes: admission.NewAttributesRecord(test.out, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", admission.Operation(""), nil), Attributes: admission.NewAttributesRecord(test.out, nil, schema.GroupVersionKind{}, "", "", schema.GroupVersionResource{}, "", admission.Operation(""), false, nil),
VersionedOldObject: nil, VersionedOldObject: nil,
VersionedObject: test.in, VersionedObject: test.in,
} }
......
...@@ -75,27 +75,27 @@ func TestGetNamespaceLabels(t *testing.T) { ...@@ -75,27 +75,27 @@ func TestGetNamespaceLabels(t *testing.T) {
}{ }{
{ {
name: "request is for creating namespace, the labels should be from the object itself", name: "request is for creating namespace, the labels should be from the object itself",
attr: admission.NewAttributesRecord(&namespace2, nil, schema.GroupVersionKind{}, "", namespace2.Name, schema.GroupVersionResource{Resource: "namespaces"}, "", admission.Create, nil), attr: admission.NewAttributesRecord(&namespace2, nil, schema.GroupVersionKind{}, "", namespace2.Name, schema.GroupVersionResource{Resource: "namespaces"}, "", admission.Create, false, nil),
expectedLabels: namespace2Labels, expectedLabels: namespace2Labels,
}, },
{ {
name: "request is for updating namespace, the labels should be from the new object", name: "request is for updating namespace, the labels should be from the new object",
attr: admission.NewAttributesRecord(&namespace2, nil, schema.GroupVersionKind{}, namespace2.Name, namespace2.Name, schema.GroupVersionResource{Resource: "namespaces"}, "", admission.Update, nil), attr: admission.NewAttributesRecord(&namespace2, nil, schema.GroupVersionKind{}, namespace2.Name, namespace2.Name, schema.GroupVersionResource{Resource: "namespaces"}, "", admission.Update, false, nil),
expectedLabels: namespace2Labels, expectedLabels: namespace2Labels,
}, },
{ {
name: "request is for deleting namespace, the labels should be from the cache", name: "request is for deleting namespace, the labels should be from the cache",
attr: admission.NewAttributesRecord(&namespace2, nil, schema.GroupVersionKind{}, namespace1.Name, namespace1.Name, schema.GroupVersionResource{Resource: "namespaces"}, "", admission.Delete, nil), attr: admission.NewAttributesRecord(&namespace2, nil, schema.GroupVersionKind{}, namespace1.Name, namespace1.Name, schema.GroupVersionResource{Resource: "namespaces"}, "", admission.Delete, false, nil),
expectedLabels: namespace1Labels, expectedLabels: namespace1Labels,
}, },
{ {
name: "request is for namespace/finalizer", name: "request is for namespace/finalizer",
attr: admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, namespace1.Name, "mock-name", schema.GroupVersionResource{Resource: "namespaces"}, "finalizers", admission.Create, nil), attr: admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, namespace1.Name, "mock-name", schema.GroupVersionResource{Resource: "namespaces"}, "finalizers", admission.Create, false, nil),
expectedLabels: namespace1Labels, expectedLabels: namespace1Labels,
}, },
{ {
name: "request is for pod", name: "request is for pod",
attr: admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, namespace1.Name, "mock-name", schema.GroupVersionResource{Resource: "pods"}, "", admission.Create, nil), attr: admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, namespace1.Name, "mock-name", schema.GroupVersionResource{Resource: "pods"}, "", admission.Create, false, nil),
expectedLabels: namespace1Labels, expectedLabels: namespace1Labels,
}, },
} }
...@@ -117,7 +117,7 @@ func TestNotExemptClusterScopedResource(t *testing.T) { ...@@ -117,7 +117,7 @@ func TestNotExemptClusterScopedResource(t *testing.T) {
hook := &registrationv1beta1.Webhook{ hook := &registrationv1beta1.Webhook{
NamespaceSelector: &metav1.LabelSelector{}, NamespaceSelector: &metav1.LabelSelector{},
} }
attr := admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "", "mock-name", schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, "", admission.Create, nil) attr := admission.NewAttributesRecord(nil, nil, schema.GroupVersionKind{}, "", "mock-name", schema.GroupVersionResource{Version: "v1", Resource: "nodes"}, "", admission.Create, false, nil)
matcher := Matcher{} matcher := Matcher{}
matches, err := matcher.MatchNamespaceSelector(hook, attr) matches, err := matcher.MatchNamespaceSelector(hook, attr)
if err != nil { if err != nil {
......
...@@ -38,6 +38,7 @@ func a(group, version, resource, subresource, name string, operation admission.O ...@@ -38,6 +38,7 @@ func a(group, version, resource, subresource, name string, operation admission.O
"ns", name, "ns", name,
schema.GroupVersionResource{Group: group, Version: version, Resource: resource}, subresource, schema.GroupVersionResource{Group: group, Version: version, Resource: resource}, subresource,
operation, operation,
false,
nil, nil,
) )
} }
......
...@@ -95,7 +95,7 @@ func newAttributesRecord(object metav1.Object, oldObject metav1.Object, kind sch ...@@ -95,7 +95,7 @@ func newAttributesRecord(object metav1.Object, oldObject metav1.Object, kind sch
UID: "webhook-test", UID: "webhook-test",
} }
return admission.NewAttributesRecord(object.(runtime.Object), oldObject.(runtime.Object), kind, namespace, name, gvr, subResource, admission.Update, &userInfo) return admission.NewAttributesRecord(object.(runtime.Object), oldObject.(runtime.Object), kind, namespace, name, gvr, subResource, admission.Update, false, &userInfo)
} }
// NewAttribute returns static admission Attributes for testing. // NewAttribute returns static admission Attributes for testing.
......
...@@ -79,6 +79,7 @@ go_library( ...@@ -79,6 +79,7 @@ go_library(
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/server/httplog:go_default_library", "//staging/src/k8s.io/apiserver/pkg/server/httplog:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/dryrun:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/trace:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/trace:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/wsstream:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/wsstream:go_default_library",
"//vendor/github.com/evanphx/json-patch:go_default_library", "//vendor/github.com/evanphx/json-patch:go_default_library",
......
...@@ -34,6 +34,7 @@ import ( ...@@ -34,6 +34,7 @@ import (
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
"k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/util/dryrun"
utiltrace "k8s.io/apiserver/pkg/util/trace" utiltrace "k8s.io/apiserver/pkg/util/trace"
) )
...@@ -116,7 +117,7 @@ func createHandler(r rest.NamedCreater, scope RequestScope, admit admission.Inte ...@@ -116,7 +117,7 @@ func createHandler(r rest.NamedCreater, scope RequestScope, admit admission.Inte
audit.LogRequestObject(ae, obj, scope.Resource, scope.Subresource, scope.Serializer) audit.LogRequestObject(ae, obj, scope.Resource, scope.Subresource, scope.Serializer)
userInfo, _ := request.UserFrom(ctx) userInfo, _ := request.UserFrom(ctx)
admissionAttributes := admission.NewAttributesRecord(obj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, userInfo) admissionAttributes := admission.NewAttributesRecord(obj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, dryrun.IsDryRun(options.DryRun), userInfo)
if mutatingAdmission, ok := admit.(admission.MutationInterface); ok && mutatingAdmission.Handles(admission.Create) { if mutatingAdmission, ok := admit.(admission.MutationInterface); ok && mutatingAdmission.Handles(admission.Create) {
err = mutatingAdmission.Admit(admissionAttributes) err = mutatingAdmission.Admit(admissionAttributes)
if err != nil { if err != nil {
......
...@@ -32,6 +32,7 @@ import ( ...@@ -32,6 +32,7 @@ import (
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
"k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/util/dryrun"
utiltrace "k8s.io/apiserver/pkg/util/trace" utiltrace "k8s.io/apiserver/pkg/util/trace"
) )
...@@ -108,7 +109,7 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope RequestSco ...@@ -108,7 +109,7 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope RequestSco
trace.Step("About to check admission control") trace.Step("About to check admission control")
if admit != nil && admit.Handles(admission.Delete) { if admit != nil && admit.Handles(admission.Delete) {
userInfo, _ := request.UserFrom(ctx) userInfo, _ := request.UserFrom(ctx)
attrs := admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Delete, userInfo) attrs := admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Delete, dryrun.IsDryRun(options.DryRun), userInfo)
if mutatingAdmission, ok := admit.(admission.MutationInterface); ok { if mutatingAdmission, ok := admit.(admission.MutationInterface); ok {
if err := mutatingAdmission.Admit(attrs); err != nil { if err := mutatingAdmission.Admit(attrs); err != nil {
scope.err(err, w, req) scope.err(err, w, req)
...@@ -196,27 +197,6 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestSco ...@@ -196,27 +197,6 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestSco
ctx := req.Context() ctx := req.Context()
ctx = request.WithNamespace(ctx, namespace) ctx = request.WithNamespace(ctx, namespace)
ae := request.AuditEventFrom(ctx) ae := request.AuditEventFrom(ctx)
admit = admission.WithAudit(admit, ae)
if admit != nil && admit.Handles(admission.Delete) {
userInfo, _ := request.UserFrom(ctx)
attrs := admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, "", scope.Resource, scope.Subresource, admission.Delete, userInfo)
if mutatingAdmission, ok := admit.(admission.MutationInterface); ok {
err = mutatingAdmission.Admit(attrs)
if err != nil {
scope.err(err, w, req)
return
}
}
if validatingAdmission, ok := admit.(admission.ValidationInterface); ok {
err = validatingAdmission.Validate(attrs)
if err != nil {
scope.err(err, w, req)
return
}
}
}
listOptions := metainternalversion.ListOptions{} listOptions := metainternalversion.ListOptions{}
if err := metainternalversion.ParameterCodec.DecodeParameters(req.URL.Query(), scope.MetaGroupVersion, &listOptions); err != nil { if err := metainternalversion.ParameterCodec.DecodeParameters(req.URL.Query(), scope.MetaGroupVersion, &listOptions); err != nil {
...@@ -279,6 +259,27 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestSco ...@@ -279,6 +259,27 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestSco
return return
} }
admit = admission.WithAudit(admit, ae)
if admit != nil && admit.Handles(admission.Delete) {
userInfo, _ := request.UserFrom(ctx)
attrs := admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, "", scope.Resource, scope.Subresource, admission.Delete, dryrun.IsDryRun(options.DryRun), userInfo)
if mutatingAdmission, ok := admit.(admission.MutationInterface); ok {
err = mutatingAdmission.Admit(attrs)
if err != nil {
scope.err(err, w, req)
return
}
}
if validatingAdmission, ok := admit.(admission.ValidationInterface); ok {
err = validatingAdmission.Validate(attrs)
if err != nil {
scope.err(err, w, req)
return
}
}
}
result, err := finishRequest(timeout, func() (runtime.Object, error) { result, err := finishRequest(timeout, func() (runtime.Object, error) {
return r.DeleteCollection(ctx, options, &listOptions) return r.DeleteCollection(ctx, options, &listOptions)
}) })
......
...@@ -41,6 +41,7 @@ import ( ...@@ -41,6 +41,7 @@ import (
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
"k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/util/dryrun"
utiltrace "k8s.io/apiserver/pkg/util/trace" utiltrace "k8s.io/apiserver/pkg/util/trace"
) )
...@@ -130,6 +131,7 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface ...@@ -130,6 +131,7 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface
scope.Resource, scope.Resource,
scope.Subresource, scope.Subresource,
admission.Update, admission.Update,
dryrun.IsDryRun(options.DryRun),
userInfo, userInfo,
) )
admissionCheck := func(updatedObject runtime.Object, currentObject runtime.Object) error { admissionCheck := func(updatedObject runtime.Object, currentObject runtime.Object) error {
...@@ -144,6 +146,7 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface ...@@ -144,6 +146,7 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface
scope.Resource, scope.Resource,
scope.Subresource, scope.Subresource,
admission.Update, admission.Update,
dryrun.IsDryRun(options.DryRun),
userInfo, userInfo,
)) ))
} }
......
...@@ -123,14 +123,14 @@ func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admissi ...@@ -123,14 +123,14 @@ func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admissi
userInfo, _ := request.UserFrom(ctx) userInfo, _ := request.UserFrom(ctx)
// TODO: remove the mutating admission here as soon as we have ported all plugin that handle CONNECT // TODO: remove the mutating admission here as soon as we have ported all plugin that handle CONNECT
if mutatingAdmission, ok := admit.(admission.MutationInterface); ok { if mutatingAdmission, ok := admit.(admission.MutationInterface); ok {
err = mutatingAdmission.Admit(admission.NewAttributesRecord(connectRequest, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, userInfo)) err = mutatingAdmission.Admit(admission.NewAttributesRecord(connectRequest, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, false, userInfo))
if err != nil { if err != nil {
scope.err(err, w, req) scope.err(err, w, req)
return return
} }
} }
if validatingAdmission, ok := admit.(admission.ValidationInterface); ok { if validatingAdmission, ok := admit.(admission.ValidationInterface); ok {
err = validatingAdmission.Validate(admission.NewAttributesRecord(connectRequest, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, userInfo)) err = validatingAdmission.Validate(admission.NewAttributesRecord(connectRequest, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Connect, false, userInfo))
if err != nil { if err != nil {
scope.err(err, w, req) scope.err(err, w, req)
return return
......
...@@ -35,6 +35,7 @@ import ( ...@@ -35,6 +35,7 @@ import (
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
"k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/util/dryrun"
utiltrace "k8s.io/apiserver/pkg/util/trace" utiltrace "k8s.io/apiserver/pkg/util/trace"
) )
...@@ -119,11 +120,11 @@ func UpdateResource(r rest.Updater, scope RequestScope, admit admission.Interfac ...@@ -119,11 +120,11 @@ func UpdateResource(r rest.Updater, scope RequestScope, admit admission.Interfac
return nil, fmt.Errorf("unexpected error when extracting UID from oldObj: %v", err.Error()) return nil, fmt.Errorf("unexpected error when extracting UID from oldObj: %v", err.Error())
} else if !isNotZeroObject { } else if !isNotZeroObject {
if mutatingAdmission.Handles(admission.Create) { if mutatingAdmission.Handles(admission.Create) {
return newObj, mutatingAdmission.Admit(admission.NewAttributesRecord(newObj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, userInfo)) return newObj, mutatingAdmission.Admit(admission.NewAttributesRecord(newObj, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, dryrun.IsDryRun(options.DryRun), userInfo))
} }
} else { } else {
if mutatingAdmission.Handles(admission.Update) { if mutatingAdmission.Handles(admission.Update) {
return newObj, mutatingAdmission.Admit(admission.NewAttributesRecord(newObj, oldObj, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, userInfo)) return newObj, mutatingAdmission.Admit(admission.NewAttributesRecord(newObj, oldObj, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, dryrun.IsDryRun(options.DryRun), userInfo))
} }
} }
return newObj, nil return newObj, nil
...@@ -153,11 +154,11 @@ func UpdateResource(r rest.Updater, scope RequestScope, admit admission.Interfac ...@@ -153,11 +154,11 @@ func UpdateResource(r rest.Updater, scope RequestScope, admit admission.Interfac
rest.DefaultUpdatedObjectInfo(obj, transformers...), rest.DefaultUpdatedObjectInfo(obj, transformers...),
withAuthorization(rest.AdmissionToValidateObjectFunc( withAuthorization(rest.AdmissionToValidateObjectFunc(
admit, admit,
admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, userInfo)), admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, dryrun.IsDryRun(options.DryRun), userInfo)),
scope.Authorizer, createAuthorizerAttributes), scope.Authorizer, createAuthorizerAttributes),
rest.AdmissionToValidateObjectUpdateFunc( rest.AdmissionToValidateObjectUpdateFunc(
admit, admit,
admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, userInfo)), admission.NewAttributesRecord(nil, nil, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, dryrun.IsDryRun(options.DryRun), userInfo)),
false, false,
options, options,
) )
......
...@@ -170,6 +170,7 @@ func AdmissionToValidateObjectFunc(admit admission.Interface, staticAttributes a ...@@ -170,6 +170,7 @@ func AdmissionToValidateObjectFunc(admit admission.Interface, staticAttributes a
staticAttributes.GetResource(), staticAttributes.GetResource(),
staticAttributes.GetSubresource(), staticAttributes.GetSubresource(),
staticAttributes.GetOperation(), staticAttributes.GetOperation(),
staticAttributes.IsDryRun(),
staticAttributes.GetUserInfo(), staticAttributes.GetUserInfo(),
) )
if !validatingAdmission.Handles(finalAttributes.GetOperation()) { if !validatingAdmission.Handles(finalAttributes.GetOperation()) {
......
...@@ -263,6 +263,7 @@ func AdmissionToValidateObjectUpdateFunc(admit admission.Interface, staticAttrib ...@@ -263,6 +263,7 @@ func AdmissionToValidateObjectUpdateFunc(admit admission.Interface, staticAttrib
staticAttributes.GetResource(), staticAttributes.GetResource(),
staticAttributes.GetSubresource(), staticAttributes.GetSubresource(),
staticAttributes.GetOperation(), staticAttributes.GetOperation(),
staticAttributes.IsDryRun(),
staticAttributes.GetUserInfo(), staticAttributes.GetUserInfo(),
) )
if !validatingAdmission.Handles(finalAttributes.GetOperation()) { if !validatingAdmission.Handles(finalAttributes.GetOperation()) {
......
...@@ -136,6 +136,7 @@ func TestBanflunderAdmissionPlugin(t *testing.T) { ...@@ -136,6 +136,7 @@ func TestBanflunderAdmissionPlugin(t *testing.T) {
scenario.admissionInputResource, scenario.admissionInputResource,
"", "",
admission.Create, admission.Create,
false,
nil), nil),
) )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment