udpate admission for API groups

This commit is contained in:
deads2k 2015-11-30 12:02:04 -05:00
parent 33eda2ffb5
commit 3f045cf168
27 changed files with 151 additions and 110 deletions

View File

@ -17,22 +17,23 @@ limitations under the License.
package admission package admission
import ( import (
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/auth/user"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
) )
type attributesRecord struct { type attributesRecord struct {
kind string kind unversioned.GroupKind
namespace string namespace string
name string name string
resource string resource unversioned.GroupResource
subresource string subresource string
operation Operation operation Operation
object runtime.Object object runtime.Object
userInfo user.Info userInfo user.Info
} }
func NewAttributesRecord(object runtime.Object, kind, namespace, name, resource, subresource string, operation Operation, userInfo user.Info) Attributes { func NewAttributesRecord(object runtime.Object, kind unversioned.GroupKind, namespace, name string, resource unversioned.GroupResource, subresource string, operation Operation, userInfo user.Info) Attributes {
return &attributesRecord{ return &attributesRecord{
kind: kind, kind: kind,
namespace: namespace, namespace: namespace,
@ -45,7 +46,7 @@ func NewAttributesRecord(object runtime.Object, kind, namespace, name, resource,
} }
} }
func (record *attributesRecord) GetKind() string { func (record *attributesRecord) GetKind() unversioned.GroupKind {
return record.kind return record.kind
} }
@ -57,7 +58,7 @@ func (record *attributesRecord) GetName() string {
return record.name return record.name
} }
func (record *attributesRecord) GetResource() string { func (record *attributesRecord) GetResource() unversioned.GroupResource {
return record.resource return record.resource
} }

View File

