func TestLimitRangerIgnoresSubresource(t *testing.T) { client := testclient.NewSimpleFake() indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}) handler := &limitRanger{ Handler: admission.NewHandler(admission.Create, admission.Update), client: client, limitFunc: Limit, indexer: indexer, } limitRange := validLimitRangeNoDefaults() testPod := validPod("testPod", 1, api.ResourceRequirements{}) indexer.Add(&limitRange) err := handler.Admit(admission.NewAttributesRecord(&testPod, "Pod", limitRange.Namespace, "pods", "", admission.Update, nil)) if err == nil { 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, "pods", "status", admission.Update, nil)) if err != nil { t.Errorf("Should have ignored calls to any subresource of pod %v", err) } }
func TestAdmissionIgnoresSubresources(t *testing.T) { indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{"namespace": cache.MetaNamespaceIndexFunc}) handler := createResourceQuota(&testclient.Fake{}, indexer) quota := &api.ResourceQuota{} quota.Name = "quota" quota.Namespace = "test" quota.Status = api.ResourceQuotaStatus{ Hard: api.ResourceList{}, Used: api.ResourceList{}, } quota.Status.Hard[api.ResourceMemory] = resource.MustParse("2Gi") quota.Status.Used[api.ResourceMemory] = resource.MustParse("1Gi") indexer.Add(quota) newPod := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "123", Namespace: quota.Namespace}, Spec: api.PodSpec{ Volumes: []api.Volume{{Name: "vol"}}, Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("100m", "2Gi")}}, }} err := handler.Admit(admission.NewAttributesRecord(newPod, "Pod", newPod.Namespace, "pods", "", admission.Create, nil)) if err == nil { t.Errorf("Expected an error because the pod exceeded allowed quota") } err = handler.Admit(admission.NewAttributesRecord(newPod, "Pod", newPod.Namespace, "pods", "subresource", admission.Create, nil)) if err != nil { t.Errorf("Did not expect an error because the action went to a subresource: %v", err) } }
// TestAdmission func TestAdmission(t *testing.T) { namespaceObj := &api.Namespace{ ObjectMeta: api.ObjectMeta{ Name: "test", Namespace: "", }, Status: api.NamespaceStatus{ Phase: api.NamespaceActive, }, } store := cache.NewStore(cache.MetaNamespaceIndexFunc) store.Add(namespaceObj) mockClient := &testclient.Fake{} handler := &lifecycle{ client: mockClient, store: store, } pod := api.Pod{ ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespaceObj.Namespace}, Spec: api.PodSpec{ Volumes: []api.Volume{{Name: "vol"}}, Containers: []api.Container{{Name: "ctr", Image: "image"}}, }, } err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", namespaceObj.Namespace, "pods", "CREATE")) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } // change namespace state to terminating namespaceObj.Status.Phase = api.NamespaceTerminating store.Add(namespaceObj) // verify create operations in the namespace cause an error err = handler.Admit(admission.NewAttributesRecord(&pod, "Pod", namespaceObj.Namespace, "pods", "CREATE")) 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(&pod, "Pod", namespaceObj.Namespace, "pods", "UPDATE")) 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, "Pod", namespaceObj.Namespace, "pods", "DELETE")) if err != nil { t.Errorf("Unexpected error returned from admission handler: %v", err) } }
func TestIncrementUsageServices(t *testing.T) { namespace := "default" client := testclient.NewSimpleFake(&api.ServiceList{ Items: []api.Service{ { ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace}, }, }, }) status := &api.ResourceQuotaStatus{ Hard: api.ResourceList{}, Used: api.ResourceList{}, } r := api.ResourceServices status.Hard[r] = resource.MustParse("2") status.Used[r] = resource.MustParse("1") dirty, err := IncrementUsage(admission.NewAttributesRecord(&api.Service{}, "Service", namespace, "services", "", admission.Create, nil), status, client) if err != nil { t.Errorf("Unexpected error: %v", err) } if !dirty { t.Errorf("Expected the status to get incremented, therefore should have been dirty") } quantity := status.Used[r] if quantity.Value() != int64(2) { t.Errorf("Expected new item count to be 2, but was %s", quantity.String()) } }
func TestExceedUsageCPU(t *testing.T) { namespace := "default" client := testclient.NewSimpleFake(&api.PodList{ Items: []api.Pod{ { ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace}, Spec: api.PodSpec{ Volumes: []api.Volume{{Name: "vol"}}, Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("100m", "1Gi")}}, }, }, }, }) status := &api.ResourceQuotaStatus{ Hard: api.ResourceList{}, Used: api.ResourceList{}, } r := api.ResourceCPU status.Hard[r] = resource.MustParse("200m") status.Used[r] = resource.MustParse("100m") newPod := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace}, Spec: api.PodSpec{ Volumes: []api.Volume{{Name: "vol"}}, Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("500m", "1Gi")}}, }} _, err := IncrementUsage(admission.NewAttributesRecord(newPod, "Pod", namespace, "pods", "", admission.Create, nil), status, client) if err == nil { t.Errorf("Expected CPU usage exceeded error") } }
func TestAssignsDefaultServiceAccountAndToleratesMissingAPIToken(t *testing.T) { ns := "myns" admit := NewServiceAccount(nil) admit.MountServiceAccountToken = true admit.RequireAPIToken = false // Add the default service account for the ns into the cache admit.serviceAccounts.Add(&api.ServiceAccount{ ObjectMeta: api.ObjectMeta{ Name: DefaultServiceAccountName, Namespace: ns, }, }) pod := &api.Pod{} attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) err := admit.Admit(attrs) if err != nil { t.Errorf("Unexpected error: %v", err) } if pod.Spec.ServiceAccountName != DefaultServiceAccountName { t.Errorf("Expected service account %s assigned, got %s", DefaultServiceAccountName, pod.Spec.ServiceAccountName) } }
func TestAdmission(t *testing.T) { handler := NewAlwaysDeny() err := handler.Admit(admission.NewAttributesRecord(nil, "kind", "namespace", "resource", "subresource", admission.Create, nil)) if err == nil { t.Errorf("Expected error returned from admission handler") } }
func TestRejectsUnreferencedImagePullSecrets(t *testing.T) { ns := "myns" admit := NewServiceAccount(nil) admit.LimitSecretReferences = true // Add the default service account for the ns into the cache admit.serviceAccounts.Add(&api.ServiceAccount{ ObjectMeta: api.ObjectMeta{ Name: DefaultServiceAccountName, Namespace: ns, }, }) pod := &api.Pod{ Spec: api.PodSpec{ ImagePullSecrets: []api.LocalObjectReference{{Name: "foo"}}, }, } attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) err := admit.Admit(attrs) if err == nil { t.Errorf("Expected rejection for using a secret the service account does not reference") } }
// TestAdmissionNamespaceExists verifies that no client call is made when a namespace already exists func TestAdmissionNamespaceExists(t *testing.T) { namespace := "test" mockClient := &testclient.Fake{} store := cache.NewStore(cache.MetaNamespaceKeyFunc) store.Add(&api.Namespace{ ObjectMeta: api.ObjectMeta{Name: namespace}, }) handler := &provision{ client: mockClient, store: store, } pod := api.Pod{ ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace}, Spec: api.PodSpec{ Volumes: []api.Volume{{Name: "vol"}}, Containers: []api.Container{{Name: "ctr", Image: "image"}}, }, } err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", namespace, "pods", "", admission.Create, nil)) if err != nil { t.Errorf("Unexpected error returned from admission handler") } if len(mockClient.Actions) != 0 { t.Errorf("No client request should have been made") } }
// TestAdmission verifies a namespace is created on create requests for namespace managed resources func TestAdmission(t *testing.T) { namespace := "test" mockClient := &testclient.Fake{} handler := &provision{ client: mockClient, store: cache.NewStore(cache.MetaNamespaceKeyFunc), } pod := api.Pod{ ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace}, Spec: api.PodSpec{ Volumes: []api.Volume{{Name: "vol"}}, Containers: []api.Container{{Name: "ctr", Image: "image"}}, }, } err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", namespace, "pods", "", admission.Create, nil)) if err != nil { t.Errorf("Unexpected error returned from admission handler") } if len(mockClient.Actions) != 1 { t.Errorf("Expected a create-namespace request") } if mockClient.Actions[0].Action != "create-namespace" { t.Errorf("Expected a create-namespace request to be made via the client") } }
func TestIgnoresNilObject(t *testing.T) { attrs := admission.NewAttributesRecord(nil, "Pod", "myns", "myname", string(api.ResourcePods), "", admission.Create, nil) err := NewServiceAccount(nil).Admit(attrs) if err != nil { t.Errorf("Expected nil object allowed allowed, got err: %v", err) } }
func TestExceedUsagePods(t *testing.T) { namespace := "default" client := &client.Fake{ PodsList: api.PodList{ Items: []api.Pod{ { ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace}, Spec: api.PodSpec{ Volumes: []api.Volume{{Name: "vol"}}, Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("100m", "1Gi")}}, }, }, }, }, } status := &api.ResourceQuotaStatus{ Hard: api.ResourceList{}, Used: api.ResourceList{}, } r := api.ResourcePods status.Hard[r] = resource.MustParse("1") status.Used[r] = resource.MustParse("1") _, err := IncrementUsage(admission.NewAttributesRecord(&api.Pod{}, namespace, "pods", "CREATE"), status, client) if err == nil { t.Errorf("Expected error because this would exceed your quota") } }
func TestAddImagePullSecrets(t *testing.T) { ns := "myns" admit := NewServiceAccount(nil) admit.LimitSecretReferences = true sa := &api.ServiceAccount{ ObjectMeta: api.ObjectMeta{ Name: DefaultServiceAccountName, Namespace: ns, }, ImagePullSecrets: []api.LocalObjectReference{ {Name: "foo"}, {Name: "bar"}, }, } // Add the default service account for the ns with a secret reference into the cache admit.serviceAccounts.Add(sa) pod := &api.Pod{} attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) err := admit.Admit(attrs) if err != nil { t.Errorf("Unexpected error: %v", err) } if len(pod.Spec.ImagePullSecrets) != 2 || !reflect.DeepEqual(sa.ImagePullSecrets, pod.Spec.ImagePullSecrets) { t.Errorf("expected %v, got %v", sa.ImagePullSecrets, pod.Spec.ImagePullSecrets) } pod.Spec.ImagePullSecrets[1] = api.LocalObjectReference{Name: "baz"} if reflect.DeepEqual(sa.ImagePullSecrets, pod.Spec.ImagePullSecrets) { t.Errorf("accidentally mutated the ServiceAccount.ImagePullSecrets: %v", sa.ImagePullSecrets) } }
func TestAdmission(t *testing.T) { handler := NewAlwaysDeny() err := handler.Admit(admission.NewAttributesRecord(nil, "Pod", "foo", "Pod", "ignored", nil)) if err == nil { t.Errorf("Expected error returned from admission handler") } }
func TestIncrementUsagePods(t *testing.T) { namespace := "default" client := &client.Fake{ PodsList: api.PodList{ Items: []api.Pod{ { ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace}, Spec: api.PodSpec{ Volumes: []api.Volume{{Name: "vol"}}, Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("100m", "1Gi")}}, }, }, }, }, } status := &api.ResourceQuotaStatus{ Hard: api.ResourceList{}, Used: api.ResourceList{}, } r := api.ResourcePods status.Hard[r] = resource.MustParse("2") status.Used[r] = resource.MustParse("1") dirty, err := IncrementUsage(admission.NewAttributesRecord(&api.Pod{}, namespace, "pods", "CREATE"), status, client) if err != nil { t.Errorf("Unexpected error", err) } if !dirty { t.Errorf("Expected the status to get incremented, therefore should have been dirty") } quantity := status.Used[r] if quantity.Value() != int64(2) { t.Errorf("Expected new item count to be 2, but was %s", quantity.String()) } }
func TestIncrementUsageReplicationControllers(t *testing.T) { namespace := "default" client := &client.Fake{ CtrlList: api.ReplicationControllerList{ Items: []api.ReplicationController{ { ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace}, }, }, }, } status := &api.ResourceQuotaStatus{ Hard: api.ResourceList{}, Used: api.ResourceList{}, } r := api.ResourceReplicationControllers status.Hard[r] = resource.MustParse("2") status.Used[r] = resource.MustParse("1") dirty, err := IncrementUsage(admission.NewAttributesRecord(&api.ReplicationController{}, namespace, "replicationControllers", "CREATE"), status, client) if err != nil { t.Errorf("Unexpected error", err) } if !dirty { t.Errorf("Expected the status to get incremented, therefore should have been dirty") } quantity := status.Used[r] if quantity.Value() != int64(2) { t.Errorf("Expected new item count to be 2, but was %s", quantity.String()) } }
// 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 TestDoNotAddImagePullSecrets(t *testing.T) { ns := "myns" admit := NewServiceAccount(nil) admit.LimitSecretReferences = true // Add the default service account for the ns with a secret reference into the cache admit.serviceAccounts.Add(&api.ServiceAccount{ ObjectMeta: api.ObjectMeta{ Name: DefaultServiceAccountName, Namespace: ns, }, ImagePullSecrets: []api.LocalObjectReference{ {Name: "foo"}, {Name: "bar"}, }, }) pod := &api.Pod{ Spec: api.PodSpec{ ImagePullSecrets: []api.LocalObjectReference{{Name: "foo"}}, }, } attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) err := admit.Admit(attrs) if err != nil { t.Errorf("Unexpected error: %v", err) } if len(pod.Spec.ImagePullSecrets) != 1 || pod.Spec.ImagePullSecrets[0].Name != "foo" { t.Errorf("unexpected image pull secrets: %v", pod.Spec.ImagePullSecrets) } }
func TestAdmission(t *testing.T) { namespace := "default" handler := NewResourceDefaults() pod := api.Pod{ ObjectMeta: api.ObjectMeta{Name: "123", Namespace: "ns"}, Spec: api.PodSpec{ Volumes: []api.Volume{{Name: "vol"}}, Containers: []api.Container{{Name: "ctr", Image: "image"}}, }, } err := handler.Admit(admission.NewAttributesRecord(&pod, namespace, "pods", "CREATE")) if err != nil { t.Errorf("Unexpected error returned from admission handler") } for i := range pod.Spec.Containers { memory := pod.Spec.Containers[i].Resources.Limits.Memory().String() cpu := pod.Spec.Containers[i].Resources.Limits.Cpu().String() if memory != "512Mi" { t.Errorf("Unexpected memory value %s", memory) } if cpu != "1" { t.Errorf("Unexpected cpu value %s", cpu) } } }
func TestAllowsReferencedSecretVolumes(t *testing.T) { ns := "myns" admit := NewServiceAccount(nil) admit.LimitSecretReferences = true // Add the default service account for the ns with a secret reference into the cache admit.serviceAccounts.Add(&api.ServiceAccount{ ObjectMeta: api.ObjectMeta{ Name: DefaultServiceAccountName, Namespace: ns, }, Secrets: []api.ObjectReference{ {Name: "foo"}, }, }) pod := &api.Pod{ Spec: api.PodSpec{ Volumes: []api.Volume{ {VolumeSource: api.VolumeSource{Secret: &api.SecretVolumeSource{SecretName: "foo"}}}, }, }, } attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) err := admit.Admit(attrs) if err != nil { t.Errorf("Unexpected error: %v", err) } }
// TestIgnoreThatWhichCannotBeKnown verifies that the plug-in does not reject objects that are unknown to RESTMapper func TestIgnoreThatWhichCannotBeKnown(t *testing.T) { handler := &lifecycle{} unknown := &UnknownObject{} err := handler.Admit(admission.NewAttributesRecord(unknown, "who-cares", "unknown", "what", "CREATE", nil)) if err != nil { t.Errorf("Admission control should not error if it finds an object it knows nothing about %v", err) } }
func TestAdmissionIgnoresDelete(t *testing.T) { namespace := "default" handler := createResourceQuota(&testclient.Fake{}, nil) err := handler.Admit(admission.NewAttributesRecord(nil, "Pod", namespace, "pods", "", admission.Delete, nil)) if err != nil { t.Errorf("ResourceQuota should admit all deletes: %v", err) } }
func TestAdmissionIgnoresDelete(t *testing.T) { namespace := "default" handler := NewResourceQuota(&client.Fake{}) err := handler.Admit(admission.NewAttributesRecord(nil, namespace, "pods", "DELETE")) if err != nil { t.Errorf("ResourceQuota should admit all deletes", err) } }
func TestIgnoresNonPodObject(t *testing.T) { obj := &api.Namespace{} attrs := admission.NewAttributesRecord(obj, "Pod", "myns", string(api.ResourcePods), admission.Create, nil) err := NewServiceAccount(nil).Admit(attrs) if err != nil { t.Errorf("Expected non pod object allowed, got err: %v", err) } }
func TestIgnoresNonPodResource(t *testing.T) { pod := &api.Pod{} attrs := admission.NewAttributesRecord(pod, "Pod", "myns", "myname", "CustomResource", "", admission.Create, nil) err := NewServiceAccount(nil).Admit(attrs) if err != nil { t.Errorf("Expected non-pod resource allowed, got err: %v", err) } }
// DeleteResource returns a function that will handle a resource deletion func DeleteResource(r RESTDeleter, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, resource, kind string, admit admission.Interface) restful.RouteFunction { return func(req *restful.Request, res *restful.Response) { w := res.ResponseWriter // TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer) timeout := parseTimeout(req.Request.URL.Query().Get("timeout")) namespace, name, err := namer.Name(req) if err != nil { errorJSON(err, codec, w) return } ctx := ctxFn(req) if len(namespace) > 0 { ctx = api.WithNamespace(ctx, namespace) } err = admit.Admit(admission.NewAttributesRecord(nil, namespace, resource, "DELETE")) if err != nil { errorJSON(err, codec, w) return } result, err := finishRequest(timeout, func() (runtime.Object, error) { return r.Delete(ctx, name) }) if err != nil { errorJSON(err, codec, w) return } // if the RESTDeleter returns a nil object, fill out a status. Callers may return a valid // object with the response. if result == nil { result = &api.Status{ Status: api.StatusSuccess, Code: http.StatusOK, Details: &api.StatusDetails{ ID: name, Kind: kind, }, } } else { // when a non-status response is returned, set the self link if _, ok := result.(*api.Status); !ok { if err := setSelfLink(result, req, namer); err != nil { errorJSON(err, codec, w) return } } } writeJSON(http.StatusOK, codec, result, w) } }
func TestIgnoresNonCreate(t *testing.T) { pod := &api.Pod{} for _, op := range []admission.Operation{admission.Update, admission.Delete, admission.Connect} { attrs := admission.NewAttributesRecord(pod, "Pod", "myns", "myname", string(api.ResourcePods), "", op, nil) handler := admission.NewChainHandler(NewServiceAccount(nil)) err := handler.Admit(attrs) if err != nil { t.Errorf("Expected %s operation allowed, got err: %v", op, err) } } }
// CreateResource returns a function that will handle a resource creation. func CreateResource(r rest.Creater, scope RequestScope, typer runtime.ObjectTyper, admit admission.Interface) restful.RouteFunction { return func(req *restful.Request, res *restful.Response) { w := res.ResponseWriter // TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer) timeout := parseTimeout(req.Request.URL.Query().Get("timeout")) namespace, err := scope.Namer.Namespace(req) if err != nil { errorJSON(err, scope.Codec, w) return } ctx := scope.ContextFunc(req) ctx = api.WithNamespace(ctx, namespace) body, err := readBody(req.Request) if err != nil { errorJSON(err, scope.Codec, w) return } obj := r.New() if err := scope.Codec.DecodeInto(body, obj); err != nil { err = transformDecodeError(typer, err, obj, body) errorJSON(err, scope.Codec, w) return } err = admit.Admit(admission.NewAttributesRecord(obj, scope.Kind, namespace, scope.Resource, "CREATE")) if err != nil { errorJSON(err, scope.Codec, w) return } result, err := finishRequest(timeout, func() (runtime.Object, error) { out, err := r.Create(ctx, obj) if status, ok := out.(*api.Status); ok && err == nil && status.Code == 0 { status.Code = http.StatusCreated } return out, err }) if err != nil { errorJSON(err, scope.Codec, w) return } if err := setSelfLink(result, req, scope.Namer); err != nil { errorJSON(err, scope.Codec, w) return } write(http.StatusCreated, scope.APIVersion, scope.Codec, result, w, req.Request) } }
// ensures the SecurityContext is denied if it defines anything more than Caps or Privileged func TestAdmission(t *testing.T) { handler := NewSecurityContextDeny(nil) var runAsUser int64 = 1 priv := true successCases := map[string]*api.SecurityContext{ "no sc": nil, "empty sc": {}, "valid sc": {Privileged: &priv, Capabilities: &api.Capabilities{}}, } pod := api.Pod{ Spec: api.PodSpec{ Containers: []api.Container{ {}, }, }, } for k, v := range successCases { pod.Spec.Containers[0].SecurityContext = v err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", "foo", string(api.ResourcePods), "ignored", nil)) if err != nil { t.Errorf("Unexpected error returned from admission handler for case %s", k) } } errorCases := map[string]*api.SecurityContext{ "run as user": {RunAsUser: &runAsUser}, "se linux optons": {SELinuxOptions: &api.SELinuxOptions{}}, "mixed settings": {Privileged: &priv, RunAsUser: &runAsUser, SELinuxOptions: &api.SELinuxOptions{}}, } for k, v := range errorCases { pod.Spec.Containers[0].SecurityContext = v err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", "foo", string(api.ResourcePods), "ignored", nil)) if err == nil { t.Errorf("Expected error returned from admission handler for case %s", k) } } }
func TestDeniesInvalidServiceAccount(t *testing.T) { ns := "myns" // Build a test client that the admission plugin can use to look up the service account missing from its cache client := testclient.NewSimpleFake() admit := NewServiceAccount(client) pod := &api.Pod{} attrs := admission.NewAttributesRecord(pod, "Pod", ns, "myname", string(api.ResourcePods), "", admission.Create, nil) err := admit.Admit(attrs) if err == nil { t.Errorf("Expected error for missing service account, got none") } }