more dependencies packages:

pkg/metrics
pkg/credentialprovider
pkg/security
pkg/securitycontext
pkg/serviceaccount
pkg/storage
pkg/fieldpath
This commit is contained in:
Chao Xu 2016-11-18 13:26:53 -08:00
parent f8b36bdd40
commit 4f3d0e3bde
21 changed files with 352 additions and 176 deletions

View File

@ -27,7 +27,7 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
dockertypes "github.com/docker/engine-api/types" dockertypes "github.com/docker/engine-api/types"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/util/sets"
) )
@ -306,17 +306,17 @@ func (k *unionDockerKeyring) Lookup(image string) ([]LazyAuthConfiguration, bool
// MakeDockerKeyring inspects the passedSecrets to see if they contain any DockerConfig secrets. If they do, // MakeDockerKeyring inspects the passedSecrets to see if they contain any DockerConfig secrets. If they do,
// then a DockerKeyring is built based on every hit and unioned with the defaultKeyring. // then a DockerKeyring is built based on every hit and unioned with the defaultKeyring.
// If they do not, then the default keyring is returned // If they do not, then the default keyring is returned
func MakeDockerKeyring(passedSecrets []api.Secret, defaultKeyring DockerKeyring) (DockerKeyring, error) { func MakeDockerKeyring(passedSecrets []v1.Secret, defaultKeyring DockerKeyring) (DockerKeyring, error) {
passedCredentials := []DockerConfig{} passedCredentials := []DockerConfig{}
for _, passedSecret := range passedSecrets { for _, passedSecret := range passedSecrets {
if dockerConfigJsonBytes, dockerConfigJsonExists := passedSecret.Data[api.DockerConfigJsonKey]; (passedSecret.Type == api.SecretTypeDockerConfigJson) && dockerConfigJsonExists && (len(dockerConfigJsonBytes) > 0) { if dockerConfigJsonBytes, dockerConfigJsonExists := passedSecret.Data[v1.DockerConfigJsonKey]; (passedSecret.Type == v1.SecretTypeDockerConfigJson) && dockerConfigJsonExists && (len(dockerConfigJsonBytes) > 0) {
dockerConfigJson := DockerConfigJson{} dockerConfigJson := DockerConfigJson{}
if err := json.Unmarshal(dockerConfigJsonBytes, &dockerConfigJson); err != nil { if err := json.Unmarshal(dockerConfigJsonBytes, &dockerConfigJson); err != nil {
return nil, err return nil, err
} }
passedCredentials = append(passedCredentials, dockerConfigJson.Auths) passedCredentials = append(passedCredentials, dockerConfigJson.Auths)
} else if dockercfgBytes, dockercfgExists := passedSecret.Data[api.DockerConfigKey]; (passedSecret.Type == api.SecretTypeDockercfg) && dockercfgExists && (len(dockercfgBytes) > 0) { } else if dockercfgBytes, dockercfgExists := passedSecret.Data[v1.DockerConfigKey]; (passedSecret.Type == v1.SecretTypeDockercfg) && dockercfgExists && (len(dockercfgBytes) > 0) {
dockercfg := DockerConfig{} dockercfg := DockerConfig{}
if err := json.Unmarshal(dockercfgBytes, &dockercfg); err != nil { if err := json.Unmarshal(dockercfgBytes, &dockercfg); err != nil {
return nil, err return nil, err

View File

@ -25,6 +25,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/v1"
) )
// formatMap formats map[string]string to a string. // formatMap formats map[string]string to a string.
@ -65,9 +66,10 @@ func ExtractFieldPathAsString(obj interface{}, fieldPath string) (string, error)
return "", fmt.Errorf("Unsupported fieldPath: %v", fieldPath) return "", fmt.Errorf("Unsupported fieldPath: %v", fieldPath)
} }
// TODO: move the functions below to pkg/api/util/resources
// ExtractResourceValueByContainerName extracts the value of a resource // ExtractResourceValueByContainerName extracts the value of a resource
// by providing container name // by providing container name
func ExtractResourceValueByContainerName(fs *api.ResourceFieldSelector, pod *api.Pod, containerName string) (string, error) { func ExtractResourceValueByContainerName(fs *v1.ResourceFieldSelector, pod *v1.Pod, containerName string) (string, error) {
container, err := findContainerInPod(pod, containerName) container, err := findContainerInPod(pod, containerName)
if err != nil { if err != nil {
return "", err return "", err
@ -77,7 +79,7 @@ func ExtractResourceValueByContainerName(fs *api.ResourceFieldSelector, pod *api
// ExtractResourceValueByContainerNameAndNodeAllocatable extracts the value of a resource // ExtractResourceValueByContainerNameAndNodeAllocatable extracts the value of a resource
// by providing container name and node allocatable // by providing container name and node allocatable
func ExtractResourceValueByContainerNameAndNodeAllocatable(fs *api.ResourceFieldSelector, pod *api.Pod, containerName string, nodeAllocatable api.ResourceList) (string, error) { func ExtractResourceValueByContainerNameAndNodeAllocatable(fs *v1.ResourceFieldSelector, pod *v1.Pod, containerName string, nodeAllocatable v1.ResourceList) (string, error) {
realContainer, err := findContainerInPod(pod, containerName) realContainer, err := findContainerInPod(pod, containerName)
if err != nil { if err != nil {
return "", err return "", err
@ -88,7 +90,7 @@ func ExtractResourceValueByContainerNameAndNodeAllocatable(fs *api.ResourceField
return "", fmt.Errorf("failed to perform a deep copy of container object: %v", err) return "", fmt.Errorf("failed to perform a deep copy of container object: %v", err)
} }
container, ok := containerCopy.(*api.Container) container, ok := containerCopy.(*v1.Container)
if !ok { if !ok {
return "", fmt.Errorf("unexpected type returned from deep copy of container object") return "", fmt.Errorf("unexpected type returned from deep copy of container object")
} }
@ -100,7 +102,32 @@ func ExtractResourceValueByContainerNameAndNodeAllocatable(fs *api.ResourceField
// ExtractContainerResourceValue extracts the value of a resource // ExtractContainerResourceValue extracts the value of a resource
// in an already known container // in an already known container
func ExtractContainerResourceValue(fs *api.ResourceFieldSelector, container *api.Container) (string, error) { func ExtractContainerResourceValue(fs *v1.ResourceFieldSelector, container *v1.Container) (string, error) {
divisor := resource.Quantity{}
if divisor.Cmp(fs.Divisor) == 0 {
divisor = resource.MustParse("1")
} else {
divisor = fs.Divisor
}
switch fs.Resource {
case "limits.cpu":
return convertResourceCPUToString(container.Resources.Limits.Cpu(), divisor)
case "limits.memory":
return convertResourceMemoryToString(container.Resources.Limits.Memory(), divisor)
case "requests.cpu":
return convertResourceCPUToString(container.Resources.Requests.Cpu(), divisor)
case "requests.memory":
return convertResourceMemoryToString(container.Resources.Requests.Memory(), divisor)
}
return "", fmt.Errorf("Unsupported container resource : %v", fs.Resource)
}
// TODO: remove this duplicate
// InternalExtractContainerResourceValue extracts the value of a resource
// in an already known container
func InternalExtractContainerResourceValue(fs *api.ResourceFieldSelector, container *api.Container) (string, error) {
divisor := resource.Quantity{} divisor := resource.Quantity{}
if divisor.Cmp(fs.Divisor) == 0 { if divisor.Cmp(fs.Divisor) == 0 {
divisor = resource.MustParse("1") divisor = resource.MustParse("1")
@ -123,7 +150,7 @@ func ExtractContainerResourceValue(fs *api.ResourceFieldSelector, container *api
} }
// findContainerInPod finds a container by its name in the provided pod // findContainerInPod finds a container by its name in the provided pod
func findContainerInPod(pod *api.Pod, containerName string) (*api.Container, error) { func findContainerInPod(pod *v1.Pod, containerName string) (*v1.Container, error) {
for _, container := range pod.Spec.Containers { for _, container := range pod.Spec.Containers {
if container.Name == containerName { if container.Name == containerName {
return &container, nil return &container, nil
@ -148,12 +175,12 @@ func convertResourceMemoryToString(memory *resource.Quantity, divisor resource.Q
// MergeContainerResourceLimits checks if a limit is applied for // MergeContainerResourceLimits checks if a limit is applied for
// the container, and if not, it sets the limit to the passed resource list. // the container, and if not, it sets the limit to the passed resource list.
func MergeContainerResourceLimits(container *api.Container, func MergeContainerResourceLimits(container *v1.Container,
allocatable api.ResourceList) { allocatable v1.ResourceList) {
if container.Resources.Limits == nil { if container.Resources.Limits == nil {
container.Resources.Limits = make(api.ResourceList) container.Resources.Limits = make(v1.ResourceList)
} }
for _, resource := range []api.ResourceName{api.ResourceCPU, api.ResourceMemory} { for _, resource := range []v1.ResourceName{v1.ResourceCPU, v1.ResourceMemory} {
if quantity, exists := container.Resources.Limits[resource]; !exists || quantity.IsZero() { if quantity, exists := container.Resources.Limits[resource]; !exists || quantity.IsZero() {
if cap, exists := allocatable[resource]; exists { if cap, exists := allocatable[resource]; exists {
container.Resources.Limits[resource] = *cap.Copy() container.Resources.Limits[resource] = *cap.Copy()

View File

@ -22,8 +22,8 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/v1"
) )
func TestExtractFieldPathAsString(t *testing.T) { func TestExtractFieldPathAsString(t *testing.T) {
@ -43,8 +43,8 @@ func TestExtractFieldPathAsString(t *testing.T) {
{ {
name: "ok - namespace", name: "ok - namespace",
fieldPath: "metadata.namespace", fieldPath: "metadata.namespace",
obj: &api.Pod{ obj: &v1.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Namespace: "object-namespace", Namespace: "object-namespace",
}, },
}, },
@ -53,8 +53,8 @@ func TestExtractFieldPathAsString(t *testing.T) {
{ {
name: "ok - name", name: "ok - name",
fieldPath: "metadata.name", fieldPath: "metadata.name",
obj: &api.Pod{ obj: &v1.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Name: "object-name", Name: "object-name",
}, },
}, },
@ -63,8 +63,8 @@ func TestExtractFieldPathAsString(t *testing.T) {
{ {
name: "ok - labels", name: "ok - labels",
fieldPath: "metadata.labels", fieldPath: "metadata.labels",
obj: &api.Pod{ obj: &v1.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Labels: map[string]string{"key": "value"}, Labels: map[string]string{"key": "value"},
}, },
}, },
@ -73,8 +73,8 @@ func TestExtractFieldPathAsString(t *testing.T) {
{ {
name: "ok - labels bslash n", name: "ok - labels bslash n",
fieldPath: "metadata.labels", fieldPath: "metadata.labels",
obj: &api.Pod{ obj: &v1.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Labels: map[string]string{"key": "value\n"}, Labels: map[string]string{"key": "value\n"},
}, },
}, },
@ -83,8 +83,8 @@ func TestExtractFieldPathAsString(t *testing.T) {
{ {
name: "ok - annotations", name: "ok - annotations",
fieldPath: "metadata.annotations", fieldPath: "metadata.annotations",
obj: &api.Pod{ obj: &v1.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Annotations: map[string]string{"builder": "john-doe"}, Annotations: map[string]string{"builder": "john-doe"},
}, },
}, },
@ -94,8 +94,8 @@ func TestExtractFieldPathAsString(t *testing.T) {
{ {
name: "invalid expression", name: "invalid expression",
fieldPath: "metadata.whoops", fieldPath: "metadata.whoops",
obj: &api.Pod{ obj: &v1.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Namespace: "object-namespace", Namespace: "object-namespace",
}, },
}, },
@ -119,26 +119,26 @@ func TestExtractFieldPathAsString(t *testing.T) {
} }
} }
func getPod(cname, cpuRequest, cpuLimit, memoryRequest, memoryLimit string) *api.Pod { func getPod(cname, cpuRequest, cpuLimit, memoryRequest, memoryLimit string) *v1.Pod {
resources := api.ResourceRequirements{ resources := v1.ResourceRequirements{
Limits: make(api.ResourceList), Limits: make(v1.ResourceList),
Requests: make(api.ResourceList), Requests: make(v1.ResourceList),
} }
if cpuLimit != "" { if cpuLimit != "" {
resources.Limits[api.ResourceCPU] = resource.MustParse(cpuLimit) resources.Limits[v1.ResourceCPU] = resource.MustParse(cpuLimit)
} }
if memoryLimit != "" { if memoryLimit != "" {
resources.Limits[api.ResourceMemory] = resource.MustParse(memoryLimit) resources.Limits[v1.ResourceMemory] = resource.MustParse(memoryLimit)
} }
if cpuRequest != "" { if cpuRequest != "" {
resources.Requests[api.ResourceCPU] = resource.MustParse(cpuRequest) resources.Requests[v1.ResourceCPU] = resource.MustParse(cpuRequest)
} }
if memoryRequest != "" { if memoryRequest != "" {
resources.Requests[api.ResourceMemory] = resource.MustParse(memoryRequest) resources.Requests[v1.ResourceMemory] = resource.MustParse(memoryRequest)
} }
return &api.Pod{ return &v1.Pod{
Spec: api.PodSpec{ Spec: v1.PodSpec{
Containers: []api.Container{ Containers: []v1.Container{
{ {
Name: cname, Name: cname,
Resources: resources, Resources: resources,
@ -150,14 +150,14 @@ func getPod(cname, cpuRequest, cpuLimit, memoryRequest, memoryLimit string) *api
func TestExtractResourceValue(t *testing.T) { func TestExtractResourceValue(t *testing.T) {
cases := []struct { cases := []struct {
fs *api.ResourceFieldSelector fs *v1.ResourceFieldSelector
pod *api.Pod pod *v1.Pod
cName string cName string
expectedValue string expectedValue string
expectedError error expectedError error
}{ }{
{ {
fs: &api.ResourceFieldSelector{ fs: &v1.ResourceFieldSelector{
Resource: "limits.cpu", Resource: "limits.cpu",
}, },
cName: "foo", cName: "foo",
@ -165,7 +165,7 @@ func TestExtractResourceValue(t *testing.T) {
expectedValue: "9", expectedValue: "9",
}, },
{ {
fs: &api.ResourceFieldSelector{ fs: &v1.ResourceFieldSelector{
Resource: "requests.cpu", Resource: "requests.cpu",
}, },
cName: "foo", cName: "foo",
@ -173,7 +173,7 @@ func TestExtractResourceValue(t *testing.T) {
expectedValue: "0", expectedValue: "0",
}, },
{ {
fs: &api.ResourceFieldSelector{ fs: &v1.ResourceFieldSelector{
Resource: "requests.cpu", Resource: "requests.cpu",
}, },
cName: "foo", cName: "foo",
@ -181,7 +181,7 @@ func TestExtractResourceValue(t *testing.T) {
expectedValue: "8", expectedValue: "8",
}, },
{ {
fs: &api.ResourceFieldSelector{ fs: &v1.ResourceFieldSelector{
Resource: "requests.cpu", Resource: "requests.cpu",
}, },
cName: "foo", cName: "foo",
@ -189,7 +189,7 @@ func TestExtractResourceValue(t *testing.T) {
expectedValue: "1", expectedValue: "1",
}, },
{ {
fs: &api.ResourceFieldSelector{ fs: &v1.ResourceFieldSelector{
Resource: "requests.cpu", Resource: "requests.cpu",
Divisor: resource.MustParse("100m"), Divisor: resource.MustParse("100m"),
}, },
@ -198,7 +198,7 @@ func TestExtractResourceValue(t *testing.T) {
expectedValue: "12", expectedValue: "12",
}, },
{ {
fs: &api.ResourceFieldSelector{ fs: &v1.ResourceFieldSelector{
Resource: "requests.memory", Resource: "requests.memory",
}, },
cName: "foo", cName: "foo",
@ -206,7 +206,7 @@ func TestExtractResourceValue(t *testing.T) {
expectedValue: "104857600", expectedValue: "104857600",
}, },
{ {
fs: &api.ResourceFieldSelector{ fs: &v1.ResourceFieldSelector{
Resource: "requests.memory", Resource: "requests.memory",
Divisor: resource.MustParse("1Mi"), Divisor: resource.MustParse("1Mi"),
}, },
@ -215,7 +215,7 @@ func TestExtractResourceValue(t *testing.T) {
expectedValue: "100", expectedValue: "100",
}, },
{ {
fs: &api.ResourceFieldSelector{ fs: &v1.ResourceFieldSelector{
Resource: "limits.memory", Resource: "limits.memory",
}, },
cName: "foo", cName: "foo",

View File

@ -21,7 +21,8 @@ import (
"time" "time"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/api/v1"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
"k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/master/ports" "k8s.io/kubernetes/pkg/master/ports"
"k8s.io/kubernetes/pkg/util/system" "k8s.io/kubernetes/pkg/util/system"
@ -53,7 +54,7 @@ type MetricsGrabber struct {
func NewMetricsGrabber(c clientset.Interface, kubelets bool, scheduler bool, controllers bool, apiServer bool) (*MetricsGrabber, error) { func NewMetricsGrabber(c clientset.Interface, kubelets bool, scheduler bool, controllers bool, apiServer bool) (*MetricsGrabber, error) {
registeredMaster := false registeredMaster := false
masterName := "" masterName := ""
nodeList, err := c.Core().Nodes().List(api.ListOptions{}) nodeList, err := c.Core().Nodes().List(v1.ListOptions{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -61,7 +62,7 @@ func NewMetricsGrabber(c clientset.Interface, kubelets bool, scheduler bool, con
glog.Warning("Can't find any Nodes in the API server to grab metrics from") glog.Warning("Can't find any Nodes in the API server to grab metrics from")
} }
for _, node := range nodeList.Items { for _, node := range nodeList.Items {
if system.IsMasterNode(&node) { if system.IsMasterNode(node.Name) {
registeredMaster = true registeredMaster = true
masterName = node.Name masterName = node.Name
break break
@ -85,7 +86,7 @@ func NewMetricsGrabber(c clientset.Interface, kubelets bool, scheduler bool, con
} }
func (g *MetricsGrabber) GrabFromKubelet(nodeName string) (KubeletMetrics, error) { func (g *MetricsGrabber) GrabFromKubelet(nodeName string) (KubeletMetrics, error) {
nodes, err := g.client.Core().Nodes().List(api.ListOptions{FieldSelector: fields.Set{api.ObjectNameField: nodeName}.AsSelector()}) nodes, err := g.client.Core().Nodes().List(v1.ListOptions{FieldSelector: fields.Set{api.ObjectNameField: nodeName}.AsSelector().String()})
if err != nil { if err != nil {
return KubeletMetrics{}, err return KubeletMetrics{}, err
} }
@ -166,7 +167,7 @@ func (g *MetricsGrabber) Grab() (MetricsCollection, error) {
} }
if g.grabFromKubelets { if g.grabFromKubelets {
result.KubeletMetrics = make(map[string]KubeletMetrics) result.KubeletMetrics = make(map[string]KubeletMetrics)
nodes, err := g.client.Core().Nodes().List(api.ListOptions{}) nodes, err := g.client.Core().Nodes().List(v1.ListOptions{})
if err != nil { if err != nil {
errs = append(errs, err) errs = append(errs, err)
} else { } else {

View File

@ -19,7 +19,7 @@ package apparmor
import ( import (
"strings" "strings"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1"
) )
// TODO: Move these values into the API package. // TODO: Move these values into the API package.
@ -38,7 +38,7 @@ const (
) )
// Checks whether app armor is required for pod to be run. // Checks whether app armor is required for pod to be run.
func isRequired(pod *api.Pod) bool { func isRequired(pod *v1.Pod) bool {
for key := range pod.Annotations { for key := range pod.Annotations {
if strings.HasPrefix(key, ContainerAnnotationKeyPrefix) { if strings.HasPrefix(key, ContainerAnnotationKeyPrefix) {
return true return true
@ -48,7 +48,7 @@ func isRequired(pod *api.Pod) bool {
} }
// Returns the name of the profile to use with the container. // Returns the name of the profile to use with the container.
func GetProfileName(pod *api.Pod, containerName string) string { func GetProfileName(pod *v1.Pod, containerName string) string {
return GetProfileNameFromPodAnnotations(pod.Annotations, containerName) return GetProfileNameFromPodAnnotations(pod.Annotations, containerName)
} }
@ -59,10 +59,19 @@ func GetProfileNameFromPodAnnotations(annotations map[string]string, containerNa
} }
// Sets the name of the profile to use with the container. // Sets the name of the profile to use with the container.
func SetProfileName(pod *api.Pod, containerName, profileName string) error { func SetProfileName(pod *v1.Pod, containerName, profileName string) error {
if pod.Annotations == nil { if pod.Annotations == nil {
pod.Annotations = map[string]string{} pod.Annotations = map[string]string{}
} }
pod.Annotations[ContainerAnnotationKeyPrefix+containerName] = profileName pod.Annotations[ContainerAnnotationKeyPrefix+containerName] = profileName
return nil return nil
} }
// Sets the name of the profile to use with the container.
func SetProfileNameFromPodAnnotations(annotations map[string]string, containerName, profileName string) error {
if annotations == nil {
return nil
}
annotations[ContainerAnnotationKeyPrefix+containerName] = profileName
return nil
}

View File

@ -25,7 +25,7 @@ import (
"path" "path"
"strings" "strings"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
utilconfig "k8s.io/kubernetes/pkg/util/config" utilconfig "k8s.io/kubernetes/pkg/util/config"
) )
@ -36,7 +36,7 @@ var isDisabledBuild bool
// Interface for validating that a pod with with an AppArmor profile can be run by a Node. // Interface for validating that a pod with with an AppArmor profile can be run by a Node.
type Validator interface { type Validator interface {
Validate(pod *api.Pod) error Validate(pod *v1.Pod) error
ValidateHost() error ValidateHost() error
} }
@ -60,7 +60,7 @@ type validator struct {
appArmorFS string appArmorFS string
} }
func (v *validator) Validate(pod *api.Pod) error { func (v *validator) Validate(pod *v1.Pod) error {
if !isRequired(pod) { if !isRequired(pod) {
return nil return nil
} }

View File

@ -21,7 +21,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -133,19 +133,19 @@ func TestValidateValidHost(t *testing.T) {
} }
// Test multi-container pod. // Test multi-container pod.
pod := &api.Pod{ pod := &v1.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Annotations: map[string]string{ Annotations: map[string]string{
ContainerAnnotationKeyPrefix + "init": ProfileNamePrefix + "foo-container", ContainerAnnotationKeyPrefix + "init": ProfileNamePrefix + "foo-container",
ContainerAnnotationKeyPrefix + "test1": ProfileRuntimeDefault, ContainerAnnotationKeyPrefix + "test1": ProfileRuntimeDefault,
ContainerAnnotationKeyPrefix + "test2": ProfileNamePrefix + "docker-default", ContainerAnnotationKeyPrefix + "test2": ProfileNamePrefix + "docker-default",
}, },
}, },
Spec: api.PodSpec{ Spec: v1.PodSpec{
InitContainers: []api.Container{ InitContainers: []v1.Container{
{Name: "init"}, {Name: "init"},
}, },
Containers: []api.Container{ Containers: []v1.Container{
{Name: "test1"}, {Name: "test1"},
{Name: "test2"}, {Name: "test2"},
{Name: "no-profile"}, {Name: "no-profile"},
@ -172,7 +172,7 @@ func TestParseProfileName(t *testing.T) {
} }
} }
func getPodWithProfile(profile string) *api.Pod { func getPodWithProfile(profile string) *v1.Pod {
annotations := map[string]string{ annotations := map[string]string{
ContainerAnnotationKeyPrefix + "test": profile, ContainerAnnotationKeyPrefix + "test": profile,
} }
@ -181,12 +181,12 @@ func getPodWithProfile(profile string) *api.Pod {
"foo": "bar", "foo": "bar",
} }
} }
return &api.Pod{ return &v1.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Annotations: annotations, Annotations: annotations,
}, },
Spec: api.PodSpec{ Spec: v1.PodSpec{
Containers: []api.Container{ Containers: []v1.Container{
{ {
Name: "test", Name: "test",
}, },

View File

@ -92,7 +92,7 @@ func (s *strategy) Validate(pod *api.Pod, container *api.Container) field.ErrorL
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
fieldPath := field.NewPath("pod", "metadata", "annotations").Key(apparmor.ContainerAnnotationKeyPrefix + container.Name) fieldPath := field.NewPath("pod", "metadata", "annotations").Key(apparmor.ContainerAnnotationKeyPrefix + container.Name)
profile := apparmor.GetProfileName(pod, container.Name) profile := apparmor.GetProfileNameFromPodAnnotations(pod.Annotations, container.Name)
if profile == "" { if profile == "" {
if len(s.allowedProfiles) > 0 { if len(s.allowedProfiles) > 0 {
allErrs = append(allErrs, field.Forbidden(fieldPath, "AppArmor profile must be set")) allErrs = append(allErrs, field.Forbidden(fieldPath, "AppArmor profile must be set"))

View File

@ -25,6 +25,7 @@ import (
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/security/apparmor" "k8s.io/kubernetes/pkg/security/apparmor"
"k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp"
@ -373,8 +374,11 @@ func TestValidateContainerSecurityContextFailures(t *testing.T) {
} }
failNilAppArmorPod := defaultPod() failNilAppArmorPod := defaultPod()
failInvalidAppArmorPod := defaultPod() v1FailInvalidAppArmorPod := defaultV1Pod()
apparmor.SetProfileName(failInvalidAppArmorPod, defaultContainerName, apparmor.ProfileNamePrefix+"foo") apparmor.SetProfileName(v1FailInvalidAppArmorPod, defaultContainerName, apparmor.ProfileNamePrefix+"foo")
failInvalidAppArmorPod := &api.Pod{}
v1.Convert_v1_Pod_To_api_Pod(v1FailInvalidAppArmorPod, failInvalidAppArmorPod, nil)
failAppArmorPSP := defaultPSP() failAppArmorPSP := defaultPSP()
failAppArmorPSP.Annotations = map[string]string{ failAppArmorPSP.Annotations = map[string]string{
apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault, apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault,
@ -669,8 +673,10 @@ func TestValidateContainerSecurityContextSuccess(t *testing.T) {
appArmorPSP.Annotations = map[string]string{ appArmorPSP.Annotations = map[string]string{
apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault, apparmor.AllowedProfilesAnnotationKey: apparmor.ProfileRuntimeDefault,
} }
appArmorPod := defaultPod() v1AppArmorPod := defaultV1Pod()
apparmor.SetProfileName(appArmorPod, defaultContainerName, apparmor.ProfileRuntimeDefault) apparmor.SetProfileName(v1AppArmorPod, defaultContainerName, apparmor.ProfileRuntimeDefault)
appArmorPod := &api.Pod{}
v1.Convert_v1_Pod_To_api_Pod(v1AppArmorPod, appArmorPod, nil)
privPSP := defaultPSP() privPSP := defaultPSP()
privPSP.Spec.Privileged = true privPSP.Spec.Privileged = true
@ -930,6 +936,30 @@ func defaultPod() *api.Pod {
} }
} }
func defaultV1Pod() *v1.Pod {
var notPriv bool = false
return &v1.Pod{
ObjectMeta: v1.ObjectMeta{
Annotations: map[string]string{},
},
Spec: v1.PodSpec{
SecurityContext: &v1.PodSecurityContext{
// fill in for test cases
},
Containers: []v1.Container{
{
Name: defaultContainerName,
SecurityContext: &v1.SecurityContext{
// expected to be set by defaulting mechanisms
Privileged: &notPriv,
// fill in the rest for test cases
},
},
},
},
}
}
// TestValidateAllowedVolumes will test that for every field of VolumeSource we can create // TestValidateAllowedVolumes will test that for every field of VolumeSource we can create
// a pod with that type of volume and deny it, accept it explicitly, or accept it with // a pod with that type of volume and deny it, accept it explicitly, or accept it with
// the FSTypeAll wildcard. // the FSTypeAll wildcard.

View File

@ -18,16 +18,17 @@ package securitycontext
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1"
dockercontainer "github.com/docker/engine-api/types/container" dockercontainer "github.com/docker/engine-api/types/container"
) )
// ValidSecurityContextWithContainerDefaults creates a valid security context provider based on // ValidSecurityContextWithContainerDefaults creates a valid security context provider based on
// empty container defaults. Used for testing. // empty container defaults. Used for testing.
func ValidSecurityContextWithContainerDefaults() *api.SecurityContext { func ValidSecurityContextWithContainerDefaults() *v1.SecurityContext {
priv := false priv := false
return &api.SecurityContext{ return &v1.SecurityContext{
Capabilities: &api.Capabilities{}, Capabilities: &v1.Capabilities{},
Privileged: &priv, Privileged: &priv,
} }
} }
@ -39,7 +40,17 @@ func NewFakeSecurityContextProvider() SecurityContextProvider {
type FakeSecurityContextProvider struct{} type FakeSecurityContextProvider struct{}
func (p FakeSecurityContextProvider) ModifyContainerConfig(pod *api.Pod, container *api.Container, config *dockercontainer.Config) { func (p FakeSecurityContextProvider) ModifyContainerConfig(pod *v1.Pod, container *v1.Container, config *dockercontainer.Config) {
} }
func (p FakeSecurityContextProvider) ModifyHostConfig(pod *api.Pod, container *api.Container, hostConfig *dockercontainer.HostConfig, supplementalGids []int64) { func (p FakeSecurityContextProvider) ModifyHostConfig(pod *v1.Pod, container *v1.Container, hostConfig *dockercontainer.HostConfig, supplementalGids []int64) {
}
// ValidInternalSecurityContextWithContainerDefaults creates a valid security context provider based on
// empty container defaults. Used for testing.
func ValidInternalSecurityContextWithContainerDefaults() *api.SecurityContext {
priv := false
return &api.SecurityContext{
Capabilities: &api.Capabilities{},
Privileged: &priv,
}
} }

View File

@ -20,7 +20,8 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/kubelet/leaky" "k8s.io/kubernetes/pkg/kubelet/leaky"
dockercontainer "github.com/docker/engine-api/types/container" dockercontainer "github.com/docker/engine-api/types/container"
@ -37,7 +38,7 @@ type SimpleSecurityContextProvider struct{}
// ModifyContainerConfig is called before the Docker createContainer call. // ModifyContainerConfig is called before the Docker createContainer call.
// The security context provider can make changes to the Config with which // The security context provider can make changes to the Config with which
// the container is created. // the container is created.
func (p SimpleSecurityContextProvider) ModifyContainerConfig(pod *api.Pod, container *api.Container, config *dockercontainer.Config) { func (p SimpleSecurityContextProvider) ModifyContainerConfig(pod *v1.Pod, container *v1.Container, config *dockercontainer.Config) {
effectiveSC := DetermineEffectiveSecurityContext(pod, container) effectiveSC := DetermineEffectiveSecurityContext(pod, container)
if effectiveSC == nil { if effectiveSC == nil {
return return
@ -50,7 +51,7 @@ func (p SimpleSecurityContextProvider) ModifyContainerConfig(pod *api.Pod, conta
// ModifyHostConfig is called before the Docker runContainer call. The // ModifyHostConfig is called before the Docker runContainer call. The
// security context provider can make changes to the HostConfig, affecting // security context provider can make changes to the HostConfig, affecting
// security options, whether the container is privileged, volume binds, etc. // security options, whether the container is privileged, volume binds, etc.
func (p SimpleSecurityContextProvider) ModifyHostConfig(pod *api.Pod, container *api.Container, hostConfig *dockercontainer.HostConfig, supplementalGids []int64) { func (p SimpleSecurityContextProvider) ModifyHostConfig(pod *v1.Pod, container *v1.Container, hostConfig *dockercontainer.HostConfig, supplementalGids []int64) {
// Apply supplemental groups // Apply supplemental groups
if container.Name != leaky.PodInfraContainerName { if container.Name != leaky.PodInfraContainerName {
// TODO: We skip application of supplemental groups to the // TODO: We skip application of supplemental groups to the
@ -96,7 +97,7 @@ func (p SimpleSecurityContextProvider) ModifyHostConfig(pod *api.Pod, container
} }
// ModifySecurityOptions adds SELinux options to config. // ModifySecurityOptions adds SELinux options to config.
func ModifySecurityOptions(config []string, selinuxOpts *api.SELinuxOptions) []string { func ModifySecurityOptions(config []string, selinuxOpts *v1.SELinuxOptions) []string {
config = modifySecurityOption(config, DockerLabelUser, selinuxOpts.User) config = modifySecurityOption(config, DockerLabelUser, selinuxOpts.User)
config = modifySecurityOption(config, DockerLabelRole, selinuxOpts.Role) config = modifySecurityOption(config, DockerLabelRole, selinuxOpts.Role)
config = modifySecurityOption(config, DockerLabelType, selinuxOpts.Type) config = modifySecurityOption(config, DockerLabelType, selinuxOpts.Type)
@ -115,7 +116,7 @@ func modifySecurityOption(config []string, name, value string) []string {
} }
// MakeCapabilities creates string slices from Capability slices // MakeCapabilities creates string slices from Capability slices
func MakeCapabilities(capAdd []api.Capability, capDrop []api.Capability) ([]string, []string) { func MakeCapabilities(capAdd []v1.Capability, capDrop []v1.Capability) ([]string, []string) {
var ( var (
addCaps []string addCaps []string
dropCaps []string dropCaps []string
@ -129,7 +130,7 @@ func MakeCapabilities(capAdd []api.Capability, capDrop []api.Capability) ([]stri
return addCaps, dropCaps return addCaps, dropCaps
} }
func DetermineEffectiveSecurityContext(pod *api.Pod, container *api.Container) *api.SecurityContext { func DetermineEffectiveSecurityContext(pod *v1.Pod, container *v1.Container) *v1.SecurityContext {
effectiveSc := securityContextFromPodSecurityContext(pod) effectiveSc := securityContextFromPodSecurityContext(pod)
containerSc := container.SecurityContext containerSc := container.SecurityContext
@ -143,6 +144,78 @@ func DetermineEffectiveSecurityContext(pod *api.Pod, container *api.Container) *
return containerSc return containerSc
} }
if containerSc.SELinuxOptions != nil {
effectiveSc.SELinuxOptions = new(v1.SELinuxOptions)
*effectiveSc.SELinuxOptions = *containerSc.SELinuxOptions
}
if containerSc.Capabilities != nil {
effectiveSc.Capabilities = new(v1.Capabilities)
*effectiveSc.Capabilities = *containerSc.Capabilities
}
if containerSc.Privileged != nil {
effectiveSc.Privileged = new(bool)
*effectiveSc.Privileged = *containerSc.Privileged
}
if containerSc.RunAsUser != nil {
effectiveSc.RunAsUser = new(int64)
*effectiveSc.RunAsUser = *containerSc.RunAsUser
}
if containerSc.RunAsNonRoot != nil {
effectiveSc.RunAsNonRoot = new(bool)
*effectiveSc.RunAsNonRoot = *containerSc.RunAsNonRoot
}
if containerSc.ReadOnlyRootFilesystem != nil {
effectiveSc.ReadOnlyRootFilesystem = new(bool)
*effectiveSc.ReadOnlyRootFilesystem = *containerSc.ReadOnlyRootFilesystem
}
return effectiveSc
}
func securityContextFromPodSecurityContext(pod *v1.Pod) *v1.SecurityContext {
if pod.Spec.SecurityContext == nil {
return nil
}
synthesized := &v1.SecurityContext{}
if pod.Spec.SecurityContext.SELinuxOptions != nil {
synthesized.SELinuxOptions = &v1.SELinuxOptions{}
*synthesized.SELinuxOptions = *pod.Spec.SecurityContext.SELinuxOptions
}
if pod.Spec.SecurityContext.RunAsUser != nil {
synthesized.RunAsUser = new(int64)
*synthesized.RunAsUser = *pod.Spec.SecurityContext.RunAsUser
}
if pod.Spec.SecurityContext.RunAsNonRoot != nil {
synthesized.RunAsNonRoot = new(bool)
*synthesized.RunAsNonRoot = *pod.Spec.SecurityContext.RunAsNonRoot
}
return synthesized
}
// TODO: remove the duplicate code
func InternalDetermineEffectiveSecurityContext(pod *api.Pod, container *api.Container) *api.SecurityContext {
effectiveSc := internalSecurityContextFromPodSecurityContext(pod)
containerSc := container.SecurityContext
if effectiveSc == nil && containerSc == nil {
return nil
}
if effectiveSc != nil && containerSc == nil {
return effectiveSc
}
if effectiveSc == nil && containerSc != nil {
return containerSc
}
if containerSc.SELinuxOptions != nil { if containerSc.SELinuxOptions != nil {
effectiveSc.SELinuxOptions = new(api.SELinuxOptions) effectiveSc.SELinuxOptions = new(api.SELinuxOptions)
*effectiveSc.SELinuxOptions = *containerSc.SELinuxOptions *effectiveSc.SELinuxOptions = *containerSc.SELinuxOptions
@ -176,7 +249,7 @@ func DetermineEffectiveSecurityContext(pod *api.Pod, container *api.Container) *
return effectiveSc return effectiveSc
} }
func securityContextFromPodSecurityContext(pod *api.Pod) *api.SecurityContext { func internalSecurityContextFromPodSecurityContext(pod *api.Pod) *api.SecurityContext {
if pod.Spec.SecurityContext == nil { if pod.Spec.SecurityContext == nil {
return nil return nil
} }

View File

@ -23,8 +23,8 @@ import (
"testing" "testing"
dockercontainer "github.com/docker/engine-api/types/container" dockercontainer "github.com/docker/engine-api/types/container"
"k8s.io/kubernetes/pkg/api"
apitesting "k8s.io/kubernetes/pkg/api/testing" apitesting "k8s.io/kubernetes/pkg/api/testing"
"k8s.io/kubernetes/pkg/api/v1"
) )
func TestModifyContainerConfig(t *testing.T) { func TestModifyContainerConfig(t *testing.T) {
@ -33,13 +33,13 @@ func TestModifyContainerConfig(t *testing.T) {
cases := []struct { cases := []struct {
name string name string
podSc *api.PodSecurityContext podSc *v1.PodSecurityContext
sc *api.SecurityContext sc *v1.SecurityContext
expected *dockercontainer.Config expected *dockercontainer.Config
}{ }{
{ {
name: "container.SecurityContext.RunAsUser set", name: "container.SecurityContext.RunAsUser set",
sc: &api.SecurityContext{ sc: &v1.SecurityContext{
RunAsUser: &uid, RunAsUser: &uid,
}, },
expected: &dockercontainer.Config{ expected: &dockercontainer.Config{
@ -48,12 +48,12 @@ func TestModifyContainerConfig(t *testing.T) {
}, },
{ {
name: "no RunAsUser value set", name: "no RunAsUser value set",
sc: &api.SecurityContext{}, sc: &v1.SecurityContext{},
expected: &dockercontainer.Config{}, expected: &dockercontainer.Config{},
}, },
{ {
name: "pod.Spec.SecurityContext.RunAsUser set", name: "pod.Spec.SecurityContext.RunAsUser set",
podSc: &api.PodSecurityContext{ podSc: &v1.PodSecurityContext{
RunAsUser: &uid, RunAsUser: &uid,
}, },
expected: &dockercontainer.Config{ expected: &dockercontainer.Config{
@ -62,10 +62,10 @@ func TestModifyContainerConfig(t *testing.T) {
}, },
{ {
name: "container.SecurityContext.RunAsUser overrides pod.Spec.SecurityContext.RunAsUser", name: "container.SecurityContext.RunAsUser overrides pod.Spec.SecurityContext.RunAsUser",
podSc: &api.PodSecurityContext{ podSc: &v1.PodSecurityContext{
RunAsUser: &uid, RunAsUser: &uid,
}, },
sc: &api.SecurityContext{ sc: &v1.SecurityContext{
RunAsUser: &overrideUid, RunAsUser: &overrideUid,
}, },
expected: &dockercontainer.Config{ expected: &dockercontainer.Config{
@ -75,9 +75,9 @@ func TestModifyContainerConfig(t *testing.T) {
} }
provider := NewSimpleSecurityContextProvider() provider := NewSimpleSecurityContextProvider()
dummyContainer := &api.Container{} dummyContainer := &v1.Container{}
for _, tc := range cases { for _, tc := range cases {
pod := &api.Pod{Spec: api.PodSpec{SecurityContext: tc.podSc}} pod := &v1.Pod{Spec: v1.PodSpec{SecurityContext: tc.podSc}}
dummyContainer.SecurityContext = tc.sc dummyContainer.SecurityContext = tc.sc
dockerCfg := &dockercontainer.Config{} dockerCfg := &dockercontainer.Config{}
@ -91,7 +91,7 @@ func TestModifyContainerConfig(t *testing.T) {
func TestModifyHostConfig(t *testing.T) { func TestModifyHostConfig(t *testing.T) {
priv := true priv := true
setPrivSC := &api.SecurityContext{} setPrivSC := &v1.SecurityContext{}
setPrivSC.Privileged = &priv setPrivSC.Privileged = &priv
setPrivHC := &dockercontainer.HostConfig{ setPrivHC := &dockercontainer.HostConfig{
Privileged: true, Privileged: true,
@ -115,8 +115,8 @@ func TestModifyHostConfig(t *testing.T) {
cases := []struct { cases := []struct {
name string name string
podSc *api.PodSecurityContext podSc *v1.PodSecurityContext
sc *api.SecurityContext sc *v1.SecurityContext
expected *dockercontainer.HostConfig expected *dockercontainer.HostConfig
}{ }{
{ {
@ -131,21 +131,21 @@ func TestModifyHostConfig(t *testing.T) {
}, },
{ {
name: "container.SecurityContext.Capabilities", name: "container.SecurityContext.Capabilities",
sc: &api.SecurityContext{ sc: &v1.SecurityContext{
Capabilities: inputCapabilities(), Capabilities: inputCapabilities(),
}, },
expected: setCapsHC, expected: setCapsHC,
}, },
{ {
name: "container.SecurityContext.SELinuxOptions", name: "container.SecurityContext.SELinuxOptions",
sc: &api.SecurityContext{ sc: &v1.SecurityContext{
SELinuxOptions: inputSELinuxOptions(), SELinuxOptions: inputSELinuxOptions(),
}, },
expected: setSELinuxHC, expected: setSELinuxHC,
}, },
{ {
name: "pod.Spec.SecurityContext.SELinuxOptions", name: "pod.Spec.SecurityContext.SELinuxOptions",
podSc: &api.PodSecurityContext{ podSc: &v1.PodSecurityContext{
SELinuxOptions: inputSELinuxOptions(), SELinuxOptions: inputSELinuxOptions(),
}, },
expected: setSELinuxHC, expected: setSELinuxHC,
@ -159,10 +159,10 @@ func TestModifyHostConfig(t *testing.T) {
} }
provider := NewSimpleSecurityContextProvider() provider := NewSimpleSecurityContextProvider()
dummyContainer := &api.Container{} dummyContainer := &v1.Container{}
for _, tc := range cases { for _, tc := range cases {
pod := &api.Pod{Spec: api.PodSpec{SecurityContext: tc.podSc}} pod := &v1.Pod{Spec: v1.PodSpec{SecurityContext: tc.podSc}}
dummyContainer.SecurityContext = tc.sc dummyContainer.SecurityContext = tc.sc
dockerCfg := &dockercontainer.HostConfig{} dockerCfg := &dockercontainer.HostConfig{}
@ -175,7 +175,7 @@ func TestModifyHostConfig(t *testing.T) {
} }
func TestModifyHostConfigPodSecurityContext(t *testing.T) { func TestModifyHostConfigPodSecurityContext(t *testing.T) {
supplementalGroupsSC := &api.PodSecurityContext{} supplementalGroupsSC := &v1.PodSecurityContext{}
supplementalGroupsSC.SupplementalGroups = []int64{2222} supplementalGroupsSC.SupplementalGroups = []int64{2222}
supplementalGroupHC := fullValidHostConfig() supplementalGroupHC := fullValidHostConfig()
supplementalGroupHC.GroupAdd = []string{"2222"} supplementalGroupHC.GroupAdd = []string{"2222"}
@ -189,7 +189,7 @@ func TestModifyHostConfigPodSecurityContext(t *testing.T) {
extraSupplementalGroup := []int64{1234} extraSupplementalGroup := []int64{1234}
testCases := map[string]struct { testCases := map[string]struct {
securityContext *api.PodSecurityContext securityContext *v1.PodSecurityContext
expected *dockercontainer.HostConfig expected *dockercontainer.HostConfig
extraSupplementalGroups []int64 extraSupplementalGroups []int64
}{ }{
@ -204,12 +204,12 @@ func TestModifyHostConfigPodSecurityContext(t *testing.T) {
extraSupplementalGroups: nil, extraSupplementalGroups: nil,
}, },
"FSGroup": { "FSGroup": {
securityContext: &api.PodSecurityContext{FSGroup: &fsGroup}, securityContext: &v1.PodSecurityContext{FSGroup: &fsGroup},
expected: fsGroupHC, expected: fsGroupHC,
extraSupplementalGroups: nil, extraSupplementalGroups: nil,
}, },
"FSGroup + SupplementalGroups": { "FSGroup + SupplementalGroups": {
securityContext: &api.PodSecurityContext{ securityContext: &v1.PodSecurityContext{
SupplementalGroups: []int64{2222}, SupplementalGroups: []int64{2222},
FSGroup: &fsGroup, FSGroup: &fsGroup,
}, },
@ -229,10 +229,10 @@ func TestModifyHostConfigPodSecurityContext(t *testing.T) {
} }
provider := NewSimpleSecurityContextProvider() provider := NewSimpleSecurityContextProvider()
dummyContainer := &api.Container{} dummyContainer := &v1.Container{}
dummyContainer.SecurityContext = fullValidSecurityContext() dummyContainer.SecurityContext = fullValidSecurityContext()
dummyPod := &api.Pod{ dummyPod := &v1.Pod{
Spec: apitesting.DeepEqualSafePodSpec(), Spec: apitesting.V1DeepEqualSafePodSpec(),
} }
for k, v := range testCases { for k, v := range testCases {
@ -277,9 +277,9 @@ func TestModifySecurityOption(t *testing.T) {
} }
} }
func overridePodSecurityContext() *api.PodSecurityContext { func overridePodSecurityContext() *v1.PodSecurityContext {
return &api.PodSecurityContext{ return &v1.PodSecurityContext{
SELinuxOptions: &api.SELinuxOptions{ SELinuxOptions: &v1.SELinuxOptions{
User: "user2", User: "user2",
Role: "role2", Role: "role2",
Type: "type2", Type: "type2",
@ -288,30 +288,30 @@ func overridePodSecurityContext() *api.PodSecurityContext {
} }
} }
func fullValidPodSecurityContext() *api.PodSecurityContext { func fullValidPodSecurityContext() *v1.PodSecurityContext {
return &api.PodSecurityContext{ return &v1.PodSecurityContext{
SELinuxOptions: inputSELinuxOptions(), SELinuxOptions: inputSELinuxOptions(),
} }
} }
func fullValidSecurityContext() *api.SecurityContext { func fullValidSecurityContext() *v1.SecurityContext {
priv := true priv := true
return &api.SecurityContext{ return &v1.SecurityContext{
Privileged: &priv, Privileged: &priv,
Capabilities: inputCapabilities(), Capabilities: inputCapabilities(),
SELinuxOptions: inputSELinuxOptions(), SELinuxOptions: inputSELinuxOptions(),
} }
} }
func inputCapabilities() *api.Capabilities { func inputCapabilities() *v1.Capabilities {
return &api.Capabilities{ return &v1.Capabilities{
Add: []api.Capability{"addCapA", "addCapB"}, Add: []v1.Capability{"addCapA", "addCapB"},
Drop: []api.Capability{"dropCapA", "dropCapB"}, Drop: []v1.Capability{"dropCapA", "dropCapB"},
} }
} }
func inputSELinuxOptions() *api.SELinuxOptions { func inputSELinuxOptions() *v1.SELinuxOptions {
return &api.SELinuxOptions{ return &v1.SELinuxOptions{
User: "user", User: "user",
Role: "role", Role: "role",
Type: "type", Type: "type",

View File

@ -17,7 +17,7 @@ limitations under the License.
package securitycontext package securitycontext
import ( import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1"
dockercontainer "github.com/docker/engine-api/types/container" dockercontainer "github.com/docker/engine-api/types/container"
) )
@ -26,7 +26,7 @@ type SecurityContextProvider interface {
// ModifyContainerConfig is called before the Docker createContainer call. // ModifyContainerConfig is called before the Docker createContainer call.
// The security context provider can make changes to the Config with which // The security context provider can make changes to the Config with which
// the container is created. // the container is created.
ModifyContainerConfig(pod *api.Pod, container *api.Container, config *dockercontainer.Config) ModifyContainerConfig(pod *v1.Pod, container *v1.Container, config *dockercontainer.Config)
// ModifyHostConfig is called before the Docker createContainer call. // ModifyHostConfig is called before the Docker createContainer call.
// The security context provider can make changes to the HostConfig, affecting // The security context provider can make changes to the HostConfig, affecting
@ -37,7 +37,7 @@ type SecurityContextProvider interface {
// - pod: the pod to modify the docker hostconfig for // - pod: the pod to modify the docker hostconfig for
// - container: the container to modify the hostconfig for // - container: the container to modify the hostconfig for
// - supplementalGids: additional supplemental GIDs associated with the pod's volumes // - supplementalGids: additional supplemental GIDs associated with the pod's volumes
ModifyHostConfig(pod *api.Pod, container *api.Container, hostConfig *dockercontainer.HostConfig, supplementalGids []int64) ModifyHostConfig(pod *v1.Pod, container *v1.Container, hostConfig *dockercontainer.HostConfig, supplementalGids []int64)
} }
const ( const (

View File

@ -20,12 +20,12 @@ import (
"fmt" "fmt"
"strings" "strings"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1"
) )
// HasPrivilegedRequest returns the value of SecurityContext.Privileged, taking into account // HasPrivilegedRequest returns the value of SecurityContext.Privileged, taking into account
// the possibility of nils // the possibility of nils
func HasPrivilegedRequest(container *api.Container) bool { func HasPrivilegedRequest(container *v1.Container) bool {
if container.SecurityContext == nil { if container.SecurityContext == nil {
return false return false
} }
@ -37,7 +37,7 @@ func HasPrivilegedRequest(container *api.Container) bool {
// HasCapabilitiesRequest returns true if Adds or Drops are defined in the security context // HasCapabilitiesRequest returns true if Adds or Drops are defined in the security context
// capabilities, taking into account nils // capabilities, taking into account nils
func HasCapabilitiesRequest(container *api.Container) bool { func HasCapabilitiesRequest(container *v1.Container) bool {
if container.SecurityContext == nil { if container.SecurityContext == nil {
return false return false
} }
@ -52,14 +52,14 @@ const expectedSELinuxFields = 4
// ParseSELinuxOptions parses a string containing a full SELinux context // ParseSELinuxOptions parses a string containing a full SELinux context
// (user, role, type, and level) into an SELinuxOptions object. If the // (user, role, type, and level) into an SELinuxOptions object. If the
// context is malformed, an error is returned. // context is malformed, an error is returned.
func ParseSELinuxOptions(context string) (*api.SELinuxOptions, error) { func ParseSELinuxOptions(context string) (*v1.SELinuxOptions, error) {
fields := strings.SplitN(context, ":", expectedSELinuxFields) fields := strings.SplitN(context, ":", expectedSELinuxFields)
if len(fields) != expectedSELinuxFields { if len(fields) != expectedSELinuxFields {
return nil, fmt.Errorf("expected %v fields in selinux; got %v (context: %v)", expectedSELinuxFields, len(fields), context) return nil, fmt.Errorf("expected %v fields in selinux; got %v (context: %v)", expectedSELinuxFields, len(fields), context)
} }
return &api.SELinuxOptions{ return &v1.SELinuxOptions{
User: fields[0], User: fields[0],
Role: fields[1], Role: fields[1],
Type: fields[2], Type: fields[2],
@ -68,7 +68,7 @@ func ParseSELinuxOptions(context string) (*api.SELinuxOptions, error) {
} }
// HasNonRootUID returns true if the runAsUser is set and is greater than 0. // HasNonRootUID returns true if the runAsUser is set and is greater than 0.
func HasRootUID(container *api.Container) bool { func HasRootUID(container *v1.Container) bool {
if container.SecurityContext == nil { if container.SecurityContext == nil {
return false return false
} }
@ -79,11 +79,11 @@ func HasRootUID(container *api.Container) bool {
} }
// HasRunAsUser determines if the sc's runAsUser field is set. // HasRunAsUser determines if the sc's runAsUser field is set.
func HasRunAsUser(container *api.Container) bool { func HasRunAsUser(container *v1.Container) bool {
return container.SecurityContext != nil && container.SecurityContext.RunAsUser != nil return container.SecurityContext != nil && container.SecurityContext.RunAsUser != nil
} }
// HasRootRunAsUser returns true if the run as user is set and it is set to 0. // HasRootRunAsUser returns true if the run as user is set and it is set to 0.
func HasRootRunAsUser(container *api.Container) bool { func HasRootRunAsUser(container *v1.Container) bool {
return HasRunAsUser(container) && HasRootUID(container) return HasRunAsUser(container) && HasRootUID(container)
} }

View File

@ -19,19 +19,19 @@ package securitycontext
import ( import (
"testing" "testing"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1"
) )
func TestParseSELinuxOptions(t *testing.T) { func TestParseSELinuxOptions(t *testing.T) {
cases := []struct { cases := []struct {
name string name string
input string input string
expected *api.SELinuxOptions expected *v1.SELinuxOptions
}{ }{
{ {
name: "simple", name: "simple",
input: "user_t:role_t:type_t:s0", input: "user_t:role_t:type_t:s0",
expected: &api.SELinuxOptions{ expected: &v1.SELinuxOptions{
User: "user_t", User: "user_t",
Role: "role_t", Role: "role_t",
Type: "type_t", Type: "type_t",
@ -41,7 +41,7 @@ func TestParseSELinuxOptions(t *testing.T) {
{ {
name: "simple + categories", name: "simple + categories",
input: "user_t:role_t:type_t:s0:c0", input: "user_t:role_t:type_t:s0:c0",
expected: &api.SELinuxOptions{ expected: &v1.SELinuxOptions{
User: "user_t", User: "user_t",
Role: "role_t", Role: "role_t",
Type: "type_t", Type: "type_t",
@ -69,7 +69,7 @@ func TestParseSELinuxOptions(t *testing.T) {
} }
} }
func compareContexts(name string, ex, ac *api.SELinuxOptions, t *testing.T) { func compareContexts(name string, ex, ac *v1.SELinuxOptions, t *testing.T) {
if e, a := ex.User, ac.User; e != a { if e, a := ex.User, ac.User; e != a {
t.Errorf("%v: expected user: %v, got: %v", name, e, a) t.Errorf("%v: expected user: %v, got: %v", name, e, a)
} }
@ -84,8 +84,8 @@ func compareContexts(name string, ex, ac *api.SELinuxOptions, t *testing.T) {
} }
} }
func containerWithUser(ptr *int64) *api.Container { func containerWithUser(ptr *int64) *v1.Container {
return &api.Container{SecurityContext: &api.SecurityContext{RunAsUser: ptr}} return &v1.Container{SecurityContext: &v1.SecurityContext{RunAsUser: ptr}}
} }
func TestHaRootUID(t *testing.T) { func TestHaRootUID(t *testing.T) {
@ -93,11 +93,11 @@ func TestHaRootUID(t *testing.T) {
var root int64 = 0 var root int64 = 0
tests := map[string]struct { tests := map[string]struct {
container *api.Container container *v1.Container
expect bool expect bool
}{ }{
"nil sc": { "nil sc": {
container: &api.Container{SecurityContext: nil}, container: &v1.Container{SecurityContext: nil},
}, },
"nil runAsuser": { "nil runAsuser": {
container: containerWithUser(nil), container: containerWithUser(nil),
@ -123,11 +123,11 @@ func TestHasRunAsUser(t *testing.T) {
var runAsUser int64 = 0 var runAsUser int64 = 0
tests := map[string]struct { tests := map[string]struct {
container *api.Container container *v1.Container
expect bool expect bool
}{ }{
"nil sc": { "nil sc": {
container: &api.Container{SecurityContext: nil}, container: &v1.Container{SecurityContext: nil},
}, },
"nil runAsUser": { "nil runAsUser": {
container: containerWithUser(nil), container: containerWithUser(nil),
@ -151,11 +151,11 @@ func TestHasRootRunAsUser(t *testing.T) {
var root int64 = 0 var root int64 = 0
tests := map[string]struct { tests := map[string]struct {
container *api.Container container *v1.Container
expect bool expect bool
}{ }{
"nil sc": { "nil sc": {
container: &api.Container{SecurityContext: nil}, container: &v1.Container{SecurityContext: nil},
}, },
"nil runAsuser": { "nil runAsuser": {
container: containerWithUser(nil), container: containerWithUser(nil),

View File

@ -26,7 +26,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/auth/authenticator" "k8s.io/kubernetes/pkg/auth/authenticator"
"k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/auth/user"
@ -47,14 +47,14 @@ const (
// ServiceAccountTokenGetter defines functions to retrieve a named service account and secret // ServiceAccountTokenGetter defines functions to retrieve a named service account and secret
type ServiceAccountTokenGetter interface { type ServiceAccountTokenGetter interface {
GetServiceAccount(namespace, name string) (*api.ServiceAccount, error) GetServiceAccount(namespace, name string) (*v1.ServiceAccount, error)
GetSecret(namespace, name string) (*api.Secret, error) GetSecret(namespace, name string) (*v1.Secret, error)
} }
type TokenGenerator interface { type TokenGenerator interface {
// GenerateToken generates a token which will identify the given ServiceAccount. // GenerateToken generates a token which will identify the given ServiceAccount.
// The returned token will be stored in the given (and yet-unpersisted) Secret. // The returned token will be stored in the given (and yet-unpersisted) Secret.
GenerateToken(serviceAccount api.ServiceAccount, secret api.Secret) (string, error) GenerateToken(serviceAccount v1.ServiceAccount, secret v1.Secret) (string, error)
} }
// ReadPrivateKey is a helper function for reading a private key from a PEM-encoded file // ReadPrivateKey is a helper function for reading a private key from a PEM-encoded file
@ -148,7 +148,7 @@ type jwtTokenGenerator struct {
privateKey interface{} privateKey interface{}
} }
func (j *jwtTokenGenerator) GenerateToken(serviceAccount api.ServiceAccount, secret api.Secret) (string, error) { func (j *jwtTokenGenerator) GenerateToken(serviceAccount v1.ServiceAccount, secret v1.Secret) (string, error) {
var method jwt.SigningMethod var method jwt.SigningMethod
switch privateKey := j.privateKey.(type) { switch privateKey := j.privateKey.(type) {
case *rsa.PrivateKey: case *rsa.PrivateKey:
@ -299,7 +299,7 @@ func (j *jwtTokenAuthenticator) AuthenticateToken(token string) (user.Info, bool
glog.V(4).Infof("Could not retrieve token %s/%s for service account %s/%s: %v", namespace, secretName, namespace, serviceAccountName, err) glog.V(4).Infof("Could not retrieve token %s/%s for service account %s/%s: %v", namespace, secretName, namespace, serviceAccountName, err)
return nil, false, errors.New("Token has been invalidated") return nil, false, errors.New("Token has been invalidated")
} }
if bytes.Compare(secret.Data[api.ServiceAccountTokenKey], []byte(token)) != 0 { if bytes.Compare(secret.Data[v1.ServiceAccountTokenKey], []byte(token)) != 0 {
glog.V(4).Infof("Token contents no longer matches %s/%s for service account %s/%s", namespace, secretName, namespace, serviceAccountName) glog.V(4).Infof("Token contents no longer matches %s/%s for service account %s/%s", namespace, secretName, namespace, serviceAccountName)
return nil, false, errors.New("Token does not match server's copy") return nil, false, errors.New("Token does not match server's copy")
} }

View File

@ -22,9 +22,9 @@ import (
"reflect" "reflect"
"testing" "testing"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/v1"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/fake"
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount" serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
"k8s.io/kubernetes/pkg/serviceaccount" "k8s.io/kubernetes/pkg/serviceaccount"
) )
@ -164,21 +164,21 @@ func TestTokenGenerateAndValidate(t *testing.T) {
expectedUserUID := "12345" expectedUserUID := "12345"
// Related API objects // Related API objects
serviceAccount := &api.ServiceAccount{ serviceAccount := &v1.ServiceAccount{
ObjectMeta: api.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Name: "my-service-account", Name: "my-service-account",
UID: "12345", UID: "12345",
Namespace: "test", Namespace: "test",
}, },
} }
rsaSecret := &api.Secret{ rsaSecret := &v1.Secret{
ObjectMeta: api.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Name: "my-rsa-secret", Name: "my-rsa-secret",
Namespace: "test", Namespace: "test",
}, },
} }
ecdsaSecret := &api.Secret{ ecdsaSecret := &v1.Secret{
ObjectMeta: api.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Name: "my-ecdsa-secret", Name: "my-ecdsa-secret",
Namespace: "test", Namespace: "test",
}, },

View File

@ -21,6 +21,7 @@ import (
"strings" "strings"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/auth/user"
) )
@ -84,7 +85,28 @@ func UserInfo(namespace, name, uid string) user.Info {
} }
// IsServiceAccountToken returns true if the secret is a valid api token for the service account // IsServiceAccountToken returns true if the secret is a valid api token for the service account
func IsServiceAccountToken(secret *api.Secret, sa *api.ServiceAccount) bool { func IsServiceAccountToken(secret *v1.Secret, sa *v1.ServiceAccount) bool {
if secret.Type != v1.SecretTypeServiceAccountToken {
return false
}
name := secret.Annotations[v1.ServiceAccountNameKey]
uid := secret.Annotations[v1.ServiceAccountUIDKey]
if name != sa.Name {
// Name must match
return false
}
if len(uid) > 0 && uid != string(sa.UID) {
// If UID is specified, it must match
return false
}
return true
}
// TODO: remove the duplicate code
// InternalIsServiceAccountToken returns true if the secret is a valid api token for the service account
func InternalIsServiceAccountToken(secret *api.Secret, sa *api.ServiceAccount) bool {
if secret.Type != api.SecretTypeServiceAccountToken { if secret.Type != api.SecretTypeServiceAccountToken {
return false return false
} }

View File

@ -28,6 +28,7 @@ import (
"k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/cache" "k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/conversion" "k8s.io/kubernetes/pkg/conversion"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
@ -631,7 +632,7 @@ func newCacherListerWatcher(storage Interface, resourcePrefix string, newListFun
} }
// Implements cache.ListerWatcher interface. // Implements cache.ListerWatcher interface.
func (lw *cacherListerWatcher) List(options api.ListOptions) (runtime.Object, error) { func (lw *cacherListerWatcher) List(options v1.ListOptions) (runtime.Object, error) {
list := lw.newListFunc() list := lw.newListFunc()
if err := lw.storage.List(context.TODO(), lw.resourcePrefix, "", Everything, list); err != nil { if err := lw.storage.List(context.TODO(), lw.resourcePrefix, "", Everything, list); err != nil {
return nil, err return nil, err
@ -640,7 +641,7 @@ func (lw *cacherListerWatcher) List(options api.ListOptions) (runtime.Object, er
} }
// Implements cache.ListerWatcher interface. // Implements cache.ListerWatcher interface.
func (lw *cacherListerWatcher) Watch(options api.ListOptions) (watch.Interface, error) { func (lw *cacherListerWatcher) Watch(options v1.ListOptions) (watch.Interface, error) {
return lw.storage.WatchList(context.TODO(), lw.resourcePrefix, options.ResourceVersion, Everything) return lw.storage.WatchList(context.TODO(), lw.resourcePrefix, options.ResourceVersion, Everything)
} }

View File

@ -24,13 +24,14 @@ package testing
import ( import (
"errors" "errors"
"fmt" "fmt"
"reflect"
"runtime"
time "time"
codec1978 "github.com/ugorji/go/codec" codec1978 "github.com/ugorji/go/codec"
pkg2_api "k8s.io/kubernetes/pkg/api" pkg2_api "k8s.io/kubernetes/pkg/api"
pkg1_unversioned "k8s.io/kubernetes/pkg/api/unversioned" pkg1_unversioned "k8s.io/kubernetes/pkg/api/unversioned"
pkg3_types "k8s.io/kubernetes/pkg/types" pkg3_types "k8s.io/kubernetes/pkg/types"
"reflect"
"runtime"
time "time"
) )
const ( const (

View File

@ -24,6 +24,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/cache" "k8s.io/kubernetes/pkg/client/cache"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/clock" "k8s.io/kubernetes/pkg/util/clock"
@ -312,14 +313,14 @@ func TestWaitUntilFreshAndListTimeout(t *testing.T) {
} }
type testLW struct { type testLW struct {
ListFunc func(options api.ListOptions) (runtime.Object, error) ListFunc func(options v1.ListOptions) (runtime.Object, error)
WatchFunc func(options api.ListOptions) (watch.Interface, error) WatchFunc func(options v1.ListOptions) (watch.Interface, error)
} }
func (t *testLW) List(options api.ListOptions) (runtime.Object, error) { func (t *testLW) List(options v1.ListOptions) (runtime.Object, error) {
return t.ListFunc(options) return t.ListFunc(options)
} }
func (t *testLW) Watch(options api.ListOptions) (watch.Interface, error) { func (t *testLW) Watch(options v1.ListOptions) (watch.Interface, error) {
return t.WatchFunc(options) return t.WatchFunc(options)
} }
@ -337,12 +338,12 @@ func TestReflectorForWatchCache(t *testing.T) {
} }
lw := &testLW{ lw := &testLW{
WatchFunc: func(options api.ListOptions) (watch.Interface, error) { WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
fw := watch.NewFake() fw := watch.NewFake()
go fw.Stop() go fw.Stop()
return fw, nil return fw, nil
}, },
ListFunc: func(options api.ListOptions) (runtime.Object, error) { ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
return &api.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "10"}}, nil return &api.PodList{ListMeta: unversioned.ListMeta{ResourceVersion: "10"}}, nil
}, },
} }