diff --git a/pkg/admission/admission_control.go b/pkg/admission/admission_control.go index 829e2684f56..2941a38c4bc 100644 --- a/pkg/admission/admission_control.go +++ b/pkg/admission/admission_control.go @@ -19,6 +19,7 @@ package admission import ( "errors" + apierrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" ) @@ -30,7 +31,7 @@ type stubAdmissionController struct { func (ac *stubAdmissionController) AdmissionControl(operation, kind, namespace string, object runtime.Object) (err error) { if !ac.admit { - err = errors.New("No changes allowed") + err = apierrors.NewConflict(kind, "name", errors.New("No changes allowed")) } return err } diff --git a/pkg/apiserver/apiserver_test.go b/pkg/apiserver/apiserver_test.go index 4adb9643ef8..e585ccffee1 100644 --- a/pkg/apiserver/apiserver_test.go +++ b/pkg/apiserver/apiserver_test.go @@ -477,6 +477,26 @@ func TestDelete(t *testing.T) { } } +func TestDeleteInvokesAdmissionControl(t *testing.T) { + storage := map[string]RESTStorage{} + simpleStorage := SimpleRESTStorage{} + ID := "id" + storage["simple"] = &simpleStorage + handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admission.NewAlwaysDenyController()) + server := httptest.NewServer(handler) + defer server.Close() + + client := http.Client{} + request, err := http.NewRequest("DELETE", server.URL+"/prefix/version/simple/"+ID, nil) + response, err := client.Do(request) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if response.StatusCode != http.StatusConflict { + t.Errorf("Unexpected response %#v", response) + } +} + func TestDeleteMissing(t *testing.T) { storage := map[string]RESTStorage{} ID := "id" @@ -537,6 +557,39 @@ func TestUpdate(t *testing.T) { } } +func TestUpdateInvokesAdmissionControl(t *testing.T) { + storage := map[string]RESTStorage{} + simpleStorage := SimpleRESTStorage{} + ID := "id" + storage["simple"] = &simpleStorage + selfLinker := &setTestSelfLinker{ + t: t, + expectedSet: "/prefix/version/simple/" + ID, + } + handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admission.NewAlwaysDenyController()) + server := httptest.NewServer(handler) + defer server.Close() + + item := &Simple{ + Other: "bar", + } + body, err := codec.Encode(item) + if err != nil { + // The following cases will fail, so die now + t.Fatalf("unexpected error: %v", err) + } + + client := http.Client{} + request, err := http.NewRequest("PUT", server.URL+"/prefix/version/simple/"+ID, bytes.NewReader(body)) + response, err := client.Do(request) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if response.StatusCode != http.StatusConflict { + t.Errorf("Unexpected response %#v", response) + } +} + func TestUpdateMissing(t *testing.T) { storage := map[string]RESTStorage{} ID := "id" @@ -615,6 +668,41 @@ func TestCreate(t *testing.T) { wait.Done() } +func TestCreateInvokesAdmissionControl(t *testing.T) { + wait := sync.WaitGroup{} + wait.Add(1) + simpleStorage := &SimpleRESTStorage{ + injectedFunction: func(obj runtime.Object) (returnObj runtime.Object, err error) { + wait.Wait() + return &Simple{}, nil + }, + } + handler := Handle(map[string]RESTStorage{ + "foo": simpleStorage, + }, codec, "/prefix", testVersion, selfLinker, admission.NewAlwaysDenyController()) + handler.(*defaultAPIServer).group.handler.asyncOpWait = 0 + server := httptest.NewServer(handler) + defer server.Close() + client := http.Client{} + + simple := &Simple{ + Other: "foo", + } + data, _ := codec.Encode(simple) + request, err := http.NewRequest("POST", server.URL+"/prefix/version/foo", bytes.NewBuffer(data)) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + response, err := client.Do(request) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if response.StatusCode != http.StatusConflict { + t.Errorf("Unexpected response %#v", response) + } +} + func TestCreateNotFound(t *testing.T) { handler := Handle(map[string]RESTStorage{ "simple": &SimpleRESTStorage{ diff --git a/plugin/pkg/admission/deny/admission.go b/plugin/pkg/admission/deny/admission.go index a96333bd96f..8f0f6243bdb 100644 --- a/plugin/pkg/admission/deny/admission.go +++ b/plugin/pkg/admission/deny/admission.go @@ -18,8 +18,10 @@ package deny import ( "errors" - "github.com/GoogleCloudPlatform/kubernetes/pkg/admission" "io" + + "github.com/GoogleCloudPlatform/kubernetes/pkg/admission" + apierrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" ) func init() { @@ -31,7 +33,7 @@ func init() { type alwaysDeny struct{} func (alwaysDeny) Admit(a admission.Attributes) (err error) { - return errors.New("You shall not pass!") + return apierrors.NewConflict(a.GetKind(), "", errors.New("No changes allowed")) } func NewAlwaysDeny() admission.Interface {