// TestAdmissionExists verifies you cannot create Origin content if namespace is not known func TestAdmissionExists(t *testing.T) { mockClient := &testclient.Fake{ Err: fmt.Errorf("DOES NOT EXIST"), } projectcache.FakeProjectCache(mockClient, cache.NewStore(cache.MetaNamespaceKeyFunc), "") handler := &lifecycle{client: mockClient} build := &buildapi.Build{ ObjectMeta: kapi.ObjectMeta{Name: "buildid"}, Parameters: buildapi.BuildParameters{ Source: buildapi.BuildSource{ Type: buildapi.BuildSourceGit, Git: &buildapi.GitBuildSource{ URI: "http://github.com/my/repository", }, ContextDir: "context", }, Strategy: buildapi.BuildStrategy{ Type: buildapi.DockerBuildStrategyType, DockerStrategy: &buildapi.DockerBuildStrategy{}, }, Output: buildapi.BuildOutput{ DockerImageReference: "repository/data", }, }, Status: buildapi.BuildStatusNew, } err := handler.Admit(admission.NewAttributesRecord(build, "Build", "bogus-ns", "builds", "CREATE", nil)) if err == nil { t.Errorf("Expected an error because namespace does not exist") } }
func TestSAR(t *testing.T) { store := cache.NewStore(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") }) projectcache.FakeProjectCache(mockClient, store, "") handler := &lifecycle{client: mockClient} 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, v.kind, "foo", "name", v.resource, "", "CREATE", nil)) if err != nil { t.Errorf("Unexpected error for %s returned from admission handler: %v", k, err) } } }
// 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") }) projectcache.FakeProjectCache(mockClient, cache.NewStore(cache.MetaNamespaceKeyFunc), "") handler := &lifecycle{client: mockClient} build := &buildapi.Build{ ObjectMeta: kapi.ObjectMeta{Name: "buildid"}, Spec: buildapi.BuildSpec{ Source: buildapi.BuildSource{ Type: buildapi.BuildSourceGit, Git: &buildapi.GitBuildSource{ URI: "http://github.com/my/repository", }, ContextDir: "context", }, Strategy: buildapi.BuildStrategy{ Type: buildapi.DockerBuildStrategyType, 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, "Build", "namespace", "name", "builds", "", "CREATE", nil)) if err == nil { t.Errorf("Expected an error because namespace does not exist") } }
// 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 := cache.NewStore(cache.MetaNamespaceIndexFunc) store.Add(namespaceObj) mockClient := &testclient.Fake{} projectcache.FakeProjectCache(mockClient, store, "") handler := &lifecycle{client: mockClient} build := &buildapi.Build{ ObjectMeta: kapi.ObjectMeta{Name: "buildid", Namespace: "other"}, Parameters: buildapi.BuildParameters{ Source: buildapi.BuildSource{ Type: buildapi.BuildSourceGit, Git: &buildapi.GitBuildSource{ URI: "http://github.com/my/repository", }, ContextDir: "context", }, Strategy: buildapi.BuildStrategy{ Type: buildapi.DockerBuildStrategyType, DockerStrategy: &buildapi.DockerBuildStrategy{}, }, Output: buildapi.BuildOutput{ DockerImageReference: "repository/data", }, }, Status: buildapi.BuildStatusNew, } err := handler.Admit(admission.NewAttributesRecord(build, "Build", build.Namespace, "builds", "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, "Build", build.Namespace, "builds", "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", build.Namespace, "builds", "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, "Build", build.Namespace, "builds", "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) { mockClient := &testclient.Fake{} project := &kapi.Namespace{ ObjectMeta: kapi.ObjectMeta{ Name: "testProject", Namespace: "", }, } projectStore := cache.NewStore(cache.IndexFuncToKeyFuncAdapter(cache.MetaNamespaceIndexFunc)) projectStore.Add(project) handler := &podNodeEnvironment{client: mockClient} 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 { projectcache.FakeProjectCache(mockClient, projectStore, test.defaultNodeSelector) 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, "Pod", "namespace", project.ObjectMeta.Name, "pods", "", 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) } } }