Example #1
0
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)
	}

}
Example #2
0
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)
	}

}
Example #4
0
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())
	}
}
Example #5
0
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")
	}
}
Example #6
0
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)
	}
}
Example #7
0
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")
	}
}
Example #8
0
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")
	}
}
Example #9
0
// 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")
	}
}
Example #10
0
// 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")
	}
}
Example #11
0
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)
	}
}
Example #12
0
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")
	}
}
Example #13
0
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)
	}
}
Example #14
0
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")
	}
}
Example #15
0
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())
	}
}
Example #16
0
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())
	}
}
Example #17
0
// 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")
	}
}
Example #18
0
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)
	}
}
Example #19
0
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)
		}
	}
}
Example #20
0
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)
	}
}
Example #21
0
// 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)
	}
}
Example #22
0
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)
	}
}
Example #23
0
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)
	}
}
Example #24
0
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)
	}
}
Example #25
0
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)
	}
}
Example #26
0
// 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)
	}
}
Example #27
0
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)
	}
}
Example #29
0
// 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)
		}
	}
}
Example #30
0
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")
	}
}