@ -19,6 +19,8 @@ package admission
import ( import (
"fmt" "fmt"
"testing" "testing"
"k8s.io/kubernetes/pkg/api/unversioned"
) )
type FakeHandler struct { type FakeHandler struct {
@ -98,7 +100,7 @@ func TestAdmit(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
err := test.chain.Admit(NewAttributesRecord(nil, "", "", "", "", "", test.operation, nil)) err := test.chain.Admit(NewAttributesRecord(nil, unversioned.GroupKind{}, "", "", unversioned.GroupResource{}, "", test.operation, nil))
accepted := (err == nil) accepted := (err == nil)
if accepted != test.accept { if accepted != test.accept {
t.Errorf("%s: unexpected result of admit call: %v\n", test.name, accepted) t.Errorf("%s: unexpected result of admit call: %v\n", test.name, accepted)

View File

@ -19,17 +19,18 @@ package admission
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
apierrors "k8s.io/kubernetes/pkg/api/errors" apierrors "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/unversioned"
utilerrors "k8s.io/kubernetes/pkg/util/errors" utilerrors "k8s.io/kubernetes/pkg/util/errors"
) )
func extractKindName(a Attributes) (name, kind string, err error) { func extractKindName(a Attributes) (name string, kind unversioned.GroupKind, err error) {
name = "Unknown" name = "Unknown"
kind = a.GetKind() kind = a.GetKind()
obj := a.GetObject() obj := a.GetObject()
if obj != nil { if obj != nil {
objectMeta, err := api.ObjectMetaFor(obj) objectMeta, err := api.ObjectMetaFor(obj)
if err != nil { if err != nil {
return "", "", err return "", unversioned.GroupKind{}, err
} }
// this is necessary because name object name generation has not occurred yet // this is necessary because name object name generation has not occurred yet
@ -52,7 +53,7 @@ func NewForbidden(a Attributes, internalError error) error {
if err != nil { if err != nil {
return apierrors.NewInternalError(utilerrors.NewAggregate([]error{internalError, err})) return apierrors.NewInternalError(utilerrors.NewAggregate([]error{internalError, err}))
} }
return apierrors.NewForbidden(kind, name, internalError) return apierrors.NewForbidden(kind.Kind, name, internalError)
} }
// NewNotFound is a utility function to return a well-formatted admission control error response // NewNotFound is a utility function to return a well-formatted admission control error response
@ -61,5 +62,5 @@ func NewNotFound(a Attributes) error {
if err != nil { if err != nil {
return apierrors.NewInternalError(err) return apierrors.NewInternalError(err)
} }
return apierrors.NewNotFound(kind, name) return apierrors.NewNotFound(kind.Kind, name)
} }

View File

@ -17,6 +17,7 @@ limitations under the License.
package admission package admission
import ( import (
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/auth/user"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
) )
@ -31,7 +32,7 @@ type Attributes interface {
// GetNamespace is the namespace associated with the request (if any) // GetNamespace is the namespace associated with the request (if any)
GetNamespace() string GetNamespace() string
// GetResource is the name of the resource being requested. This is not the kind. For example: pods // GetResource is the name of the resource being requested. This is not the kind. For example: pods
GetResource() string GetResource() unversioned.GroupResource
// GetSubresource is the name of the subresource being requested. This is a different resource, scoped to the parent resource, but it may have a different kind. // GetSubresource is the name of the subresource being requested. This is a different resource, scoped to the parent resource, but it may have a different kind.
// For instance, /pods has the resource "pods" and the kind "Pod", while /pods/foo/status has the resource "pods", the sub resource "status", and the kind "Pod" // For instance, /pods has the resource "pods" and the kind "Pod", while /pods/foo/status has the resource "pods", the sub resource "status", and the kind "Pod"
// (because status operates on pods). The binding resource for a pod though may be /pods/foo/binding, which has resource "pods", subresource "binding", and kind "Binding". // (because status operates on pods). The binding resource for a pod though may be /pods/foo/binding, which has resource "pods", subresource "binding", and kind "Binding".
@ -41,7 +42,7 @@ type Attributes interface {
// 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
// GetKind is the type of object being manipulated. For example: Pod // GetKind is the type of object being manipulated. For example: Pod
GetKind() string GetKind() unversioned.GroupKind
// GetUserInfo is information about the requesting user // GetUserInfo is information about the requesting user
GetUserInfo() user.Info GetUserInfo() user.Info
} }

View File

@ -32,6 +32,11 @@ func Kind(kind string) unversioned.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind() return SchemeGroupVersion.WithKind(kind).GroupKind()
} }
// Resource takes an unqualified resource and returns back a Group qualified GroupResource
func Resource(resource string) unversioned.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
func init() { func init() {
Scheme.AddKnownTypes(SchemeGroupVersion, Scheme.AddKnownTypes(SchemeGroupVersion,
&Pod{}, &Pod{},

View File

@ -22,6 +22,17 @@ import (
"strings" "strings"
) )
// GroupResource specifies a Group and a Resource, but does not force a version. This is useful for identifying
// concepts during lookup stages without having partially valid types
type GroupResource struct {
Group string
Resource string
}
func (gr *GroupResource) String() string {
return strings.Join([]string{gr.Group, ", Resource=", gr.Resource}, "")
}
// GroupVersionResource unambiguously identifies a resource. It doesn't anonymously include GroupVersion // GroupVersionResource unambiguously identifies a resource. It doesn't anonymously include GroupVersion
// to avoid automatic coersion. It doesn't use a GroupVersion to avoid custom marshalling // to avoid automatic coersion. It doesn't use a GroupVersion to avoid custom marshalling
type GroupVersionResource struct { type GroupVersionResource struct {
@ -30,12 +41,16 @@ type GroupVersionResource struct {
Resource string Resource string
} }
func (gvr GroupVersionResource) GroupResource() GroupResource {
return GroupResource{Group: gvr.Group, Resource: gvr.Resource}
}
func (gvr GroupVersionResource) GroupVersion() GroupVersion { func (gvr GroupVersionResource) GroupVersion() GroupVersion {
return GroupVersion{Group: gvr.Group, Version: gvr.Version} return GroupVersion{Group: gvr.Group, Version: gvr.Version}
} }
func (gvr *GroupVersionResource) String() string { func (gvr *GroupVersionResource) String() string {
return gvr.Group + "/" + gvr.Version + ", Resource=" + gvr.Resource return strings.Join([]string{gvr.Group, "/", gvr.Version, ", Resource=", gvr.Resource}, "")
} }
// GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying // GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying

View File

@ -33,6 +33,11 @@ func Kind(kind string) unversioned.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind() return SchemeGroupVersion.WithKind(kind).GroupKind()
} }
// Resource takes an unqualified resource and returns back a Group qualified GroupResource
func Resource(resource string) unversioned.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
func addKnownTypes() { func addKnownTypes() {
// TODO this will get cleaned up with the scheme types are fixed // TODO this will get cleaned up with the scheme types are fixed
api.Scheme.AddKnownTypes(SchemeGroupVersion, api.Scheme.AddKnownTypes(SchemeGroupVersion,

View File

@ -29,6 +29,11 @@ func Kind(kind string) unversioned.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind() return SchemeGroupVersion.WithKind(kind).GroupKind()
} }
// Resource takes an unqualified resource and returns back a Group qualified GroupResource
func Resource(resource string) unversioned.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
func init() { func init() {
// Register the API. // Register the API.
addKnownTypes() addKnownTypes()

View File

@ -34,6 +34,11 @@ func Kind(kind string) unversioned.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind() return SchemeGroupVersion.WithKind(kind).GroupKind()
} }
// Resource takes an unqualified resource and returns back a Group qualified GroupResource
func Resource(resource string) unversioned.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
// Adds the list of known types to api.Scheme. // Adds the list of known types to api.Scheme.
func addKnownTypes() { func addKnownTypes() {
// TODO this will get cleaned up with the scheme types are fixed // TODO this will get cleaned up with the scheme types are fixed

View File

@ -186,7 +186,7 @@ func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admissi
} }
userInfo, _ := api.UserFrom(ctx) userInfo, _ := api.UserFrom(ctx)
err = admit.Admit(admission.NewAttributesRecord(connectRequest, scope.Kind.Kind, namespace, name, scope.Resource.Resource, scope.Subresource, admission.Connect, userInfo)) err = admit.Admit(admission.NewAttributesRecord(connectRequest, scope.Kind.GroupKind(), namespace, name, scope.Resource.GroupResource(), scope.Subresource, admission.Connect, userInfo))
if err != nil { if err != nil {
errorJSON(err, scope.Codec, w) errorJSON(err, scope.Codec, w)
return return
@ -361,7 +361,7 @@ func createHandler(r rest.NamedCreater, scope RequestScope, typer runtime.Object
if admit != nil && admit.Handles(admission.Create) { if admit != nil && admit.Handles(admission.Create) {
userInfo, _ := api.UserFrom(ctx) userInfo, _ := api.UserFrom(ctx)
err = admit.Admit(admission.NewAttributesRecord(obj, scope.Kind.Kind, namespace, name, scope.Resource.Resource, scope.Subresource, admission.Create, userInfo)) err = admit.Admit(admission.NewAttributesRecord(obj, scope.Kind.GroupKind(), namespace, name, scope.Resource.GroupResource(), scope.Subresource, admission.Create, userInfo))
if err != nil { if err != nil {
errorJSON(err, scope.Codec, w) errorJSON(err, scope.Codec, w)
return return
@ -432,7 +432,7 @@ func PatchResource(r rest.Patcher, scope RequestScope, typer runtime.ObjectTyper
if admit.Handles(admission.Update) { if admit.Handles(admission.Update) {
userInfo, _ := api.UserFrom(ctx) userInfo, _ := api.UserFrom(ctx)
err = admit.Admit(admission.NewAttributesRecord(obj, scope.Kind.Kind, namespace, name, scope.Resource.Resource, scope.Subresource, admission.Update, userInfo)) err = admit.Admit(admission.NewAttributesRecord(obj, scope.Kind.GroupKind(), namespace, name, scope.Resource.GroupResource(), scope.Subresource, admission.Update, userInfo))
if err != nil { if err != nil {
errorJSON(err, scope.Codec, w) errorJSON(err, scope.Codec, w)
return return
@ -599,7 +599,7 @@ func UpdateResource(r rest.Updater, scope RequestScope, typer runtime.ObjectType
if admit != nil && admit.Handles(admission.Update) { if admit != nil && admit.Handles(admission.Update) {
userInfo, _ := api.UserFrom(ctx) userInfo, _ := api.UserFrom(ctx)
err = admit.Admit(admission.NewAttributesRecord(obj, scope.Kind.Kind, namespace, name, scope.Resource.Resource, scope.Subresource, admission.Update, userInfo)) err = admit.Admit(admission.NewAttributesRecord(obj, scope.Kind.GroupKind(), namespace, name, scope.Resource.GroupResource(), scope.Subresource, admission.Update, userInfo))
if err != nil { if err != nil {
errorJSON(err, scope.Codec, w) errorJSON(err, scope.Codec, w)
return return
@ -664,7 +664,7 @@ func DeleteResource(r rest.GracefulDeleter, checkBody bool, scope RequestScope,
if admit != nil && admit.Handles(admission.Delete) { if admit != nil && admit.Handles(admission.Delete) {
userInfo, _ := api.UserFrom(ctx) userInfo, _ := api.UserFrom(ctx)
err = admit.Admit(admission.NewAttributesRecord(nil, scope.Kind.Kind, namespace, name, scope.Resource.Resource, scope.Subresource, admission.Delete, userInfo)) err = admit.Admit(admission.NewAttributesRecord(nil, scope.Kind.GroupKind(), namespace, name, scope.Resource.GroupResource(), scope.Subresource, admission.Delete, userInfo))
if err != nil { if err != nil {
errorJSON(err, scope.Codec, w) errorJSON(err, scope.Codec, w)
return return

View File

@ -20,11 +20,12 @@ import (
"testing" "testing"
"k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
) )
func TestAdmission(t *testing.T) { func TestAdmission(t *testing.T) {
handler := NewAlwaysDeny() handler := NewAlwaysDeny()
err := handler.Admit(admission.NewAttributesRecord(nil, "kind", "namespace", "name", "resource", "subresource", admission.Create, nil)) err := handler.Admit(admission.NewAttributesRecord(nil, api.Kind("kind"), "namespace", "name", api.Resource("resource"), "subresource", admission.Create, nil))
if err == nil { if err == nil {
t.Errorf("Expected error returned from admission handler") t.Errorf("Expected error returned from admission handler")
} }

View File

@ -101,7 +101,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.Admit(admission.NewAttributesRecord(req, "Pod", "test", "name", "pods", "exec", admission.Connect, nil)) err := handler.Admit(admission.NewAttributesRecord(req, api.Kind("Pod"), "test", "name", api.Resource("pods"), "exec", admission.Connect, 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)
} }
@ -113,7 +113,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.Admit(admission.NewAttributesRecord(req, "Pod", "test", "name", "pods", "attach", admission.Connect, nil)) err := handler.Admit(admission.NewAttributesRecord(req, api.Kind("Pod"), "test", "name", api.Resource("pods"), "attach", admission.Connect, 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)
} }

View File

@ -73,7 +73,7 @@ func newInitialResources(source dataSource, percentile int64, nsOnly bool) admis
func (ir initialResources) Admit(a admission.Attributes) (err error) { func (ir initialResources) Admit(a admission.Attributes) (err error) {
// Ignore all calls to subresources or resources other than pods. // Ignore all calls to subresources or resources other than pods.
if a.GetSubresource() != "" || a.GetResource() != string(api.ResourcePods) { if a.GetSubresource() != "" || a.GetResource() != api.Resource("pods") {
return nil return nil
} }
pod, ok := a.GetObject().(*api.Pod) pod, ok := a.GetObject().(*api.Pod)

View File

@ -107,7 +107,7 @@ func expectNoAnnotation(t *testing.T, pod *api.Pod) {
func admit(t *testing.T, ir admission.Interface, pods []*api.Pod) { func admit(t *testing.T, ir admission.Interface, pods []*api.Pod) {
for i := range pods { for i := range pods {
p := pods[i] p := pods[i]
if err := ir.Admit(admission.NewAttributesRecord(p, "Pod", "test", p.ObjectMeta.Name, "pods", "", admission.Create, nil)); err != nil { if err := ir.Admit(admission.NewAttributesRecord(p, api.Kind("Pod"), "test", p.ObjectMeta.Name, api.Resource("pods"), "", admission.Create, nil)); err != nil {
t.Error(err) t.Error(err)
} }
} }

View File

@ -61,7 +61,6 @@ func (l *limitRanger) Admit(a admission.Attributes) (err error) {
} }
obj := a.GetObject() obj := a.GetObject()
resource := a.GetResource()
name := "Unknown" name := "Unknown"
if obj != nil { if obj != nil {
name, _ = meta.NewAccessor().Name(obj) name, _ = meta.NewAccessor().Name(obj)
@ -78,7 +77,7 @@ func (l *limitRanger) Admit(a admission.Attributes) (err error) {
} }
items, err := l.indexer.Index("namespace", key) items, err := l.indexer.Index("namespace", key)
if err != nil { if err != nil {
return admission.NewForbidden(a, fmt.Errorf("Unable to %s %s at this time because there was an error enforcing limit ranges", a.GetOperation(), resource)) return admission.NewForbidden(a, fmt.Errorf("Unable to %s %v at this time because there was an error enforcing limit ranges", a.GetOperation(), a.GetResource()))
} }
if len(items) == 0 { if len(items) == 0 {
return nil return nil
@ -87,7 +86,7 @@ func (l *limitRanger) Admit(a admission.Attributes) (err error) {
// ensure it meets each prescribed min/max // ensure it meets each prescribed min/max
for i := range items { for i := range items {
limitRange := items[i].(*api.LimitRange) limitRange := items[i].(*api.LimitRange)
err = l.limitFunc(limitRange, a.GetResource(), a.GetObject()) err = l.limitFunc(limitRange, a.GetResource().Resource, a.GetObject())
if err != nil { if err != nil {
return admission.NewForbidden(a, err) return admission.NewForbidden(a, err)
} }

View File

@ -442,12 +442,12 @@ func TestLimitRangerIgnoresSubresource(t *testing.T) {
testPod := validPod("testPod", 1, api.ResourceRequirements{}) testPod := validPod("testPod", 1, api.ResourceRequirements{})
indexer.Add(&limitRange) indexer.Add(&limitRange)
err := handler.Admit(admission.NewAttributesRecord(&testPod, "Pod", limitRange.Namespace, "testPod", "pods", "", admission.Update, nil)) err := handler.Admit(admission.NewAttributesRecord(&testPod, api.Kind("Pod"), limitRange.Namespace, "testPod", api.Resource("pods"), "", admission.Update, 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.Admit(admission.NewAttributesRecord(&testPod, "Pod", limitRange.Namespace, "testPod", "pods", "status", admission.Update, nil)) err = handler.Admit(admission.NewAttributesRecord(&testPod, api.Kind("Pod"), limitRange.Namespace, "testPod", api.Resource("pods"), "status", admission.Update, 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)
} }

View File

@ -46,7 +46,7 @@ type provision struct {
} }
func (p *provision) Admit(a admission.Attributes) (err error) { func (p *provision) Admit(a admission.Attributes) (err error) {
gvk, err := api.RESTMapper.KindFor(a.GetResource()) gvk, err := api.RESTMapper.KindFor(a.GetResource().Resource)
if err != nil { if err != nil {
return admission.NewForbidden(a, err) return admission.NewForbidden(a, err)
} }

View File

@ -42,7 +42,7 @@ func TestAdmission(t *testing.T) {
Containers: []api.Container{{Name: "ctr", Image: "image"}}, Containers: []api.Container{{Name: "ctr", Image: "image"}},
}, },
} }
err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Create, nil)) err := handler.Admit(admission.NewAttributesRecord(&pod, api.Kind("Pod"), pod.Namespace, pod.Name, api.Resource("pods"), "", admission.Create, nil))
if err != nil { if err != nil {
t.Errorf("Unexpected error returned from admission handler") t.Errorf("Unexpected error returned from admission handler")
} }
@ -74,7 +74,7 @@ func TestAdmissionNamespaceExists(t *testing.T) {
Containers: []api.Container{{Name: "ctr", Image: "image"}}, Containers: []api.Container{{Name: "ctr", Image: "image"}},
}, },
} }
err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Create, nil)) err := handler.Admit(admission.NewAttributesRecord(&pod, api.Kind("Pod"), pod.Namespace, pod.Name, api.Resource("pods"), "", admission.Create, nil))
if err != nil { if err != nil {
t.Errorf("Unexpected error returned from admission handler") t.Errorf("Unexpected error returned from admission handler")
} }
@ -95,7 +95,7 @@ func TestIgnoreAdmission(t *testing.T) {
Containers: []api.Container{{Name: "ctr", Image: "image"}}, Containers: []api.Container{{Name: "ctr", Image: "image"}},
}, },
} }
err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Update, nil)) err := handler.Admit(admission.NewAttributesRecord(&pod, api.Kind("Pod"), pod.Namespace, pod.Name, api.Resource("pods"), "", admission.Update, nil))
if err != nil { if err != nil {
t.Errorf("Unexpected error returned from admission handler") t.Errorf("Unexpected error returned from admission handler")
} }
@ -124,7 +124,7 @@ func TestAdmissionNamespaceExistsUnknownToHandler(t *testing.T) {
Containers: []api.Container{{Name: "ctr", Image: "image"}}, Containers: []api.Container{{Name: "ctr", Image: "image"}},
}, },
} }
err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Create, nil)) err := handler.Admit(admission.NewAttributesRecord(&pod, api.Kind("Pod"), pod.Namespace, pod.Name, api.Resource("pods"), "", admission.Create, nil))
if err != nil { if err != nil {
t.Errorf("Unexpected error returned from admission handler") t.Errorf("Unexpected error returned from admission handler")
} }

View File

@ -47,7 +47,7 @@ type exists struct {
} }
func (e *exists) Admit(a admission.Attributes) (err error) { func (e *exists) Admit(a admission.Attributes) (err error) {
gvk, err := api.RESTMapper.KindFor(a.GetResource()) gvk, err := api.RESTMapper.KindFor(a.GetResource().Resource)
if err != nil { if err != nil {
return errors.NewInternalError(err) return errors.NewInternalError(err)
} }

View File

@ -51,11 +51,11 @@ type lifecycle struct {
func (l *lifecycle) Admit(a admission.Attributes) (err error) { func (l *lifecycle) Admit(a admission.Attributes) (err error) {
// prevent deletion of immortal namespaces // prevent deletion of immortal namespaces
if a.GetOperation() == admission.Delete && a.GetKind() == "Namespace" && l.immortalNamespaces.Has(a.GetName()) { if a.GetOperation() == admission.Delete && a.GetKind() == api.Kind("Namespace") && l.immortalNamespaces.Has(a.GetName()) {
return errors.NewForbidden(a.GetKind(), a.GetName(), fmt.Errorf("this namespace may not be deleted")) return errors.NewForbidden(a.GetKind().Kind, a.GetName(), fmt.Errorf("this namespace may not be deleted"))
} }
gvk, err := api.RESTMapper.KindFor(a.GetResource()) gvk, err := api.RESTMapper.KindFor(a.GetResource().Resource)
if err != nil { if err != nil {
return errors.NewInternalError(err) return errors.NewInternalError(err)
} }

View File

@ -75,7 +75,7 @@ func TestAdmission(t *testing.T) {
Containers: []api.Container{{Name: "ctr", Image: "image"}}, Containers: []api.Container{{Name: "ctr", Image: "image"}},
}, },
} }
err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Create, nil)) err := handler.Admit(admission.NewAttributesRecord(&pod, api.Kind("Pod"), pod.Namespace, pod.Name, api.Resource("pods"), "", admission.Create, nil))
if err != nil { if err != nil {
t.Errorf("Unexpected error returned from admission handler: %v", err) t.Errorf("Unexpected error returned from admission handler: %v", err)
} }
@ -87,47 +87,47 @@ func TestAdmission(t *testing.T) {
store.Add(namespaceObj) store.Add(namespaceObj)
// verify create operations in the namespace cause an error // verify create operations in the namespace cause an error
err = handler.Admit(admission.NewAttributesRecord(&pod, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Create, nil)) err = handler.Admit(admission.NewAttributesRecord(&pod, api.Kind("Pod"), pod.Namespace, pod.Name, api.Resource("pods"), "", admission.Create, nil))
if err == nil { if err == nil {
t.Errorf("Expected error rejecting creates in a namespace when it is terminating") t.Errorf("Expected error rejecting creates in a namespace when it is terminating")
} }
// verify update operations in the namespace can proceed // verify update operations in the namespace can proceed
err = handler.Admit(admission.NewAttributesRecord(&pod, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Update, nil)) err = handler.Admit(admission.NewAttributesRecord(&pod, api.Kind("Pod"), pod.Namespace, pod.Name, api.Resource("pods"), "", admission.Update, nil))
if err != nil { if err != nil {
t.Errorf("Unexpected error returned from admission handler: %v", err) t.Errorf("Unexpected error returned from admission handler: %v", err)
} }
// verify delete operations in the namespace can proceed // verify delete operations in the namespace can proceed
err = handler.Admit(admission.NewAttributesRecord(nil, "Pod", pod.Namespace, pod.Name, "pods", "", admission.Delete, nil)) err = handler.Admit(admission.NewAttributesRecord(nil, api.Kind("Pod"), pod.Namespace, pod.Name, api.Resource("pods"), "", admission.Delete, nil))
if err != nil { if err != nil {
t.Errorf("Unexpected error returned from admission handler: %v", err) t.Errorf("Unexpected error returned from admission handler: %v", err)
} }
// verify delete of namespace default can never proceed // verify delete of namespace default can never proceed
err = handler.Admit(admission.NewAttributesRecord(nil, "Namespace", "", api.NamespaceDefault, "namespaces", "", admission.Delete, nil)) err = handler.Admit(admission.NewAttributesRecord(nil, api.Kind("Namespace"), "", api.NamespaceDefault, api.Resource("namespaces"), "", admission.Delete, nil))
if err == nil { if err == nil {
t.Errorf("Expected an error that this namespace can never be deleted") t.Errorf("Expected an error that this namespace can never be deleted")
} }
// verify delete of namespace other than default can proceed // verify delete of namespace other than default can proceed
err = handler.Admit(admission.NewAttributesRecord(nil, "Namespace", "", "other", "namespaces", "", admission.Delete, nil)) err = handler.Admit(admission.NewAttributesRecord(nil, api.Kind("Namespace"), "", "other", api.Resource("namespaces"), "", admission.Delete, nil))
if err != nil { if err != nil {
t.Errorf("Did not expect an error %v", err) t.Errorf("Did not expect an error %v", err)
} }
// verify create/update/delete of object in non-existant namespace throws error // verify create/update/delete of object in non-existant namespace throws error
err = handler.Admit(admission.NewAttributesRecord(&badPod, "Pod", badPod.Namespace, badPod.Name, "pods", "", admission.Create, nil)) err = handler.Admit(admission.NewAttributesRecord(&badPod, api.Kind("Pod"), badPod.Namespace, badPod.Name, api.Resource("pods"), "", admission.Create, nil))
if err == nil { if err == nil {
t.Errorf("Expected an aerror that objects cannot be created in non-existant namespaces", err) t.Errorf("Expected an aerror that objects cannot be created in non-existant namespaces", err)
} }
err = handler.Admit(admission.NewAttributesRecord(&badPod, "Pod", badPod.Namespace, badPod.Name, "pods", "", admission.Update, nil)) err = handler.Admit(admission.NewAttributesRecord(&badPod, api.Kind("Pod"), badPod.Namespace, badPod.Name, api.Resource("pods"), "", admission.Update, nil))
if err == nil { if err == nil {
t.Errorf("Expected an aerror that objects cannot be updated in non-existant namespaces", err) t.Errorf("Expected an aerror that objects cannot be updated in non-existant namespaces", err)
} }
err = handler.Admit(admission.NewAttributesRecord(&badPod, "Pod", badPod.Namespace, badPod.Name, "pods", "", admission.Delete, nil)) err = handler.Admit(admission.NewAttributesRecord(&badPod, api.Kind("Pod"), badPod.Namespace, badPod.Name, api.Resource("pods"), "", admission.Delete, nil))
if err == nil { if err == nil {
t.Errorf("Expected an aerror that objects cannot be deleted in non-existant namespaces", err) t.Errorf("Expected an aerror that objects cannot be deleted in non-existant namespaces", err)
} }

View File

@ -69,13 +69,13 @@ func createResourceQuota(client client.Interface, indexer cache.Indexer) admissi
} }
} }
var resourceToResourceName = map[string]api.ResourceName{ var resourceToResourceName = map[unversioned.GroupResource]api.ResourceName{
"pods": api.ResourcePods, api.Resource("pods"): api.ResourcePods,
"services": api.ResourceServices, api.Resource("services"): api.ResourceServices,
"replicationcontrollers": api.ResourceReplicationControllers, api.Resource("replicationcontrollers"): api.ResourceReplicationControllers,
"resourcequotas": api.ResourceQuotas, api.Resource("resourcequotas"): api.ResourceQuotas,
"secrets": api.ResourceSecrets, api.Resource("secrets"): api.ResourceSecrets,
"persistentvolumeclaims": api.ResourcePersistentVolumeClaims, api.Resource("persistentvolumeclaims"): api.ResourcePersistentVolumeClaims,
} }
func (q *quota) Admit(a admission.Attributes) (err error) { func (q *quota) Admit(a admission.Attributes) (err error) {
@ -169,7 +169,7 @@ func (q *quota) Admit(a admission.Attributes) (err error) {
func IncrementUsage(a admission.Attributes, status *api.ResourceQuotaStatus, client client.Interface) (bool, error) { func IncrementUsage(a admission.Attributes, status *api.ResourceQuotaStatus, client client.Interface) (bool, error) {
// on update, the only resource that can modify the value of a quota is pods // on update, the only resource that can modify the value of a quota is pods
// so if your not a pod, we exit quickly // so if your not a pod, we exit quickly
if a.GetOperation() == admission.Update && a.GetResource() != "pods" { if a.GetOperation() == admission.Update && a.GetResource() != api.Resource("pods") {
return false, nil return false, nil
} }
@ -198,7 +198,7 @@ func IncrementUsage(a admission.Attributes, status *api.ResourceQuotaStatus, cli
} }
} }
if a.GetResource() == "pods" { if a.GetResource() == api.Resource("pods") {
for _, resourceName := range []api.ResourceName{api.ResourceMemory, api.ResourceCPU} { for _, resourceName := range []api.ResourceName{api.ResourceMemory, api.ResourceCPU} {
// ignore tracking the resource if it's not in the quota document // ignore tracking the resource if it's not in the quota document

View File

@ -23,6 +23,7 @@ import (
"k8s.io/kubernetes/pkg/admission" "k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/client/cache" "k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/client/unversioned/testclient"
resourcequotacontroller "k8s.io/kubernetes/pkg/controller/resourcequota" resourcequotacontroller "k8s.io/kubernetes/pkg/controller/resourcequota"
@ -65,7 +66,7 @@ func validPod(name string, numContainers int, resources api.ResourceRequirements
func TestAdmissionIgnoresDelete(t *testing.T) { func TestAdmissionIgnoresDelete(t *testing.T) {
namespace := "default" namespace := "default"
handler := createResourceQuota(&testclient.Fake{}, nil) handler := createResourceQuota(&testclient.Fake{}, nil)
err := handler.Admit(admission.NewAttributesRecord(nil, "Pod", namespace, "name", "pods", "", admission.Delete, nil)) err := handler.Admit(admission.NewAttributesRecord(nil, api.Kind("Pod"), namespace, "name", api.Resource("pods"), "", admission.Delete, nil))
if err != nil { if err != nil {
t.Errorf("ResourceQuota should admit all deletes: %v", err) t.Errorf("ResourceQuota should admit all deletes: %v", err)
} }
@ -88,12 +89,12 @@ func TestAdmissionIgnoresSubresources(t *testing.T) {
indexer.Add(quota) indexer.Add(quota)
newPod := validPod("123", 1, getResourceRequirements(getResourceList("100m", "2Gi"), getResourceList("", ""))) newPod := validPod("123", 1, getResourceRequirements(getResourceList("100m", "2Gi"), getResourceList("", "")))
err := handler.Admit(admission.NewAttributesRecord(newPod, "Pod", newPod.Namespace, newPod.Name, "pods", "", admission.Create, nil)) err := handler.Admit(admission.NewAttributesRecord(newPod, api.Kind("Pod"), newPod.Namespace, newPod.Name, api.Resource("pods"), "", admission.Create, nil))
if err == nil { if err == nil {
t.Errorf("Expected an error because the pod exceeded allowed quota") t.Errorf("Expected an error because the pod exceeded allowed quota")
} }
err = handler.Admit(admission.NewAttributesRecord(newPod, "Pod", newPod.Namespace, newPod.Name, "pods", "subresource", admission.Create, nil)) err = handler.Admit(admission.NewAttributesRecord(newPod, api.Kind("Pod"), newPod.Namespace, newPod.Name, api.Resource("pods"), "subresource", admission.Create, nil))
if err != nil { if err != nil {
t.Errorf("Did not expect an error because the action went to a subresource: %v", err) t.Errorf("Did not expect an error because the action went to a subresource: %v", err)
} }
@ -184,7 +185,7 @@ func TestIncrementUsagePodResources(t *testing.T) {
status.Hard[item.resourceName] = item.hard status.Hard[item.resourceName] = item.hard
status.Used[item.resourceName] = *used status.Used[item.resourceName] = *used
dirty, err := IncrementUsage(admission.NewAttributesRecord(item.input, "Pod", item.input.Namespace, item.input.Name, "pods", "", admission.Create, nil), status, client) dirty, err := IncrementUsage(admission.NewAttributesRecord(item.input, api.Kind("Pod"), item.input.Namespace, item.input.Name, api.Resource("pods"), "", admission.Create, nil), status, client)
if err == nil && item.expectedError { if err == nil && item.expectedError {
t.Errorf("Test %s, expected error", item.testName) t.Errorf("Test %s, expected error", item.testName)
} }
@ -214,7 +215,7 @@ func TestIncrementUsagePods(t *testing.T) {
r := api.ResourcePods r := api.ResourcePods
status.Hard[r] = resource.MustParse("2") status.Hard[r] = resource.MustParse("2")
status.Used[r] = resource.MustParse("1") status.Used[r] = resource.MustParse("1")
dirty, err := IncrementUsage(admission.NewAttributesRecord(&api.Pod{}, "Pod", pod.Namespace, "new-pod", "pods", "", admission.Create, nil), status, client) dirty, err := IncrementUsage(admission.NewAttributesRecord(&api.Pod{}, api.Kind("Pod"), pod.Namespace, "new-pod", api.Resource("pods"), "", admission.Create, nil), status, client)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
@ -238,7 +239,7 @@ func TestExceedUsagePods(t *testing.T) {
r := api.ResourcePods r := api.ResourcePods
status.Hard[r] = resource.MustParse("1") status.Hard[r] = resource.MustParse("1")
status.Used[r] = resource.MustParse("1") status.Used[r] = resource.MustParse("1")
_, err := IncrementUsage(admission.NewAttributesRecord(&api.Pod{}, "Pod", pod.Namespace, "name", "pods", "", admission.Create, nil), status, client) _, err := IncrementUsage(admission.NewAttributesRecord(&api.Pod{}, api.Kind("Pod"), pod.Namespace, "name", api.Resource("pods"), "", admission.Create, nil), status, client)
if err == nil { if err == nil {
t.Errorf("Expected error because this would exceed your quota") t.Errorf("Expected error because this would exceed your quota")
} }
@ -260,7 +261,7 @@ func TestIncrementUsageServices(t *testing.T) {
r := api.ResourceServices r := api.ResourceServices
status.Hard[r] = resource.MustParse("2") status.Hard[r] = resource.MustParse("2")
status.Used[r] = resource.MustParse("1") status.Used[r] = resource.MustParse("1")
dirty, err := IncrementUsage(admission.NewAttributesRecord(&api.Service{}, "Service", namespace, "name", "services", "", admission.Create, nil), status, client) dirty, err := IncrementUsage(admission.NewAttributesRecord(&api.Service{}, api.Kind("Service"), namespace, "name", api.Resource("services"), "", admission.Create, nil), status, client)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
@ -289,7 +290,7 @@ func TestExceedUsageServices(t *testing.T) {
r := api.ResourceServices r := api.ResourceServices
status.Hard[r] = resource.MustParse("1") status.Hard[r] = resource.MustParse("1")
status.Used[r] = resource.MustParse("1") status.Used[r] = resource.MustParse("1")
_, err := IncrementUsage(admission.NewAttributesRecord(&api.Service{}, "Service", namespace, "name", "services", "", admission.Create, nil), status, client) _, err := IncrementUsage(admission.NewAttributesRecord(&api.Service{}, api.Kind("Service"), namespace, "name", api.Resource("services"), "", admission.Create, nil), status, client)
if err == nil { if err == nil {
t.Errorf("Expected error because this would exceed usage") t.Errorf("Expected error because this would exceed usage")
} }
@ -311,7 +312,7 @@ func TestIncrementUsageReplicationControllers(t *testing.T) {
r := api.ResourceReplicationControllers r := api.ResourceReplicationControllers
status.Hard[r] = resource.MustParse("2") status.Hard[r] = resource.MustParse("2")
status.Used[r] = resource.MustParse("1") status.Used[r] = resource.MustParse("1")
dirty, err := IncrementUsage(admission.NewAttributesRecord(&api.ReplicationController{}, "ReplicationController", namespace, "name", "replicationcontrollers", "", admission.Create, nil), status, client) dirty, err := IncrementUsage(admission.NewAttributesRecord(&api.ReplicationController{}, api.Kind("ReplicationController"), namespace, "name", api.Resource("replicationcontrollers"), "", admission.Create, nil), status, client)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
@ -340,7 +341,7 @@ func TestExceedUsageReplicationControllers(t *testing.T) {
r := api.ResourceReplicationControllers r := api.ResourceReplicationControllers
status.Hard[r] = resource.MustParse("1") status.Hard[r] = resource.MustParse("1")
status.Used[r] = resource.MustParse("1") status.Used[r] = resource.MustParse("1")
_, err := IncrementUsage(admission.NewAttributesRecord(&api.ReplicationController{}, "ReplicationController", namespace, "name", "replicationcontrollers", "", admission.Create, nil), status, client) _, err := IncrementUsage(admission.NewAttributesRecord(&api.ReplicationController{}, api.Kind("ReplicationController"), namespace, "name", api.Resource("replicationcontrollers"), "", admission.Create, nil), status, client)
if err == nil { if err == nil {
t.Errorf("Expected error for exceeding hard limits") t.Errorf("Expected error for exceeding hard limits")
} }
@ -362,7 +363,7 @@ func TestExceedUsageSecrets(t *testing.T) {
r := api.ResourceSecrets r := api.ResourceSecrets
status.Hard[r] = resource.MustParse("1") status.Hard[r] = resource.MustParse("1")
status.Used[r] = resource.MustParse("1") status.Used[r] = resource.MustParse("1")
_, err := IncrementUsage(admission.NewAttributesRecord(&api.Secret{}, "Secret", namespace, "name", "secrets", "", admission.Create, nil), status, client) _, err := IncrementUsage(admission.NewAttributesRecord(&api.Secret{}, api.Kind("Secret"), namespace, "name", api.Resource("secrets"), "", admission.Create, nil), status, client)
if err == nil { if err == nil {
t.Errorf("Expected error for exceeding hard limits") t.Errorf("Expected error for exceeding hard limits")
} }
@ -384,7 +385,7 @@ func TestExceedUsagePersistentVolumeClaims(t *testing.T) {
r := api.ResourcePersistentVolumeClaims r := api.ResourcePersistentVolumeClaims
status.Hard[r] = resource.MustParse("1") status.Hard[r] = resource.MustParse("1")
status.Used[r] = resource.MustParse("1") status.Used[r] = resource.MustParse("1")
_, err := IncrementUsage(admission.NewAttributesRecord(&api.PersistentVolumeClaim{}, "PersistentVolumeClaim", namespace, "name", "persistentvolumeclaims", "", admission.Create, nil), status, client) _, err := IncrementUsage(admission.NewAttributesRecord(&api.PersistentVolumeClaim{}, api.Kind("PersistentVolumeClaim"), namespace, "name", api.Resource("persistentvolumeclaims"), "", admission.Create, nil), status, client)
if err == nil { if err == nil {
t.Errorf("Expected error for exceeding hard limits") t.Errorf("Expected error for exceeding hard limits")
} }
@ -392,34 +393,34 @@ func TestExceedUsagePersistentVolumeClaims(t *testing.T) {
func TestIncrementUsageOnUpdateIgnoresNonPodResources(t *testing.T) { func TestIncrementUsageOnUpdateIgnoresNonPodResources(t *testing.T) {
testCase := []struct { testCase := []struct {
kind string kind unversioned.GroupKind
resource string resource unversioned.GroupResource
subresource string subresource string
object runtime.Object object runtime.Object
}{ }{
{ {
kind: "Service", kind: api.Kind("Service"),
resource: "services", resource: api.Resource("services"),
object: &api.Service{}, object: &api.Service{},
}, },
{ {
kind: "ReplicationController", kind: api.Kind("ReplicationController"),
resource: "replicationcontrollers", resource: api.Resource("replicationcontrollers"),
object: &api.ReplicationController{}, object: &api.ReplicationController{},
}, },
{ {
kind: "ResourceQuota", kind: api.Kind("ResourceQuota"),
resource: "resourcequotas", resource: api.Resource("resourcequotas"),
object: &api.ResourceQuota{}, object: &api.ResourceQuota{},
}, },
{ {
kind: "Secret", kind: api.Kind("Secret"),
resource: "secrets", resource: api.Resource("secrets"),
object: &api.Secret{}, object: &api.Secret{},
}, },
{ {
kind: "PersistentVolumeClaim", kind: api.Kind("PersistentVolumeClaim"),
resource: "persistentvolumeclaims", resource: api.Resource("persistentvolumeclaims"),
object: &api.PersistentVolumeClaim{}, object: &api.PersistentVolumeClaim{},
}, },
} }
@ -430,7 +431,7 @@ func TestIncrementUsageOnUpdateIgnoresNonPodResources(t *testing.T) {
Hard: api.ResourceList{}, Hard: api.ResourceList{},
Used: api.ResourceList{}, Used: api.ResourceList{},
} }
r := api.ResourceName(testCase.resource) r := resourceToResourceName[testCase.resource]
status.Hard[r] = resource.MustParse("2") status.Hard[r] = resource.MustParse("2")
status.Used[r] = resource.MustParse("1") status.Used[r] = resource.MustParse("1")

View File

@ -48,7 +48,7 @@ func NewSecurityContextDeny(client client.Interface) admission.Interface {
// Admit will deny any pod that defines SELinuxOptions or RunAsUser. // Admit will deny any pod that defines SELinuxOptions or RunAsUser.
func (p *plugin) Admit(a admission.Attributes) (err error) { func (p *plugin) Admit(a admission.Attributes) (err error) {
if a.GetResource() != string(api.ResourcePods) { if a.GetResource() != api.Resource("pods") {
return nil return nil
} }
@ -58,28 +58,28 @@ func (p *plugin) Admit(a admission.Attributes) (err error) {
} }
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SupplementalGroups != nil { if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SupplementalGroups != nil {
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("SecurityContext.SupplementalGroups is forbidden")) return apierrors.NewForbidden(a.GetResource().Resource, pod.Name, fmt.Errorf("SecurityContext.SupplementalGroups is forbidden"))
} }
if pod.Spec.SecurityContext != nil { if pod.Spec.SecurityContext != nil {
if pod.Spec.SecurityContext.SELinuxOptions != nil { if pod.Spec.SecurityContext.SELinuxOptions != nil {
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("pod.Spec.SecurityContext.SELinuxOptions is forbidden")) return apierrors.NewForbidden(a.GetResource().Resource, pod.Name, fmt.Errorf("pod.Spec.SecurityContext.SELinuxOptions is forbidden"))
} }
if pod.Spec.SecurityContext.RunAsUser != nil { if pod.Spec.SecurityContext.RunAsUser != nil {
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("pod.Spec.SecurityContext.RunAsUser is forbidden")) return apierrors.NewForbidden(a.GetResource().Resource, pod.Name, fmt.Errorf("pod.Spec.SecurityContext.RunAsUser is forbidden"))
} }
} }
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.FSGroup != nil { if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.FSGroup != nil {
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("SecurityContext.FSGroup is forbidden")) return apierrors.NewForbidden(a.GetResource().Resource, pod.Name, fmt.Errorf("SecurityContext.FSGroup is forbidden"))
} }
for _, v := range pod.Spec.Containers { for _, v := range pod.Spec.Containers {
if v.SecurityContext != nil { if v.SecurityContext != nil {
if v.SecurityContext.SELinuxOptions != nil { if v.SecurityContext.SELinuxOptions != nil {
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("SecurityContext.SELinuxOptions is forbidden")) return apierrors.NewForbidden(a.GetResource().Resource, pod.Name, fmt.Errorf("SecurityContext.SELinuxOptions is forbidden"))
} }
if v.SecurityContext.RunAsUser != nil { if v.SecurityContext.RunAsUser != nil {
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("SecurityContext.RunAsUser is forbidden")) return apierrors.NewForbidden(a.GetResource().Resource, pod.Name, fmt.Errorf("SecurityContext.RunAsUser is forbidden"))
} }
} }
} }

View File

@ -82,7 +82,7 @@ func TestAdmission(t *testing.T) {
pod.Spec.SecurityContext = tc.podSc pod.Spec.SecurityContext = tc.podSc
pod.Spec.Containers[0].SecurityContext = tc.sc pod.Spec.Containers[0].SecurityContext = tc.sc
err := handler.Admit(admission.NewAttributesRecord(pod, "Pod", "foo", "name", string(api.ResourcePods), "", "ignored", nil)) err := handler.Admit(admission.NewAttributesRecord(pod, api.Kind("Pod"), "foo", "name", api.Resource("pods"), "", "ignored", 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 {
@ -126,7 +126,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.Admit(admission.NewAttributesRecord(&pod, "Pod", "foo", "name", string(api.ResourcePods), "", "ignored", nil)) err := handler.Admit(admission.NewAttributesRecord(&pod, api.Kind("Pod"), "foo", "name", api.Resource("pods"), "", "ignored", 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)

View File

@ -149,7 +149,7 @@ func (s *serviceAccount) Stop() {
} }
func (s *serviceAccount) Admit(a admission.Attributes) (err error) { func (s *serviceAccount) Admit(a admission.Attributes) (err error) {
if a.GetResource() != string(api.ResourcePods) { if a.GetResource() != api.Resource("pods") {
return nil return nil
} }
obj := a.GetObject() obj := a.GetObject()

View File

@ -30,7 +30,7 @@ import (
func TestIgnoresNonCreate(t *testing.T) { func TestIgnoresNonCreate(t *testing.T) {
pod := &api.Pod{} pod := &api.Pod{}
for _, op := range []admission.Operation{admission.Update, admission.Delete, admission.Connect} { for _, op := range []admission.Operation{admission.Update, admission.Delete, admission.Connect} {
attrs := admission.NewAttributesRecord(pod, "Pod", "myns", "myname", string(api.ResourcePods), "", op, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), "myns", "myname", api.Resource("pods"), "", op, nil)
handler := admission.NewChainHandler(NewServiceAccount(nil)) handler := admission.NewChainHandler(NewServiceAccount(nil))
err := handler.Admit(attrs) err := handler.Admit(attrs)
if err != nil { if err != nil {
@ -41,7 +41,7 @@ func TestIgnoresNonCreate(t *testing.T) {
func TestIgnoresNonPodResource(t *testing.T) { func TestIgnoresNonPodResource(t *testing.T) {
pod := &api.Pod{} pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, "Pod", "myns", "myname", "CustomResource", "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), "myns", "myname", api.Resource("CustomResource"), "", admission.Create, nil)
err := NewServiceAccount(nil).Admit(attrs) err := NewServiceAccount(nil).Admit(attrs)
if err != nil { if err != nil {
t.Errorf("Expected non-pod resource allowed, got err: %v", err) t.Errorf("Expected non-pod resource allowed, got err: %v", err)
@ -49,7 +49,7 @@ func TestIgnoresNonPodResource(t *testing.T) {
} }
func TestIgnoresNilObject(t *testing.T) { func TestIgnoresNilObject(t *testing.T) {
attrs := admission.NewAttributesRecord(nil, "Pod", "myns", "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(nil, api.Kind("Pod"), "myns", "myname", api.Resource("pods"), "", admission.Create, nil)
err := NewServiceAccount(nil).Admit(attrs) err := NewServiceAccount(nil).Admit(attrs)
if err != nil { if err != nil {
t.Errorf("Expected nil object allowed allowed, got err: %v", err) t.Errorf("Expected nil object allowed allowed, got err: %v", err)
@ -58,7 +58,7 @@ func TestIgnoresNilObject(t *testing.T) {
func TestIgnoresNonPodObject(t *testing.T) { func TestIgnoresNonPodObject(t *testing.T) {
obj := &api.Namespace{} obj := &api.Namespace{}
attrs := admission.NewAttributesRecord(obj, "Pod", "myns", "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(obj, api.Kind("Pod"), "myns", "myname", api.Resource("pods"), "", admission.Create, nil)
err := NewServiceAccount(nil).Admit(attrs) err := NewServiceAccount(nil).Admit(attrs)
if err != nil { if err != nil {
t.Errorf("Expected non pod object allowed, got err: %v", err) t.Errorf("Expected non pod object allowed, got err: %v", err)
@ -78,7 +78,7 @@ func TestIgnoresMirrorPod(t *testing.T) {
}, },
}, },
} }
attrs := admission.NewAttributesRecord(pod, "Pod", "myns", "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), "myns", "myname", api.Resource("pods"), "", admission.Create, nil)
err := NewServiceAccount(nil).Admit(attrs) err := NewServiceAccount(nil).Admit(attrs)
if err != nil { if err != nil {
t.Errorf("Expected mirror pod without service account or secrets allowed, got err: %v", err) t.Errorf("Expected mirror pod without service account or secrets allowed, got err: %v", err)
@ -96,7 +96,7 @@ func TestRejectsMirrorPodWithServiceAccount(t *testing.T) {
ServiceAccountName: "default", ServiceAccountName: "default",
}, },
} }
attrs := admission.NewAttributesRecord(pod, "Pod", "myns", "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), "myns", "myname", api.Resource("pods"), "", admission.Create, nil)
err := NewServiceAccount(nil).Admit(attrs) err := NewServiceAccount(nil).Admit(attrs)
if err == nil { if err == nil {
t.Errorf("Expected a mirror pod to be prevented from referencing a service account") t.Errorf("Expected a mirror pod to be prevented from referencing a service account")
@ -116,7 +116,7 @@ func TestRejectsMirrorPodWithSecretVolumes(t *testing.T) {
}, },
}, },
} }
attrs := admission.NewAttributesRecord(pod, "Pod", "myns", "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), "myns", "myname", api.Resource("pods"), "", admission.Create, nil)
err := NewServiceAccount(nil).Admit(attrs) err := NewServiceAccount(nil).Admit(attrs)
if err == nil { if err == nil {
t.Errorf("Expected a mirror pod to be prevented from referencing a secret volume") t.Errorf("Expected a mirror pod to be prevented from referencing a secret volume")
@ -139,7 +139,7 @@ func TestAssignsDefaultServiceAccountAndToleratesMissingAPIToken(t *testing.T) {
}) })
pod := &api.Pod{} pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), ns, "myname", api.Resource("pods"), "", admission.Create, nil)
err := admit.Admit(attrs) err := admit.Admit(attrs)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
@ -165,7 +165,7 @@ func TestAssignsDefaultServiceAccountAndRejectsMissingAPIToken(t *testing.T) {
}) })
pod := &api.Pod{} pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), ns, "myname", api.Resource("pods"), "", admission.Create, nil)
err := admit.Admit(attrs) err := admit.Admit(attrs)
if err == nil { if err == nil {
t.Errorf("Expected admission error for missing API token") t.Errorf("Expected admission error for missing API token")
@ -187,7 +187,7 @@ func TestFetchesUncachedServiceAccount(t *testing.T) {
admit.RequireAPIToken = false admit.RequireAPIToken = false
pod := &api.Pod{} pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), ns, "myname", api.Resource("pods"), "", admission.Create, nil)
err := admit.Admit(attrs) err := admit.Admit(attrs)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
@ -206,7 +206,7 @@ func TestDeniesInvalidServiceAccount(t *testing.T) {
admit := NewServiceAccount(client) admit := NewServiceAccount(client)
pod := &api.Pod{} pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), ns, "myname", api.Resource("pods"), "", admission.Create, nil)
err := admit.Admit(attrs) err := admit.Admit(attrs)
if err == nil { if err == nil {
t.Errorf("Expected error for missing service account, got none") t.Errorf("Expected error for missing service account, got none")
@ -269,7 +269,7 @@ func TestAutomountsAPIToken(t *testing.T) {
}, },
}, },
} }
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), ns, "myname", api.Resource("pods"), "", admission.Create, nil)
err := admit.Admit(attrs) err := admit.Admit(attrs)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
@ -348,7 +348,7 @@ func TestRespectsExistingMount(t *testing.T) {
}, },
}, },
} }
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), ns, "myname", api.Resource("pods"), "", admission.Create, nil)
err := admit.Admit(attrs) err := admit.Admit(attrs)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
@ -392,7 +392,7 @@ func TestAllowsReferencedSecretVolumes(t *testing.T) {
}, },
}, },
} }
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), ns, "myname", api.Resource("pods"), "", admission.Create, nil)
err := admit.Admit(attrs) err := admit.Admit(attrs)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
@ -421,7 +421,7 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) {
}, },
}, },
} }
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), ns, "myname", api.Resource("pods"), "", admission.Create, nil)
err := admit.Admit(attrs) err := admit.Admit(attrs)
if err == nil { if err == nil {
t.Errorf("Expected rejection for using a secret the service account does not reference") t.Errorf("Expected rejection for using a secret the service account does not reference")
@ -451,7 +451,7 @@ func TestAllowUnreferencedSecretVolumesForPermissiveSAs(t *testing.T) {
}, },
}, },
} }
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), ns, "myname", api.Resource("pods"), "", admission.Create, nil)
err := admit.Admit(attrs) err := admit.Admit(attrs)
if err == nil { if err == nil {
t.Errorf("Expected rejection for using a secret the service account does not reference") t.Errorf("Expected rejection for using a secret the service account does not reference")
@ -481,7 +481,7 @@ func TestAllowsReferencedImagePullSecrets(t *testing.T) {
ImagePullSecrets: []api.LocalObjectReference{{Name: "foo"}}, ImagePullSecrets: []api.LocalObjectReference{{Name: "foo"}},
}, },
} }
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), ns, "myname", api.Resource("pods"), "", admission.Create, nil)
err := admit.Admit(attrs) err := admit.Admit(attrs)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
@ -508,7 +508,7 @@ func TestRejectsUnreferencedImagePullSecrets(t *testing.T) {
ImagePullSecrets: []api.LocalObjectReference{{Name: "foo"}}, ImagePullSecrets: []api.LocalObjectReference{{Name: "foo"}},
}, },
} }
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), ns, "myname", api.Resource("pods"), "", admission.Create, nil)
err := admit.Admit(attrs) err := admit.Admit(attrs)
if err == nil { if err == nil {
t.Errorf("Expected rejection for using a secret the service account does not reference") t.Errorf("Expected rejection for using a secret the service account does not reference")
@ -539,7 +539,7 @@ func TestDoNotAddImagePullSecrets(t *testing.T) {
ImagePullSecrets: []api.LocalObjectReference{{Name: "foo"}}, ImagePullSecrets: []api.LocalObjectReference{{Name: "foo"}},
}, },
} }
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), ns, "myname", api.Resource("pods"), "", admission.Create, nil)
err := admit.Admit(attrs) err := admit.Admit(attrs)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
@ -571,7 +571,7 @@ func TestAddImagePullSecrets(t *testing.T) {
admit.serviceAccounts.Add(sa) admit.serviceAccounts.Add(sa)
pod := &api.Pod{} pod := &api.Pod{}
attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) attrs := admission.NewAttributesRecord(pod, api.Kind("Pod"), ns, "myname", api.Resource("pods"), "", admission.Create, nil)
err := admit.Admit(attrs) err := admit.Admit(attrs)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)