func TestSAR(t *testing.T) { store := projectcache.NewCacheStore(cache.IndexFuncToKeyFuncAdapter(cache.MetaNamespaceIndexFunc)) mockClient := &testclient.Fake{} mockClient.AddReactor("get", "namespaces", func(action testclient.Action) (handled bool, ret runtime.Object, err error) { return true, nil, fmt.Errorf("shouldn't get here") }) cache := projectcache.NewFake(mockClient.Namespaces(), store, "") mockClientset := clientsetfake.NewSimpleClientset() handler := &lifecycle{client: mockClientset, creatableResources: recommendedCreatableResources} handler.SetProjectCache(cache) tests := map[string]struct { kind string resource string }{ "subject access review": { kind: "SubjectAccessReview", resource: "subjectaccessreviews", }, "local subject access review": { kind: "LocalSubjectAccessReview", resource: "localsubjectaccessreviews", }, } for k, v := range tests { err := handler.Admit(admission.NewAttributesRecord(nil, nil, kapi.Kind(v.kind).WithVersion("v1"), "foo", "name", kapi.Resource(v.resource).WithVersion("v1"), "", "CREATE", nil)) if err != nil { t.Errorf("Unexpected error for %s returned from admission handler: %v", k, err) } } }
func testCache(projectAnnotations map[string]string) *projectcache.ProjectCache { kclient := &ktestclient.Fake{} pCache := projectcache.NewFake(kclient.Namespaces(), projectcache.NewCacheStore(cache.MetaNamespaceKeyFunc), "") ns := &kapi.Namespace{} ns.Name = "default" ns.Annotations = projectAnnotations pCache.Store.Add(ns) return pCache }
func fakeProjectCache(requesters map[string]int) *projectcache.ProjectCache { kclient := &ktestclient.Fake{} pCache := projectcache.NewFake(kclient.Namespaces(), projectcache.NewCacheStore(cache.MetaNamespaceKeyFunc), "") for requester, count := range requesters { for i := 0; i < count; i++ { pCache.Store.Add(fakeNs(requester)) } } return pCache }
func fakeProjectCache(requesters map[string]projectCount) *projectcache.ProjectCache { kclientset := &fake.Clientset{} pCache := projectcache.NewFake(kclientset.Core().Namespaces(), projectcache.NewCacheStore(cache.MetaNamespaceKeyFunc), "") for requester, count := range requesters { for i := 0; i < count.active; i++ { pCache.Store.Add(fakeNs(requester, false)) } for i := 0; i < count.terminating; i++ { pCache.Store.Add(fakeNs(requester, true)) } } return pCache }
// TestAdmissionExists verifies you cannot create Origin content if namespace is not known func TestAdmissionExists(t *testing.T) { mockClient := &testclient.Fake{} mockClient.AddReactor("*", "*", func(action testclient.Action) (handled bool, ret runtime.Object, err error) { return true, &kapi.Namespace{}, fmt.Errorf("DOES NOT EXIST") }) cache := projectcache.NewFake(mockClient.Namespaces(), projectcache.NewCacheStore(cache.MetaNamespaceKeyFunc), "") mockClientset := clientsetfake.NewSimpleClientset() handler := &lifecycle{client: mockClientset} handler.SetProjectCache(cache) build := &buildapi.Build{ ObjectMeta: kapi.ObjectMeta{Name: "buildid"}, Spec: buildapi.BuildSpec{ CommonSpec: buildapi.CommonSpec{ Source: buildapi.BuildSource{ Git: &buildapi.GitBuildSource{ URI: "http://github.com/my/repository", }, ContextDir: "context", }, Strategy: buildapi.BuildStrategy{ DockerStrategy: &buildapi.DockerBuildStrategy{}, }, Output: buildapi.BuildOutput{ To: &kapi.ObjectReference{ Kind: "DockerImage", Name: "repository/data", }, }, }, }, Status: buildapi.BuildStatus{ Phase: buildapi.BuildPhaseNew, }, } err := handler.Admit(admission.NewAttributesRecord(build, nil, kapi.Kind("Build").WithVersion("v1"), "namespace", "name", kapi.Resource("builds").WithVersion("v1"), "", "CREATE", nil)) if err == nil { t.Errorf("Expected an error because namespace does not exist") } }
func fakeProjectCache(ns *kapi.Namespace) *projectcache.ProjectCache { store := projectcache.NewCacheStore(cache.MetaNamespaceKeyFunc) store.Add(ns) return projectcache.NewFake((&ktestclient.Fake{}).Namespaces(), store, "") }
func setDefaultCache(p *imagePolicyPlugin) kcache.Indexer { kclient := ktestclient.NewSimpleFake() store := cache.NewCacheStore(kcache.MetaNamespaceKeyFunc) p.SetProjectCache(cache.NewFake(kclient.Namespaces(), store, "")) return store }
// TestAdmissionLifecycle verifies you cannot create Origin content if namespace is terminating func TestAdmissionLifecycle(t *testing.T) { namespaceObj := &kapi.Namespace{ ObjectMeta: kapi.ObjectMeta{ Name: "test", Namespace: "", }, Status: kapi.NamespaceStatus{ Phase: kapi.NamespaceActive, }, } store := projectcache.NewCacheStore(cache.IndexFuncToKeyFuncAdapter(cache.MetaNamespaceIndexFunc)) store.Add(namespaceObj) mockClient := &testclient.Fake{} cache := projectcache.NewFake(mockClient.Namespaces(), store, "") mockClientset := clientsetfake.NewSimpleClientset(namespaceObj) handler := &lifecycle{client: mockClientset} handler.SetProjectCache(cache) build := &buildapi.Build{ ObjectMeta: kapi.ObjectMeta{Name: "buildid", Namespace: "other"}, Spec: buildapi.BuildSpec{ CommonSpec: buildapi.CommonSpec{ Source: buildapi.BuildSource{ Git: &buildapi.GitBuildSource{ URI: "http://github.com/my/repository", }, ContextDir: "context", }, Strategy: buildapi.BuildStrategy{ DockerStrategy: &buildapi.DockerBuildStrategy{}, }, Output: buildapi.BuildOutput{ To: &kapi.ObjectReference{ Kind: "DockerImage", Name: "repository/data", }, }, }, }, Status: buildapi.BuildStatus{ Phase: buildapi.BuildPhaseNew, }, } err := handler.Admit(admission.NewAttributesRecord(build, nil, kapi.Kind("Build").WithVersion("version"), build.Namespace, "name", kapi.Resource("builds").WithVersion("version"), "", "CREATE", nil)) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } // change namespace state to terminating namespaceObj.Status.Phase = kapi.NamespaceTerminating store.Add(namespaceObj) // verify create operations in the namespace cause an error err = handler.Admit(admission.NewAttributesRecord(build, nil, kapi.Kind("Build").WithVersion("version"), build.Namespace, "name", kapi.Resource("builds").WithVersion("version"), "", "CREATE", nil)) if err == nil { t.Errorf("Expected error rejecting creates in a namespace when it is terminating") } // verify update operations in the namespace can proceed err = handler.Admit(admission.NewAttributesRecord(build, build, kapi.Kind("Build").WithVersion("version"), build.Namespace, "name", kapi.Resource("builds").WithVersion("version"), "", "UPDATE", nil)) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } // verify delete operations in the namespace can proceed err = handler.Admit(admission.NewAttributesRecord(nil, nil, kapi.Kind("Build").WithVersion("version"), build.Namespace, "name", kapi.Resource("builds").WithVersion("version"), "", "DELETE", nil)) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } }
// TestPodAdmission verifies various scenarios involving pod/project/global node label selectors func TestPodAdmission(t *testing.T) { project := &kapi.Namespace{ ObjectMeta: kapi.ObjectMeta{ Name: "testProject", Namespace: "", }, } projectStore := projectcache.NewCacheStore(cache.IndexFuncToKeyFuncAdapter(cache.MetaNamespaceIndexFunc)) projectStore.Add(project) mockClientset := fake.NewSimpleClientset() handler := &podNodeEnvironment{client: mockClientset} pod := &kapi.Pod{ ObjectMeta: kapi.ObjectMeta{Name: "testPod"}, } tests := []struct { defaultNodeSelector string projectNodeSelector string podNodeSelector map[string]string mergedNodeSelector map[string]string ignoreProjectNodeSelector bool admit bool testName string }{ { defaultNodeSelector: "", podNodeSelector: map[string]string{}, mergedNodeSelector: map[string]string{}, ignoreProjectNodeSelector: true, admit: true, testName: "No node selectors", }, { defaultNodeSelector: "infra = false", podNodeSelector: map[string]string{}, mergedNodeSelector: map[string]string{"infra": "false"}, ignoreProjectNodeSelector: true, admit: true, testName: "Default node selector and no conflicts", }, { defaultNodeSelector: "", projectNodeSelector: "infra = false", podNodeSelector: map[string]string{}, mergedNodeSelector: map[string]string{"infra": "false"}, admit: true, testName: "Project node selector and no conflicts", }, { defaultNodeSelector: "infra = false", projectNodeSelector: "", podNodeSelector: map[string]string{}, mergedNodeSelector: map[string]string{}, admit: true, testName: "Empty project node selector and no conflicts", }, { defaultNodeSelector: "infra = false", projectNodeSelector: "infra=true", podNodeSelector: map[string]string{}, mergedNodeSelector: map[string]string{"infra": "true"}, admit: true, testName: "Default and project node selector, no conflicts", }, { defaultNodeSelector: "infra = false", projectNodeSelector: "infra=true", podNodeSelector: map[string]string{"env": "test"}, mergedNodeSelector: map[string]string{"infra": "true", "env": "test"}, admit: true, testName: "Project and pod node selector, no conflicts", }, { defaultNodeSelector: "env = test", projectNodeSelector: "infra=true", podNodeSelector: map[string]string{"infra": "false"}, mergedNodeSelector: map[string]string{"infra": "false"}, admit: false, testName: "Conflicting pod and project node selector, one label", }, { defaultNodeSelector: "env=dev", projectNodeSelector: "infra=false, env = test", podNodeSelector: map[string]string{"env": "dev", "color": "blue"}, mergedNodeSelector: map[string]string{"env": "dev", "color": "blue"}, admit: false, testName: "Conflicting pod and project node selector, multiple labels", }, } for _, test := range tests { cache := projectcache.NewFake(mockClientset.Core().Namespaces(), projectStore, test.defaultNodeSelector) handler.SetProjectCache(cache) if !test.ignoreProjectNodeSelector { project.ObjectMeta.Annotations = map[string]string{"openshift.io/node-selector": test.projectNodeSelector} } pod.Spec = kapi.PodSpec{NodeSelector: test.podNodeSelector} err := handler.Admit(admission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), "namespace", project.ObjectMeta.Name, kapi.Resource("pods").WithVersion("version"), "", admission.Create, 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 { t.Errorf("Test: %s, expected an error", test.testName) } if !labelselector.Equals(test.mergedNodeSelector, pod.Spec.NodeSelector) { t.Errorf("Test: %s, expected: %s but got: %s", test.testName, test.mergedNodeSelector, pod.Spec.NodeSelector) } } }