Commit adafb136 authored by jennybuckley's avatar jennybuckley

Support dry run in admission plugins

parent b759b002
......@@ -25,7 +25,7 @@ import (
func TestAdmissionNonNilAttribute(t *testing.T) {
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 {
t.Errorf("Unexpected error returned from admission handler")
}
......
......@@ -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 {
t.Errorf("Unexpected error returned from admission handler")
}
......@@ -84,7 +84,7 @@ func TestValidate(t *testing.T) {
},
}
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 {
t.Fatal("missing expected error")
}
......@@ -139,7 +139,7 @@ func TestOtherResources(t *testing.T) {
for _, tc := range tests {
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 err == nil {
......
......@@ -199,7 +199,7 @@ func TestInterPodAffinityAdmission(t *testing.T) {
}
for _, test := range tests {
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 {
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) {
for _, tc := range tests {
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 err == nil {
......
......@@ -395,7 +395,7 @@ func TestForgivenessAdmission(t *testing.T) {
}
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 {
t.Errorf("[%s]: unexpected error %v for pod %+v", test.description, err, test.requestedPod)
}
......
......@@ -25,7 +25,7 @@ import (
func TestAdmission(t *testing.T) {
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 {
t.Error("Expected error returned from admission handler")
}
......
......@@ -87,6 +87,13 @@ func (a *Plugin) Validate(attr admission.Attributes) (err error) {
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
// give each limit enforcer a chance to reject the event
for _, enforcer := range a.limitEnforcers {
......
......@@ -46,6 +46,7 @@ func attributesForRequest(rq request) admission.Attributes {
api.Resource("resource").WithVersion("version"),
"",
admission.Create,
rq.dryRun,
&user.DefaultInfo{Name: rq.username})
}
......@@ -56,6 +57,7 @@ type request struct {
event *api.Event
delay time.Duration
accepted bool
dryRun bool
}
func newRequest(kind 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 {
r.username = name
return r
......@@ -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",
serverBurst: 3,
requests: []request{
......
......@@ -123,7 +123,7 @@ func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept b
// 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 {
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
// 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 {
t.Errorf("Unexpected error returned from admission handler: %v", err)
}
......
......@@ -354,7 +354,7 @@ func TestAdmit(t *testing.T) {
},
}
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 {
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) {
operation = admission.Update
}
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)
if !tc.checkError(err) {
......@@ -518,7 +518,7 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) {
operation = admission.Update
}
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)
if !tc.checkError(err) {
......
......@@ -472,7 +472,7 @@ func TestTLSConfig(t *testing.T) {
return
}
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.
service.Allow()
......@@ -561,7 +561,7 @@ func TestWebhookCache(t *testing.T) {
{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
......@@ -573,7 +573,7 @@ func TestWebhookCache(t *testing.T) {
{statusCode: 200, expectedErr: false, expectedAuthorized: true, expectedCached: false},
{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)
}
......@@ -747,7 +747,7 @@ func TestContainerCombinations(t *testing.T) {
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)
if tt.wantAllowed {
......@@ -825,7 +825,7 @@ func TestDefaultAllow(t *testing.T) {
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)
if tt.wantAllowed {
......@@ -917,7 +917,7 @@ func TestAnnotationFiltering(t *testing.T) {
pod := goodPod("test")
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)
if err != nil {
......
......@@ -694,16 +694,16 @@ func TestLimitRangerIgnoresSubresource(t *testing.T) {
informerFactory.Start(wait.NeverStop)
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 {
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 {
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 {
t.Errorf("Should have ignored calls to any subresource of pod %v", err)
}
......@@ -720,16 +720,16 @@ func TestLimitRangerAdmitPod(t *testing.T) {
informerFactory.Start(wait.NeverStop)
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 {
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 {
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 {
t.Errorf("Should have ignored calls to any subresource of pod %v", err)
}
......@@ -738,7 +738,7 @@ func TestLimitRangerAdmitPod(t *testing.T) {
terminatingPod := validPod("terminatingPod", 1, api.ResourceRequirements{})
now := metav1.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 {
t.Errorf("LimitRange should ignore a pod marked for termination")
}
......
......@@ -55,6 +55,11 @@ var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&Provision{})
// Admit makes an admission decision based on the request attributes
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 the API server has found a route, which means that if we have a non-empty namespace
// its a namespaced resource.
......
......@@ -98,7 +98,7 @@ func TestAdmission(t *testing.T) {
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, 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")
}
......@@ -118,7 +118,27 @@ func TestAdmissionNamespaceExists(t *testing.T) {
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, 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 {
t.Errorf("unexpected error returned from admission handler")
}
......@@ -139,7 +159,7 @@ func TestIgnoreAdmission(t *testing.T) {
chainHandler := admission.NewChainHandler(handler)
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 {
t.Errorf("unexpected error returned from admission handler")
}
......@@ -161,7 +181,7 @@ func TestAdmissionWithLatentCache(t *testing.T) {
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, 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")
}
......
......@@ -87,7 +87,7 @@ func TestAdmissionNamespaceExists(t *testing.T) {
informerFactory.Start(wait.NeverStop)
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 {
t.Errorf("unexpected error returned from admission handler")
}
......@@ -107,7 +107,7 @@ func TestAdmissionNamespaceDoesNotExist(t *testing.T) {
informerFactory.Start(wait.NeverStop)
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 {
actions := ""
for _, action := range mockClient.Actions() {
......
......@@ -166,7 +166,7 @@ func TestPodAdmission(t *testing.T) {
handler.clusterNodeSelectors[namespace.Name] = test.whitelist
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 {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil {
......@@ -175,7 +175,7 @@ func TestPodAdmission(t *testing.T) {
if test.admit && !labels.Equals(test.mergedNodeSelector, labels.Set(pod.Spec.NodeSelector)) {
t.Errorf("Test: %s, expected: %s but got: %s", test.testName, test.mergedNodeSelector, pod.Spec.NodeSelector)
}
err = handler.Validate(admission.NewAttributesRecord(pod, 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 {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil {
......@@ -183,7 +183,7 @@ func TestPodAdmission(t *testing.T) {
}
// 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 {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil {
......@@ -192,7 +192,7 @@ func TestPodAdmission(t *testing.T) {
if test.admit && !labels.Equals(test.mergedNodeSelector, labels.Set(pod.Spec.NodeSelector)) {
t.Errorf("Test: %s, expected: %s but got: %s", test.testName, test.mergedNodeSelector, pod.Spec.NodeSelector)
}
err = handler.Validate(admission.NewAttributesRecord(pod, &oldPod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, 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 {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil {
......@@ -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.
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 {
t.Errorf("expected no error, got: %v", err)
}
......
......@@ -818,6 +818,7 @@ func admitPod(pod *api.Pod, pip *settings.PodPreset) error {
api.Resource("pods").WithVersion("version"),
"",
kadmission.Create,
false,
&user.DefaultInfo{},
)
......
......@@ -258,7 +258,7 @@ func TestPodAdmission(t *testing.T) {
oldPod.Initializers = &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init"}}}
oldPod.Spec.Tolerations = []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}}
err = handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
err = handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
if test.admit && err != nil {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil {
......@@ -271,7 +271,7 @@ func TestPodAdmission(t *testing.T) {
}
// 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 {
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
} else if !test.admit && err == nil {
......@@ -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.
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 {
t.Errorf("expected no error, got: %v", err)
}
......
......@@ -146,6 +146,7 @@ func TestPriorityClassAdmission(t *testing.T) {
scheduling.Resource("priorityclasses").WithVersion("version"),
"",
admission.Create,
false,
test.userInfo,
)
err := ctrl.Validate(attrs)
......@@ -186,7 +187,7 @@ func TestDefaultPriority(t *testing.T) {
name: "add a default class",
classesBefore: []*scheduling.PriorityClass{nondefaultClass1},
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,
expectedDefaultAfter: defaultClass1.Value,
},
......@@ -194,7 +195,7 @@ func TestDefaultPriority(t *testing.T) {
name: "multiple default classes resolves to the minimum value among them",
classesBefore: []*scheduling.PriorityClass{defaultClass1, 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,
expectedDefaultAfter: defaultClass2.Value,
},
......@@ -202,7 +203,7 @@ func TestDefaultPriority(t *testing.T) {
name: "delete default priority class",
classesBefore: []*scheduling.PriorityClass{defaultClass1},
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,
expectedDefaultAfter: scheduling.DefaultPriorityWhenNoDefaultClassExists,
},
......@@ -210,7 +211,7 @@ func TestDefaultPriority(t *testing.T) {
name: "update default class and remove its global default",
classesBefore: []*scheduling.PriorityClass{defaultClass1},
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,
expectedDefaultAfter: scheduling.DefaultPriorityWhenNoDefaultClassExists,
},
......@@ -568,6 +569,7 @@ func TestPodAdmission(t *testing.T) {
api.Resource("pods").WithVersion("version"),
"",
admission.Create,
false,
nil,
)
err := ctrl.Admit(attrs)
......
......@@ -231,6 +231,12 @@ func (e *quotaEvaluator) checkQuotas(quotas []api.ResourceQuota, admissionAttrib
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
// that means that no quota docs applied, so it can get a pass
atLeastOneChangeForThisWaiter := false
......
......@@ -472,7 +472,7 @@ func TestAdmitPreferNonmutating(t *testing.T) {
func TestFailClosedOnInvalidPod(t *testing.T) {
plugin := NewTestAdmission(nil, nil)
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)
if err == nil {
......@@ -1769,7 +1769,7 @@ func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []*
originalPod := pod.DeepCopy()
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)
attrs = &fakeAttributes{attrs, annotations}
err := plugin.Admit(attrs)
......@@ -2227,7 +2227,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) {
pod.Spec.SecurityContext.HostPID = true
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, "")
assert.Nil(t, allowedPod)
......@@ -2320,7 +2320,7 @@ func TestPreferValidatedPSP(t *testing.T) {
pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = &allowPrivilegeEscalation
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)
assert.NoError(t, err)
......
......@@ -82,7 +82,7 @@ func TestAdmission(t *testing.T) {
p.Spec.SecurityContext = tc.podSc
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 {
t.Errorf("%v: unexpected error: %v", tc.name, err)
} else if err == nil && tc.expectError {
......@@ -96,7 +96,7 @@ func TestAdmission(t *testing.T) {
p.Spec.InitContainers = p.Spec.Containers
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 {
t.Errorf("%v: unexpected error: %v", tc.name, err)
} else if err == nil && tc.expectError {
......@@ -140,7 +140,7 @@ func TestPodSecurityContextAdmission(t *testing.T) {
}
for _, test := range tests {
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 {
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) {
defer utilfeature.DefaultFeatureGate.Set("VolumeScheduling=false")
// 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 {
t.Errorf("Unexpected error returned from admission handler (on ignored pv): %v", err)
}
// 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 {
t.Errorf("Unexpected error returned from admission handler (when deleting aws pv): %v", err)
}
// Errors from the cloudprovider block creation of the 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 {
t.Errorf("Expected error when aws pv info fails")
}
......@@ -147,7 +147,7 @@ func TestAdmission(t *testing.T) {
// Don't add labels if the cloudprovider doesn't return any
labels := make(map[string]string)
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 {
t.Errorf("Expected no error when creating aws pv")
}
......@@ -160,7 +160,7 @@ func TestAdmission(t *testing.T) {
// Don't panic if the cloudprovider returns nil, 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 {
t.Errorf("Expected no error when cloud provider returns empty labels")
}
......@@ -172,7 +172,7 @@ func TestAdmission(t *testing.T) {
zones, _ := volumeutil.ZonesToSet("1,2,3")
labels[kubeletapis.LabelZoneFailureDomain] = volumeutil.ZonesSetToLabelValue(zones)
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 {
t.Errorf("Expected no error when creating aws pv")
}
......@@ -210,7 +210,7 @@ func TestAdmission(t *testing.T) {
awsPV.ObjectMeta.Labels = make(map[string]string)
awsPV.ObjectMeta.Labels["a"] = "not1"
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 {
t.Errorf("Expected no error when creating aws pv")
}
......@@ -227,7 +227,7 @@ func TestAdmission(t *testing.T) {
labels["b"] = "2"
labels["c"] = "3"
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 {
t.Errorf("Expected no error when creating aws pv")
}
......@@ -248,7 +248,7 @@ func TestAdmission(t *testing.T) {
labels["f"] = "2"
labels["g"] = "3"
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 {
t.Errorf("Expected no error when creating aws pv")
}
......
......@@ -321,7 +321,7 @@ func TestPVCResizeAdmission(t *testing.T) {
for _, tc := range tests {
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)
fmt.Println(tc.name)
......
......@@ -208,7 +208,8 @@ func TestAdmission(t *testing.T) {
api.Resource("persistentvolumeclaims").WithVersion("version"),
"", // subresource
admission.Create,
nil, // userInfo
false, // dryRun
nil, // userInfo
)
err := ctrl.Admit(attrs)
glog.Infof("Got %v", err)
......
......@@ -133,7 +133,8 @@ func TestAdmit(t *testing.T) {
test.resource,
"", // subresource
admission.Create,
nil, // userInfo
false, // dryRun
nil, // userInfo
)
err := ctrl.Admit(attrs)
......
......@@ -34,6 +34,7 @@ type attributesRecord struct {
resource schema.GroupVersionResource
subresource string
operation Operation
dryRun bool
object runtime.Object
oldObject runtime.Object
userInfo user.Info
......@@ -44,7 +45,7 @@ type attributesRecord struct {
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{
kind: kind,
namespace: namespace,
......@@ -52,6 +53,7 @@ func NewAttributesRecord(object runtime.Object, oldObject runtime.Object, kind s
resource: resource,
subresource: subresource,
operation: operation,
dryRun: dryRun,
object: object,
oldObject: oldObject,
userInfo: userInfo,
......@@ -82,6 +84,10 @@ func (record *attributesRecord) GetOperation() Operation {
return record.operation
}
func (record *attributesRecord) IsDryRun() bool {
return record.dryRun
}
func (record *attributesRecord) GetObject() runtime.Object {
return record.object
}
......
......@@ -64,7 +64,7 @@ func (h fakeHandler) Handles(o Operation) bool {
}
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) {
......
......@@ -119,7 +119,7 @@ func TestAdmitAndValidate(t *testing.T) {
for _, test := range tests {
t.Logf("testcase = %s", test.name)
// 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)
if accepted != test.accept {
t.Errorf("unexpected result of admit call: %v", accepted)
......@@ -140,7 +140,7 @@ func TestAdmitAndValidate(t *testing.T) {
}
// 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)
if accepted != test.accept {
t.Errorf("unexpected result of validate call: %v\n", accepted)
......
......@@ -36,6 +36,7 @@ func TestNewForbidden(t *testing.T) {
schema.GroupVersionResource{Group: "foo", Version: "bar", Resource: "baz"},
"",
Create,
false,
nil)
err := errors.New("some error")
expectedErr := `baz.foo "Unknown/errorGettingName" is forbidden: some error`
......
......@@ -41,6 +41,11 @@ type Attributes interface {
GetSubresource() string
// GetOperation is the operation being performed
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() runtime.Object
// GetOldObject is the existing object. Only populated for UPDATE requests.
......
......@@ -28,7 +28,7 @@ import (
var (
kind = schema.GroupVersionKind{Group: "kgroup", Version: "kversion", Kind: "kind"}
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) {
......@@ -156,7 +156,7 @@ func TestWithMetrics(t *testing.T) {
h := WithMetrics(test.handler, Metrics.ObserveAdmissionController, test.name)
// 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 {
t.Errorf("expected admit to succeed, but failed: %v", err)
continue
......@@ -181,7 +181,7 @@ func TestWithMetrics(t *testing.T) {
}
// 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 {
t.Errorf("expected admit to succeed, but failed: %v", err)
continue
......
......@@ -179,7 +179,7 @@ func TestAdmitUpdate(t *testing.T) {
oldObj.Initializers = tc.oldInitializers
newObj := &v1.Pod{}
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)
switch {
case tc.err == "" && err != nil:
......
......@@ -123,7 +123,7 @@ func TestDispatch(t *testing.T) {
},
}
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,
VersionedObject: test.in,
}
......
......@@ -75,27 +75,27 @@ func TestGetNamespaceLabels(t *testing.T) {
}{
{
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,
},
{
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,
},
{
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,
},
{
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,
},
{
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,
},
}
......@@ -117,7 +117,7 @@ func TestNotExemptClusterScopedResource(t *testing.T) {
hook := &registrationv1beta1.Webhook{
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{}
matches, err := matcher.MatchNamespaceSelector(hook, attr)
if err != nil {
......
......@@ -38,6 +38,7 @@ func a(group, version, resource, subresource, name string, operation admission.O
"ns", name,
schema.GroupVersionResource{Group: group, Version: version, Resource: resource}, subresource,
operation,
false,
nil,
)
}
......
......@@ -95,7 +95,7 @@ func newAttributesRecord(object metav1.Object, oldObject metav1.Object, kind sch
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.
......
......@@ -79,6 +79,7 @@ go_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/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/wsstream:go_default_library",
"//vendor/github.com/evanphx/json-patch:go_default_library",
......
......@@ -34,6 +34,7 @@ import (
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/util/dryrun"
utiltrace "k8s.io/apiserver/pkg/util/trace"
)
......@@ -116,7 +117,7 @@ func createHandler(r rest.NamedCreater, scope RequestScope, admit admission.Inte
audit.LogRequestObject(ae, obj, scope.Resource, scope.Subresource, scope.Serializer)
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) {
err = mutatingAdmission.Admit(admissionAttributes)
if err != nil {
......
......@@ -32,6 +32,7 @@ import (
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/util/dryrun"
utiltrace "k8s.io/apiserver/pkg/util/trace"
)
......@@ -108,7 +109,7 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope RequestSco
trace.Step("About to check admission control")
if admit != nil && admit.Handles(admission.Delete) {
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 err := mutatingAdmission.Admit(attrs); err != nil {
scope.err(err, w, req)
......@@ -196,27 +197,6 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestSco
ctx := req.Context()
ctx = request.WithNamespace(ctx, namespace)
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{}
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
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) {
return r.DeleteCollection(ctx, options, &listOptions)
})
......
......@@ -41,6 +41,7 @@ import (
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/util/dryrun"
utiltrace "k8s.io/apiserver/pkg/util/trace"
)
......@@ -130,6 +131,7 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface
scope.Resource,
scope.Subresource,
admission.Update,
dryrun.IsDryRun(options.DryRun),
userInfo,
)
admissionCheck := func(updatedObject runtime.Object, currentObject runtime.Object) error {
......@@ -144,6 +146,7 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface
scope.Resource,
scope.Subresource,
admission.Update,
dryrun.IsDryRun(options.DryRun),
userInfo,
))
}
......
......@@ -123,14 +123,14 @@ func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admissi
userInfo, _ := request.UserFrom(ctx)
// TODO: remove the mutating admission here as soon as we have ported all plugin that handle CONNECT
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 {
scope.err(err, w, req)
return
}
}
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 {
scope.err(err, w, req)
return
......
......@@ -35,6 +35,7 @@ import (
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/util/dryrun"
utiltrace "k8s.io/apiserver/pkg/util/trace"
)
......@@ -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())
} else if !isNotZeroObject {
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 {
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
......@@ -153,11 +154,11 @@ func UpdateResource(r rest.Updater, scope RequestScope, admit admission.Interfac
rest.DefaultUpdatedObjectInfo(obj, transformers...),
withAuthorization(rest.AdmissionToValidateObjectFunc(
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),
rest.AdmissionToValidateObjectUpdateFunc(
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,
options,
)
......
......@@ -170,6 +170,7 @@ func AdmissionToValidateObjectFunc(admit admission.Interface, staticAttributes a
staticAttributes.GetResource(),
staticAttributes.GetSubresource(),
staticAttributes.GetOperation(),
staticAttributes.IsDryRun(),
staticAttributes.GetUserInfo(),
)
if !validatingAdmission.Handles(finalAttributes.GetOperation()) {
......
......@@ -263,6 +263,7 @@ func AdmissionToValidateObjectUpdateFunc(admit admission.Interface, staticAttrib
staticAttributes.GetResource(),
staticAttributes.GetSubresource(),
staticAttributes.GetOperation(),
staticAttributes.IsDryRun(),
staticAttributes.GetUserInfo(),
)
if !validatingAdmission.Handles(finalAttributes.GetOperation()) {
......
......@@ -136,6 +136,7 @@ func TestBanflunderAdmissionPlugin(t *testing.T) {
scenario.admissionInputResource,
"",
admission.Create,
false,
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