package controller import ( "fmt" "strings" "testing" kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" "k8s.io/kubernetes/pkg/client/testing/core" "k8s.io/kubernetes/pkg/runtime" "github.com/openshift/origin/pkg/security" "github.com/openshift/origin/pkg/security/mcs" "github.com/openshift/origin/pkg/security/uid" "github.com/openshift/origin/pkg/security/uidallocator" ) func TestController(t *testing.T) { var action core.Action client := &fake.Clientset{} client.AddReactor("*", "*", func(a core.Action) (handled bool, ret runtime.Object, err error) { action = a return true, (*kapi.Namespace)(nil), nil }) uidr, _ := uid.NewRange(10, 20, 2) mcsr, _ := mcs.NewRange("s0:", 10, 2) uida := uidallocator.NewInMemory(uidr) c := Allocation{ uid: uida, mcs: DefaultMCSAllocation(uidr, mcsr, 5), client: client.Core().Namespaces(), } err := c.Next(&kapi.Namespace{ObjectMeta: kapi.ObjectMeta{Name: "test"}}) if err != nil { t.Fatal(err) } got := action.(core.CreateAction).GetObject().(*kapi.Namespace) if got.Annotations[security.UIDRangeAnnotation] != "10/2" { t.Errorf("unexpected uid annotation: %#v", got) } if got.Annotations[security.SupplementalGroupsAnnotation] != "10/2" { t.Errorf("unexpected supplemental group annotation: %#v", got) } if got.Annotations[security.MCSAnnotation] != "s0:c1,c0" { t.Errorf("unexpected mcs annotation: %#v", got) } if !uida.Has(uid.Block{Start: 10, End: 11}) { t.Errorf("did not allocate uid: %#v", uida) } } func TestControllerError(t *testing.T) { testCases := map[string]struct { err func() error errFn func(err error) bool reactFn core.ReactionFunc actions int }{ "not found": { err: func() error { return errors.NewNotFound(kapi.Resource("Namespace"), "test") }, errFn: func(err error) bool { return err == nil }, actions: 1, }, "unknown": { err: func() error { return fmt.Errorf("unknown") }, errFn: func(err error) bool { return err.Error() == "unknown" }, actions: 1, }, "conflict": { actions: 4, reactFn: func(a core.Action) (bool, runtime.Object, error) { if a.Matches("get", "namespaces") { return true, &kapi.Namespace{ObjectMeta: kapi.ObjectMeta{Name: "test"}}, nil } return true, (*kapi.Namespace)(nil), errors.NewConflict(kapi.Resource("namespace"), "test", fmt.Errorf("test conflict")) }, errFn: func(err error) bool { return err != nil && strings.Contains(err.Error(), "unable to allocate security info") }, }, } for s, testCase := range testCases { client := &fake.Clientset{} if testCase.reactFn == nil { testCase.reactFn = func(a core.Action) (bool, runtime.Object, error) { return true, (*kapi.Namespace)(nil), testCase.err() } } client.AddReactor("*", "*", testCase.reactFn) uidr, _ := uid.NewRange(10, 19, 2) mcsr, _ := mcs.NewRange("s0:", 10, 2) uida := uidallocator.NewInMemory(uidr) c := Allocation{ uid: uida, mcs: DefaultMCSAllocation(uidr, mcsr, 5), client: client.Core().Namespaces(), } err := c.Next(&kapi.Namespace{ObjectMeta: kapi.ObjectMeta{Name: "test"}}) if !testCase.errFn(err) { t.Errorf("%s: unexpected error: %v", s, err) } if len(client.Actions()) != testCase.actions { t.Errorf("%s: expected %d actions: %v", s, testCase.actions, client.Actions()) } if uida.Free() != 5 { t.Errorf("%s: should not have allocated uid: %d/%d", s, uida.Free(), uidr.Size()) } } }