mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 10:19:50 +00:00
Merge pull request #8146 from yifan-gu/runtime_opt
kubelet/container: Refactor RunContainerOptions.
This commit is contained in:
commit
67eab52b9e
@ -185,14 +185,43 @@ type Image struct {
|
||||
Size int64
|
||||
}
|
||||
|
||||
type EnvVar struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
type Mount struct {
|
||||
// Name of the volume mount.
|
||||
Name string
|
||||
// Path of the mount within the container.
|
||||
ContainerPath string
|
||||
// Path of the mount on the host.
|
||||
HostPath string
|
||||
// Whether the mount is read-only.
|
||||
ReadOnly bool
|
||||
}
|
||||
|
||||
type PortMapping struct {
|
||||
// Name of the port mapping
|
||||
Name string
|
||||
// Protocol of the port mapping.
|
||||
Protocol api.Protocol
|
||||
// The port number within the container.
|
||||
ContainerPort int
|
||||
// The port number on the host.
|
||||
HostPort int
|
||||
// The host IP.
|
||||
HostIP string
|
||||
}
|
||||
|
||||
// RunContainerOptions specify the options which are necessary for running containers
|
||||
type RunContainerOptions struct {
|
||||
// The environment variables, they are in the form of 'key=value'.
|
||||
Envs []string
|
||||
// The mounts for the containers, they are in the form of:
|
||||
// 'hostPath:containerPath', or
|
||||
// 'hostPath:containerPath:ro', if the path read only.
|
||||
Binds []string
|
||||
// The environment variables list.
|
||||
Envs []EnvVar
|
||||
// The mounts for the containers.
|
||||
Mounts []Mount
|
||||
// The port mappings for the containers.
|
||||
PortMappings []PortMapping
|
||||
// If the container has specified the TerminationMessagePath, then
|
||||
// this directory will be used to create and mount the log file to
|
||||
// container.TerminationMessagePath
|
||||
|
@ -572,34 +572,32 @@ func TestFindContainersByPod(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMakePortsAndBindings(t *testing.T) {
|
||||
container := api.Container{
|
||||
Ports: []api.ContainerPort{
|
||||
{
|
||||
ContainerPort: 80,
|
||||
HostPort: 8080,
|
||||
HostIP: "127.0.0.1",
|
||||
},
|
||||
{
|
||||
ContainerPort: 443,
|
||||
HostPort: 443,
|
||||
Protocol: "tcp",
|
||||
},
|
||||
{
|
||||
ContainerPort: 444,
|
||||
HostPort: 444,
|
||||
Protocol: "udp",
|
||||
},
|
||||
{
|
||||
ContainerPort: 445,
|
||||
HostPort: 445,
|
||||
Protocol: "foobar",
|
||||
},
|
||||
ports := []kubecontainer.PortMapping{
|
||||
{
|
||||
ContainerPort: 80,
|
||||
HostPort: 8080,
|
||||
HostIP: "127.0.0.1",
|
||||
},
|
||||
{
|
||||
ContainerPort: 443,
|
||||
HostPort: 443,
|
||||
Protocol: "tcp",
|
||||
},
|
||||
{
|
||||
ContainerPort: 444,
|
||||
HostPort: 444,
|
||||
Protocol: "udp",
|
||||
},
|
||||
{
|
||||
ContainerPort: 445,
|
||||
HostPort: 445,
|
||||
Protocol: "foobar",
|
||||
},
|
||||
}
|
||||
exposedPorts, bindings := makePortsAndBindings(&container)
|
||||
if len(container.Ports) != len(exposedPorts) ||
|
||||
len(container.Ports) != len(bindings) {
|
||||
t.Errorf("Unexpected ports and bindings, %#v %#v %#v", container, exposedPorts, bindings)
|
||||
exposedPorts, bindings := makePortsAndBindings(ports)
|
||||
if len(ports) != len(exposedPorts) ||
|
||||
len(ports) != len(bindings) {
|
||||
t.Errorf("Unexpected ports and bindings, %#v %#v %#v", ports, exposedPorts, bindings)
|
||||
}
|
||||
for key, value := range bindings {
|
||||
switch value[0].HostPort {
|
||||
|
@ -477,6 +477,65 @@ func (dm *DockerManager) GetPodInfraContainer(pod kubecontainer.Pod) (kubecontai
|
||||
return kubecontainer.Container{}, fmt.Errorf("unable to find pod infra container for pod %v", pod.ID)
|
||||
}
|
||||
|
||||
// makeEnvList converts EnvVar list to a list of strings, in the form of
|
||||
// '<key>=<value>', which can be understood by docker.
|
||||
func makeEnvList(envs []kubecontainer.EnvVar) (result []string) {
|
||||
for _, env := range envs {
|
||||
result = append(result, fmt.Sprintf("%s=%s", env.Name, env.Value))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// makeMountBindings converts the mount list to a list of strings that
|
||||
// can be understood by docker.
|
||||
// Each element in the string is in the form of:
|
||||
// '<HostPath>:<ContainerPath>', or
|
||||
// '<HostPath>:<ContainerPath>:ro', if the path is read only.
|
||||
func makeMountBindings(mounts []kubecontainer.Mount) (result []string) {
|
||||
for _, m := range mounts {
|
||||
bind := fmt.Sprintf("%s:%s", m.HostPath, m.ContainerPath)
|
||||
if m.ReadOnly {
|
||||
bind += ":ro"
|
||||
}
|
||||
result = append(result, bind)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func makePortsAndBindings(portMappings []kubecontainer.PortMapping) (map[docker.Port]struct{}, map[docker.Port][]docker.PortBinding) {
|
||||
exposedPorts := map[docker.Port]struct{}{}
|
||||
portBindings := map[docker.Port][]docker.PortBinding{}
|
||||
for _, port := range portMappings {
|
||||
exteriorPort := port.HostPort
|
||||
if exteriorPort == 0 {
|
||||
// No need to do port binding when HostPort is not specified
|
||||
continue
|
||||
}
|
||||
interiorPort := port.ContainerPort
|
||||
// Some of this port stuff is under-documented voodoo.
|
||||
// See http://stackoverflow.com/questions/20428302/binding-a-port-to-a-host-interface-using-the-rest-api
|
||||
var protocol string
|
||||
switch strings.ToUpper(string(port.Protocol)) {
|
||||
case "UDP":
|
||||
protocol = "/udp"
|
||||
case "TCP":
|
||||
protocol = "/tcp"
|
||||
default:
|
||||
glog.Warningf("Unknown protocol %q: defaulting to TCP", port.Protocol)
|
||||
protocol = "/tcp"
|
||||
}
|
||||
dockerPort := docker.Port(strconv.Itoa(interiorPort) + protocol)
|
||||
exposedPorts[dockerPort] = struct{}{}
|
||||
portBindings[dockerPort] = []docker.PortBinding{
|
||||
{
|
||||
HostPort: strconv.Itoa(exteriorPort),
|
||||
HostIP: port.HostIP,
|
||||
},
|
||||
}
|
||||
}
|
||||
return exposedPorts, portBindings
|
||||
}
|
||||
|
||||
func (dm *DockerManager) runContainer(
|
||||
pod *api.Pod,
|
||||
container *api.Container,
|
||||
@ -490,7 +549,7 @@ func (dm *DockerManager) runContainer(
|
||||
PodUID: pod.UID,
|
||||
ContainerName: container.Name,
|
||||
}
|
||||
exposedPorts, portBindings := makePortsAndBindings(container)
|
||||
exposedPorts, portBindings := makePortsAndBindings(opts.PortMappings)
|
||||
|
||||
// TODO(vmarmol): Handle better.
|
||||
// Cap hostname at 63 chars (specification is 64bytes which is 63 chars and the null terminating char).
|
||||
@ -517,7 +576,7 @@ func (dm *DockerManager) runContainer(
|
||||
dockerOpts := docker.CreateContainerOptions{
|
||||
Name: BuildDockerName(dockerName, container),
|
||||
Config: &docker.Config{
|
||||
Env: opts.Envs,
|
||||
Env: makeEnvList(opts.Envs),
|
||||
ExposedPorts: exposedPorts,
|
||||
Hostname: containerHostname,
|
||||
Image: container.Image,
|
||||
@ -546,6 +605,8 @@ func (dm *DockerManager) runContainer(
|
||||
dm.recorder.Eventf(ref, "created", "Created with docker id %v", dockerContainer.ID)
|
||||
}
|
||||
|
||||
binds := makeMountBindings(opts.Mounts)
|
||||
|
||||
// The reason we create and mount the log file in here (not in kubelet) is because
|
||||
// the file's location depends on the ID of the container, and we need to create and
|
||||
// mount the file before actually starting the container.
|
||||
@ -560,13 +621,13 @@ func (dm *DockerManager) runContainer(
|
||||
} else {
|
||||
fs.Close() // Close immediately; we're just doing a `touch` here
|
||||
b := fmt.Sprintf("%s:%s", containerLogPath, container.TerminationMessagePath)
|
||||
opts.Binds = append(opts.Binds, b)
|
||||
binds = append(binds, b)
|
||||
}
|
||||
}
|
||||
|
||||
hc := &docker.HostConfig{
|
||||
PortBindings: portBindings,
|
||||
Binds: opts.Binds,
|
||||
Binds: binds,
|
||||
NetworkMode: netMode,
|
||||
IpcMode: ipcMode,
|
||||
}
|
||||
@ -603,40 +664,6 @@ func setEntrypointAndCommand(container *api.Container, opts *docker.CreateContai
|
||||
}
|
||||
}
|
||||
|
||||
func makePortsAndBindings(container *api.Container) (map[docker.Port]struct{}, map[docker.Port][]docker.PortBinding) {
|
||||
exposedPorts := map[docker.Port]struct{}{}
|
||||
portBindings := map[docker.Port][]docker.PortBinding{}
|
||||
for _, port := range container.Ports {
|
||||
exteriorPort := port.HostPort
|
||||
if exteriorPort == 0 {
|
||||
// No need to do port binding when HostPort is not specified
|
||||
continue
|
||||
}
|
||||
interiorPort := port.ContainerPort
|
||||
// Some of this port stuff is under-documented voodoo.
|
||||
// See http://stackoverflow.com/questions/20428302/binding-a-port-to-a-host-interface-using-the-rest-api
|
||||
var protocol string
|
||||
switch strings.ToUpper(string(port.Protocol)) {
|
||||
case "UDP":
|
||||
protocol = "/udp"
|
||||
case "TCP":
|
||||
protocol = "/tcp"
|
||||
default:
|
||||
glog.Warningf("Unknown protocol %q: defaulting to TCP", port.Protocol)
|
||||
protocol = "/tcp"
|
||||
}
|
||||
dockerPort := docker.Port(strconv.Itoa(interiorPort) + protocol)
|
||||
exposedPorts[dockerPort] = struct{}{}
|
||||
portBindings[dockerPort] = []docker.PortBinding{
|
||||
{
|
||||
HostPort: strconv.Itoa(exteriorPort),
|
||||
HostIP: port.HostIP,
|
||||
},
|
||||
}
|
||||
}
|
||||
return exposedPorts, portBindings
|
||||
}
|
||||
|
||||
// A helper function to get the KubeletContainerName and hash from a docker
|
||||
// container.
|
||||
func getDockerContainerNameInfo(c *docker.APIContainers) (*KubeletContainerName, uint64, error) {
|
||||
|
@ -696,18 +696,49 @@ func (kl *Kubelet) syncNodeStatus() {
|
||||
}
|
||||
}
|
||||
|
||||
func makeBinds(container *api.Container, podVolumes kubecontainer.VolumeMap) (binds []string) {
|
||||
func makeMounts(container *api.Container, podVolumes kubecontainer.VolumeMap) (mounts []kubecontainer.Mount) {
|
||||
for _, mount := range container.VolumeMounts {
|
||||
vol, ok := podVolumes[mount.Name]
|
||||
if !ok {
|
||||
glog.Warningf("Mount cannot be satisified for container %q, because the volume is missing: %q", container.Name, mount)
|
||||
continue
|
||||
}
|
||||
b := fmt.Sprintf("%s:%s", vol.GetPath(), mount.MountPath)
|
||||
if mount.ReadOnly {
|
||||
b += ":ro"
|
||||
mounts = append(mounts, kubecontainer.Mount{
|
||||
Name: mount.Name,
|
||||
ContainerPath: mount.MountPath,
|
||||
HostPath: vol.GetPath(),
|
||||
ReadOnly: mount.ReadOnly,
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func makePortMappings(container *api.Container) (ports []kubecontainer.PortMapping) {
|
||||
names := make(map[string]struct{})
|
||||
for _, p := range container.Ports {
|
||||
pm := kubecontainer.PortMapping{
|
||||
HostPort: p.HostPort,
|
||||
ContainerPort: p.ContainerPort,
|
||||
Protocol: p.Protocol,
|
||||
HostIP: p.HostIP,
|
||||
}
|
||||
binds = append(binds, b)
|
||||
|
||||
// We need to create some default port name if it's not specified, since
|
||||
// this is necessary for rkt.
|
||||
// https://github.com/GoogleCloudPlatform/kubernetes/issues/7710
|
||||
if p.Name == "" {
|
||||
pm.Name = fmt.Sprintf("%s-%s:%d", container.Name, p.Protocol, p.ContainerPort)
|
||||
} else {
|
||||
pm.Name = fmt.Sprintf("%s-%s", container.Name, p.Name)
|
||||
}
|
||||
|
||||
// Protect against exposing the same protocol-port more than once in a container.
|
||||
if _, ok := names[pm.Name]; ok {
|
||||
glog.Warningf("Port name conflicted, %q is defined more than once", pm.Name)
|
||||
continue
|
||||
}
|
||||
ports = append(ports, pm)
|
||||
names[pm.Name] = struct{}{}
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -722,7 +753,9 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *api.Pod, container *api.Cont
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("impossible: cannot find the mounted volumes for pod %q", kubecontainer.GetPodFullName(pod))
|
||||
}
|
||||
opts.Binds = makeBinds(container, vol)
|
||||
|
||||
opts.PortMappings = makePortMappings(container)
|
||||
opts.Mounts = makeMounts(container, vol)
|
||||
opts.Envs, err = kl.makeEnvironmentVariables(pod, container)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -801,8 +834,8 @@ func (kl *Kubelet) getServiceEnvVarMap(ns string) (map[string]string, error) {
|
||||
}
|
||||
|
||||
// Make the service environment variables for a pod in the given namespace.
|
||||
func (kl *Kubelet) makeEnvironmentVariables(pod *api.Pod, container *api.Container) ([]string, error) {
|
||||
var result []string
|
||||
func (kl *Kubelet) makeEnvironmentVariables(pod *api.Pod, container *api.Container) ([]kubecontainer.EnvVar, error) {
|
||||
var result []kubecontainer.EnvVar
|
||||
// Note: These are added to the docker.Config, but are not included in the checksum computed
|
||||
// by dockertools.BuildDockerName(...). That way, we can still determine whether an
|
||||
// api.Container is already running by its hash. (We don't want to restart a container just
|
||||
@ -830,12 +863,12 @@ func (kl *Kubelet) makeEnvironmentVariables(pod *api.Pod, container *api.Contain
|
||||
return result, err
|
||||
}
|
||||
|
||||
result = append(result, fmt.Sprintf("%s=%s", value.Name, runtimeValue))
|
||||
result = append(result, kubecontainer.EnvVar{Name: value.Name, Value: runtimeValue})
|
||||
}
|
||||
|
||||
// Append remaining service env vars.
|
||||
for k, v := range serviceEnv {
|
||||
result = append(result, fmt.Sprintf("%s=%s", k, v))
|
||||
result = append(result, kubecontainer.EnvVar{Name: k, Value: v})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
@ -1308,7 +1308,7 @@ func (f *stubVolume) GetPath() string {
|
||||
return f.path
|
||||
}
|
||||
|
||||
func TestMakeVolumesAndBinds(t *testing.T) {
|
||||
func TestMakeVolumeMounts(t *testing.T) {
|
||||
container := api.Container{
|
||||
VolumeMounts: []api.VolumeMount{
|
||||
{
|
||||
@ -1340,19 +1340,37 @@ func TestMakeVolumesAndBinds(t *testing.T) {
|
||||
"disk5": &stubVolume{"/var/lib/kubelet/podID/volumes/empty/disk5"},
|
||||
}
|
||||
|
||||
binds := makeBinds(&container, podVolumes)
|
||||
mounts := makeMounts(&container, podVolumes)
|
||||
|
||||
expectedBinds := []string{
|
||||
"/mnt/disk:/mnt/path",
|
||||
"/mnt/disk:/mnt/path3:ro",
|
||||
"/mnt/host:/mnt/path4",
|
||||
"/var/lib/kubelet/podID/volumes/empty/disk5:/mnt/path5",
|
||||
expectedMounts := []kubecontainer.Mount{
|
||||
{
|
||||
"disk",
|
||||
"/mnt/path",
|
||||
"/mnt/disk",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"disk",
|
||||
"/mnt/path3",
|
||||
"/mnt/disk",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"disk4",
|
||||
"/mnt/path4",
|
||||
"/mnt/host",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"disk5",
|
||||
"/mnt/path5",
|
||||
"/var/lib/kubelet/podID/volumes/empty/disk5",
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
if len(binds) != len(expectedBinds) {
|
||||
t.Errorf("Unexpected binds: Expected %#v got %#v. Container was: %#v", expectedBinds, binds, container)
|
||||
if !reflect.DeepEqual(mounts, expectedMounts) {
|
||||
t.Errorf("Unexpected mounts: Expected %#v got %#v. Container was: %#v", expectedMounts, mounts, container)
|
||||
}
|
||||
verifyStringArrayEquals(t, binds, expectedBinds)
|
||||
}
|
||||
|
||||
func TestGetContainerInfo(t *testing.T) {
|
||||
@ -1884,6 +1902,16 @@ func (ls testNodeLister) List() (api.NodeList, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
type envs []kubecontainer.EnvVar
|
||||
|
||||
func (e envs) Len() int {
|
||||
return len(e)
|
||||
}
|
||||
|
||||
func (e envs) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
|
||||
|
||||
func (e envs) Less(i, j int) bool { return e[i].Name < e[j].Name }
|
||||
|
||||
func TestMakeEnvironmentVariables(t *testing.T) {
|
||||
services := []api.Service{
|
||||
{
|
||||
@ -2028,12 +2056,12 @@ func TestMakeEnvironmentVariables(t *testing.T) {
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string // the name of the test case
|
||||
ns string // the namespace to generate environment for
|
||||
container *api.Container // the container to use
|
||||
masterServiceNs string // the namespace to read master service info from
|
||||
nilLister bool // whether the lister should be nil
|
||||
expectedEnvs util.StringSet // a set of expected environment vars
|
||||
name string // the name of the test case
|
||||
ns string // the namespace to generate environment for
|
||||
container *api.Container // the container to use
|
||||
masterServiceNs string // the namespace to read master service info from
|
||||
nilLister bool // whether the lister should be nil
|
||||
expectedEnvs []kubecontainer.EnvVar // a set of expected environment vars
|
||||
}{
|
||||
{
|
||||
name: "api server = Y, kubelet = Y",
|
||||
@ -2052,29 +2080,30 @@ func TestMakeEnvironmentVariables(t *testing.T) {
|
||||
},
|
||||
masterServiceNs: api.NamespaceDefault,
|
||||
nilLister: false,
|
||||
expectedEnvs: util.NewStringSet(
|
||||
"FOO=BAR",
|
||||
"TEST_SERVICE_HOST=1.2.3.3",
|
||||
"TEST_SERVICE_PORT=8083",
|
||||
"TEST_PORT=tcp://1.2.3.3:8083",
|
||||
"TEST_PORT_8083_TCP=tcp://1.2.3.3:8083",
|
||||
"TEST_PORT_8083_TCP_PROTO=tcp",
|
||||
"TEST_PORT_8083_TCP_PORT=8083",
|
||||
"TEST_PORT_8083_TCP_ADDR=1.2.3.3",
|
||||
"KUBERNETES_SERVICE_HOST=1.2.3.1",
|
||||
"KUBERNETES_SERVICE_PORT=8081",
|
||||
"KUBERNETES_PORT=tcp://1.2.3.1:8081",
|
||||
"KUBERNETES_PORT_8081_TCP=tcp://1.2.3.1:8081",
|
||||
"KUBERNETES_PORT_8081_TCP_PROTO=tcp",
|
||||
"KUBERNETES_PORT_8081_TCP_PORT=8081",
|
||||
"KUBERNETES_PORT_8081_TCP_ADDR=1.2.3.1",
|
||||
"KUBERNETES_RO_SERVICE_HOST=1.2.3.2",
|
||||
"KUBERNETES_RO_SERVICE_PORT=8082",
|
||||
"KUBERNETES_RO_PORT=tcp://1.2.3.2:8082",
|
||||
"KUBERNETES_RO_PORT_8082_TCP=tcp://1.2.3.2:8082",
|
||||
"KUBERNETES_RO_PORT_8082_TCP_PROTO=tcp",
|
||||
"KUBERNETES_RO_PORT_8082_TCP_PORT=8082",
|
||||
"KUBERNETES_RO_PORT_8082_TCP_ADDR=1.2.3.2"),
|
||||
expectedEnvs: []kubecontainer.EnvVar{
|
||||
{Name: "FOO", Value: "BAR"},
|
||||
{Name: "TEST_SERVICE_HOST", Value: "1.2.3.3"},
|
||||
{Name: "TEST_SERVICE_PORT", Value: "8083"},
|
||||
{Name: "TEST_PORT", Value: "tcp://1.2.3.3:8083"},
|
||||
{Name: "TEST_PORT_8083_TCP", Value: "tcp://1.2.3.3:8083"},
|
||||
{Name: "TEST_PORT_8083_TCP_PROTO", Value: "tcp"},
|
||||
{Name: "TEST_PORT_8083_TCP_PORT", Value: "8083"},
|
||||
{Name: "TEST_PORT_8083_TCP_ADDR", Value: "1.2.3.3"},
|
||||
{Name: "KUBERNETES_SERVICE_PORT", Value: "8081"},
|
||||
{Name: "KUBERNETES_SERVICE_HOST", Value: "1.2.3.1"},
|
||||
{Name: "KUBERNETES_PORT", Value: "tcp://1.2.3.1:8081"},
|
||||
{Name: "KUBERNETES_PORT_8081_TCP", Value: "tcp://1.2.3.1:8081"},
|
||||
{Name: "KUBERNETES_PORT_8081_TCP_PROTO", Value: "tcp"},
|
||||
{Name: "KUBERNETES_PORT_8081_TCP_PORT", Value: "8081"},
|
||||
{Name: "KUBERNETES_PORT_8081_TCP_ADDR", Value: "1.2.3.1"},
|
||||
{Name: "KUBERNETES_RO_SERVICE_HOST", Value: "1.2.3.2"},
|
||||
{Name: "KUBERNETES_RO_SERVICE_PORT", Value: "8082"},
|
||||
{Name: "KUBERNETES_RO_PORT", Value: "tcp://1.2.3.2:8082"},
|
||||
{Name: "KUBERNETES_RO_PORT_8082_TCP", Value: "tcp://1.2.3.2:8082"},
|
||||
{Name: "KUBERNETES_RO_PORT_8082_TCP_PROTO", Value: "tcp"},
|
||||
{Name: "KUBERNETES_RO_PORT_8082_TCP_PORT", Value: "8082"},
|
||||
{Name: "KUBERNETES_RO_PORT_8082_TCP_ADDR", Value: "1.2.3.2"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "api server = Y, kubelet = N",
|
||||
@ -2093,15 +2122,16 @@ func TestMakeEnvironmentVariables(t *testing.T) {
|
||||
},
|
||||
masterServiceNs: api.NamespaceDefault,
|
||||
nilLister: true,
|
||||
expectedEnvs: util.NewStringSet(
|
||||
"FOO=BAR",
|
||||
"TEST_SERVICE_HOST=1.2.3.3",
|
||||
"TEST_SERVICE_PORT=8083",
|
||||
"TEST_PORT=tcp://1.2.3.3:8083",
|
||||
"TEST_PORT_8083_TCP=tcp://1.2.3.3:8083",
|
||||
"TEST_PORT_8083_TCP_PROTO=tcp",
|
||||
"TEST_PORT_8083_TCP_PORT=8083",
|
||||
"TEST_PORT_8083_TCP_ADDR=1.2.3.3"),
|
||||
expectedEnvs: []kubecontainer.EnvVar{
|
||||
{Name: "FOO", Value: "BAR"},
|
||||
{Name: "TEST_SERVICE_HOST", Value: "1.2.3.3"},
|
||||
{Name: "TEST_SERVICE_PORT", Value: "8083"},
|
||||
{Name: "TEST_PORT", Value: "tcp://1.2.3.3:8083"},
|
||||
{Name: "TEST_PORT_8083_TCP", Value: "tcp://1.2.3.3:8083"},
|
||||
{Name: "TEST_PORT_8083_TCP_PROTO", Value: "tcp"},
|
||||
{Name: "TEST_PORT_8083_TCP_PORT", Value: "8083"},
|
||||
{Name: "TEST_PORT_8083_TCP_ADDR", Value: "1.2.3.3"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "api server = N; kubelet = Y",
|
||||
@ -2113,29 +2143,30 @@ func TestMakeEnvironmentVariables(t *testing.T) {
|
||||
},
|
||||
masterServiceNs: api.NamespaceDefault,
|
||||
nilLister: false,
|
||||
expectedEnvs: util.NewStringSet(
|
||||
"FOO=BAZ",
|
||||
"TEST_SERVICE_HOST=1.2.3.3",
|
||||
"TEST_SERVICE_PORT=8083",
|
||||
"TEST_PORT=tcp://1.2.3.3:8083",
|
||||
"TEST_PORT_8083_TCP=tcp://1.2.3.3:8083",
|
||||
"TEST_PORT_8083_TCP_PROTO=tcp",
|
||||
"TEST_PORT_8083_TCP_PORT=8083",
|
||||
"TEST_PORT_8083_TCP_ADDR=1.2.3.3",
|
||||
"KUBERNETES_SERVICE_HOST=1.2.3.1",
|
||||
"KUBERNETES_SERVICE_PORT=8081",
|
||||
"KUBERNETES_PORT=tcp://1.2.3.1:8081",
|
||||
"KUBERNETES_PORT_8081_TCP=tcp://1.2.3.1:8081",
|
||||
"KUBERNETES_PORT_8081_TCP_PROTO=tcp",
|
||||
"KUBERNETES_PORT_8081_TCP_PORT=8081",
|
||||
"KUBERNETES_PORT_8081_TCP_ADDR=1.2.3.1",
|
||||
"KUBERNETES_RO_SERVICE_HOST=1.2.3.2",
|
||||
"KUBERNETES_RO_SERVICE_PORT=8082",
|
||||
"KUBERNETES_RO_PORT=tcp://1.2.3.2:8082",
|
||||
"KUBERNETES_RO_PORT_8082_TCP=tcp://1.2.3.2:8082",
|
||||
"KUBERNETES_RO_PORT_8082_TCP_PROTO=tcp",
|
||||
"KUBERNETES_RO_PORT_8082_TCP_PORT=8082",
|
||||
"KUBERNETES_RO_PORT_8082_TCP_ADDR=1.2.3.2"),
|
||||
expectedEnvs: []kubecontainer.EnvVar{
|
||||
{Name: "FOO", Value: "BAZ"},
|
||||
{Name: "TEST_SERVICE_HOST", Value: "1.2.3.3"},
|
||||
{Name: "TEST_SERVICE_PORT", Value: "8083"},
|
||||
{Name: "TEST_PORT", Value: "tcp://1.2.3.3:8083"},
|
||||
{Name: "TEST_PORT_8083_TCP", Value: "tcp://1.2.3.3:8083"},
|
||||
{Name: "TEST_PORT_8083_TCP_PROTO", Value: "tcp"},
|
||||
{Name: "TEST_PORT_8083_TCP_PORT", Value: "8083"},
|
||||
{Name: "TEST_PORT_8083_TCP_ADDR", Value: "1.2.3.3"},
|
||||
{Name: "KUBERNETES_SERVICE_HOST", Value: "1.2.3.1"},
|
||||
{Name: "KUBERNETES_SERVICE_PORT", Value: "8081"},
|
||||
{Name: "KUBERNETES_PORT", Value: "tcp://1.2.3.1:8081"},
|
||||
{Name: "KUBERNETES_PORT_8081_TCP", Value: "tcp://1.2.3.1:8081"},
|
||||
{Name: "KUBERNETES_PORT_8081_TCP_PROTO", Value: "tcp"},
|
||||
{Name: "KUBERNETES_PORT_8081_TCP_PORT", Value: "8081"},
|
||||
{Name: "KUBERNETES_PORT_8081_TCP_ADDR", Value: "1.2.3.1"},
|
||||
{Name: "KUBERNETES_RO_SERVICE_HOST", Value: "1.2.3.2"},
|
||||
{Name: "KUBERNETES_RO_SERVICE_PORT", Value: "8082"},
|
||||
{Name: "KUBERNETES_RO_PORT", Value: "tcp://1.2.3.2:8082"},
|
||||
{Name: "KUBERNETES_RO_PORT_8082_TCP", Value: "tcp://1.2.3.2:8082"},
|
||||
{Name: "KUBERNETES_RO_PORT_8082_TCP_PROTO", Value: "tcp"},
|
||||
{Name: "KUBERNETES_RO_PORT_8082_TCP_PORT", Value: "8082"},
|
||||
{Name: "KUBERNETES_RO_PORT_8082_TCP_ADDR", Value: "1.2.3.2"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "master service in pod ns",
|
||||
@ -2147,29 +2178,30 @@ func TestMakeEnvironmentVariables(t *testing.T) {
|
||||
},
|
||||
masterServiceNs: "kubernetes",
|
||||
nilLister: false,
|
||||
expectedEnvs: util.NewStringSet(
|
||||
"FOO=ZAP",
|
||||
"TEST_SERVICE_HOST=1.2.3.5",
|
||||
"TEST_SERVICE_PORT=8085",
|
||||
"TEST_PORT=tcp://1.2.3.5:8085",
|
||||
"TEST_PORT_8085_TCP=tcp://1.2.3.5:8085",
|
||||
"TEST_PORT_8085_TCP_PROTO=tcp",
|
||||
"TEST_PORT_8085_TCP_PORT=8085",
|
||||
"TEST_PORT_8085_TCP_ADDR=1.2.3.5",
|
||||
"KUBERNETES_SERVICE_HOST=1.2.3.4",
|
||||
"KUBERNETES_SERVICE_PORT=8084",
|
||||
"KUBERNETES_PORT=tcp://1.2.3.4:8084",
|
||||
"KUBERNETES_PORT_8084_TCP=tcp://1.2.3.4:8084",
|
||||
"KUBERNETES_PORT_8084_TCP_PROTO=tcp",
|
||||
"KUBERNETES_PORT_8084_TCP_PORT=8084",
|
||||
"KUBERNETES_PORT_8084_TCP_ADDR=1.2.3.4",
|
||||
"KUBERNETES_RO_SERVICE_HOST=1.2.3.7",
|
||||
"KUBERNETES_RO_SERVICE_PORT=8087",
|
||||
"KUBERNETES_RO_PORT=tcp://1.2.3.7:8087",
|
||||
"KUBERNETES_RO_PORT_8087_TCP=tcp://1.2.3.7:8087",
|
||||
"KUBERNETES_RO_PORT_8087_TCP_PROTO=tcp",
|
||||
"KUBERNETES_RO_PORT_8087_TCP_PORT=8087",
|
||||
"KUBERNETES_RO_PORT_8087_TCP_ADDR=1.2.3.7"),
|
||||
expectedEnvs: []kubecontainer.EnvVar{
|
||||
{Name: "FOO", Value: "ZAP"},
|
||||
{Name: "TEST_SERVICE_HOST", Value: "1.2.3.5"},
|
||||
{Name: "TEST_SERVICE_PORT", Value: "8085"},
|
||||
{Name: "TEST_PORT", Value: "tcp://1.2.3.5:8085"},
|
||||
{Name: "TEST_PORT_8085_TCP", Value: "tcp://1.2.3.5:8085"},
|
||||
{Name: "TEST_PORT_8085_TCP_PROTO", Value: "tcp"},
|
||||
{Name: "TEST_PORT_8085_TCP_PORT", Value: "8085"},
|
||||
{Name: "TEST_PORT_8085_TCP_ADDR", Value: "1.2.3.5"},
|
||||
{Name: "KUBERNETES_SERVICE_HOST", Value: "1.2.3.4"},
|
||||
{Name: "KUBERNETES_SERVICE_PORT", Value: "8084"},
|
||||
{Name: "KUBERNETES_PORT", Value: "tcp://1.2.3.4:8084"},
|
||||
{Name: "KUBERNETES_PORT_8084_TCP", Value: "tcp://1.2.3.4:8084"},
|
||||
{Name: "KUBERNETES_PORT_8084_TCP_PROTO", Value: "tcp"},
|
||||
{Name: "KUBERNETES_PORT_8084_TCP_PORT", Value: "8084"},
|
||||
{Name: "KUBERNETES_PORT_8084_TCP_ADDR", Value: "1.2.3.4"},
|
||||
{Name: "KUBERNETES_RO_SERVICE_HOST", Value: "1.2.3.7"},
|
||||
{Name: "KUBERNETES_RO_SERVICE_PORT", Value: "8087"},
|
||||
{Name: "KUBERNETES_RO_PORT", Value: "tcp://1.2.3.7:8087"},
|
||||
{Name: "KUBERNETES_RO_PORT_8087_TCP", Value: "tcp://1.2.3.7:8087"},
|
||||
{Name: "KUBERNETES_RO_PORT_8087_TCP_PROTO", Value: "tcp"},
|
||||
{Name: "KUBERNETES_RO_PORT_8087_TCP_PORT", Value: "8087"},
|
||||
{Name: "KUBERNETES_RO_PORT_8087_TCP_ADDR", Value: "1.2.3.7"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "pod in master service ns",
|
||||
@ -2177,28 +2209,29 @@ func TestMakeEnvironmentVariables(t *testing.T) {
|
||||
container: &api.Container{},
|
||||
masterServiceNs: "kubernetes",
|
||||
nilLister: false,
|
||||
expectedEnvs: util.NewStringSet(
|
||||
"NOT_SPECIAL_SERVICE_HOST=1.2.3.8",
|
||||
"NOT_SPECIAL_SERVICE_PORT=8088",
|
||||
"NOT_SPECIAL_PORT=tcp://1.2.3.8:8088",
|
||||
"NOT_SPECIAL_PORT_8088_TCP=tcp://1.2.3.8:8088",
|
||||
"NOT_SPECIAL_PORT_8088_TCP_PROTO=tcp",
|
||||
"NOT_SPECIAL_PORT_8088_TCP_PORT=8088",
|
||||
"NOT_SPECIAL_PORT_8088_TCP_ADDR=1.2.3.8",
|
||||
"KUBERNETES_SERVICE_HOST=1.2.3.6",
|
||||
"KUBERNETES_SERVICE_PORT=8086",
|
||||
"KUBERNETES_PORT=tcp://1.2.3.6:8086",
|
||||
"KUBERNETES_PORT_8086_TCP=tcp://1.2.3.6:8086",
|
||||
"KUBERNETES_PORT_8086_TCP_PROTO=tcp",
|
||||
"KUBERNETES_PORT_8086_TCP_PORT=8086",
|
||||
"KUBERNETES_PORT_8086_TCP_ADDR=1.2.3.6",
|
||||
"KUBERNETES_RO_SERVICE_HOST=1.2.3.7",
|
||||
"KUBERNETES_RO_SERVICE_PORT=8087",
|
||||
"KUBERNETES_RO_PORT=tcp://1.2.3.7:8087",
|
||||
"KUBERNETES_RO_PORT_8087_TCP=tcp://1.2.3.7:8087",
|
||||
"KUBERNETES_RO_PORT_8087_TCP_PROTO=tcp",
|
||||
"KUBERNETES_RO_PORT_8087_TCP_PORT=8087",
|
||||
"KUBERNETES_RO_PORT_8087_TCP_ADDR=1.2.3.7"),
|
||||
expectedEnvs: []kubecontainer.EnvVar{
|
||||
{Name: "NOT_SPECIAL_SERVICE_HOST", Value: "1.2.3.8"},
|
||||
{Name: "NOT_SPECIAL_SERVICE_PORT", Value: "8088"},
|
||||
{Name: "NOT_SPECIAL_PORT", Value: "tcp://1.2.3.8:8088"},
|
||||
{Name: "NOT_SPECIAL_PORT_8088_TCP", Value: "tcp://1.2.3.8:8088"},
|
||||
{Name: "NOT_SPECIAL_PORT_8088_TCP_PROTO", Value: "tcp"},
|
||||
{Name: "NOT_SPECIAL_PORT_8088_TCP_PORT", Value: "8088"},
|
||||
{Name: "NOT_SPECIAL_PORT_8088_TCP_ADDR", Value: "1.2.3.8"},
|
||||
{Name: "KUBERNETES_SERVICE_HOST", Value: "1.2.3.6"},
|
||||
{Name: "KUBERNETES_SERVICE_PORT", Value: "8086"},
|
||||
{Name: "KUBERNETES_PORT", Value: "tcp://1.2.3.6:8086"},
|
||||
{Name: "KUBERNETES_PORT_8086_TCP", Value: "tcp://1.2.3.6:8086"},
|
||||
{Name: "KUBERNETES_PORT_8086_TCP_PROTO", Value: "tcp"},
|
||||
{Name: "KUBERNETES_PORT_8086_TCP_PORT", Value: "8086"},
|
||||
{Name: "KUBERNETES_PORT_8086_TCP_ADDR", Value: "1.2.3.6"},
|
||||
{Name: "KUBERNETES_RO_SERVICE_HOST", Value: "1.2.3.7"},
|
||||
{Name: "KUBERNETES_RO_SERVICE_PORT", Value: "8087"},
|
||||
{Name: "KUBERNETES_RO_PORT", Value: "tcp://1.2.3.7:8087"},
|
||||
{Name: "KUBERNETES_RO_PORT_8087_TCP", Value: "tcp://1.2.3.7:8087"},
|
||||
{Name: "KUBERNETES_RO_PORT_8087_TCP_PROTO", Value: "tcp"},
|
||||
{Name: "KUBERNETES_RO_PORT_8087_TCP_PORT", Value: "8087"},
|
||||
{Name: "KUBERNETES_RO_PORT_8087_TCP_ADDR", Value: "1.2.3.7"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "downward api pod",
|
||||
@ -2227,14 +2260,14 @@ func TestMakeEnvironmentVariables(t *testing.T) {
|
||||
},
|
||||
masterServiceNs: "nothing",
|
||||
nilLister: true,
|
||||
expectedEnvs: util.NewStringSet(
|
||||
"POD_NAME=dapi-test-pod-name",
|
||||
"POD_NAMESPACE=downward-api",
|
||||
),
|
||||
expectedEnvs: []kubecontainer.EnvVar{
|
||||
{Name: "POD_NAME", Value: "dapi-test-pod-name"},
|
||||
{Name: "POD_NAMESPACE", Value: "downward-api"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
for i, tc := range testCases {
|
||||
testKubelet := newTestKubelet(t)
|
||||
kl := testKubelet.kubelet
|
||||
kl.masterServiceNamespace = tc.masterServiceNs
|
||||
@ -2256,14 +2289,11 @@ func TestMakeEnvironmentVariables(t *testing.T) {
|
||||
t.Errorf("[%v] Unexpected error: %v", tc.name, err)
|
||||
}
|
||||
|
||||
resultSet := util.NewStringSet(result...)
|
||||
if !resultSet.HasAll(tc.expectedEnvs.List()...) {
|
||||
sort.Sort(envs(result))
|
||||
sort.Sort(envs(tc.expectedEnvs))
|
||||
|
||||
t.Errorf("[%v] Unexpected env entries; expected {%v}, got {%v}", tc.name, tc.expectedEnvs, resultSet)
|
||||
}
|
||||
|
||||
if a, e := len(resultSet), len(tc.expectedEnvs); e != a {
|
||||
t.Errorf("[%v] Unexpected number of env vars; expected %v, got %v", tc.name, e, a)
|
||||
if !reflect.DeepEqual(result, tc.expectedEnvs) {
|
||||
t.Errorf("%d: [%v] Unexpected env entries; expected {%v}, got {%v}", i, tc.name, tc.expectedEnvs, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4397,3 +4427,77 @@ func TestFilterOutTerminatedPods(t *testing.T) {
|
||||
t.Errorf("expected %#v, got %#v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakePortMappings(t *testing.T) {
|
||||
tests := []struct {
|
||||
container *api.Container
|
||||
expectedPortMappings []kubecontainer.PortMapping
|
||||
}{
|
||||
{
|
||||
&api.Container{
|
||||
Name: "fooContainer",
|
||||
Ports: []api.ContainerPort{
|
||||
{
|
||||
Protocol: api.ProtocolTCP,
|
||||
ContainerPort: 80,
|
||||
HostPort: 8080,
|
||||
HostIP: "127.0.0.1",
|
||||
},
|
||||
{
|
||||
Protocol: api.ProtocolTCP,
|
||||
ContainerPort: 443,
|
||||
HostPort: 4343,
|
||||
HostIP: "192.168.0.1",
|
||||
},
|
||||
{
|
||||
Name: "foo",
|
||||
Protocol: api.ProtocolUDP,
|
||||
ContainerPort: 555,
|
||||
HostPort: 5555,
|
||||
},
|
||||
{
|
||||
Name: "foo", // Duplicated, should be ignored.
|
||||
Protocol: api.ProtocolUDP,
|
||||
ContainerPort: 888,
|
||||
HostPort: 8888,
|
||||
},
|
||||
{
|
||||
Protocol: api.ProtocolTCP, // Duplicated, should be ignored.
|
||||
ContainerPort: 80,
|
||||
HostPort: 8888,
|
||||
},
|
||||
},
|
||||
},
|
||||
[]kubecontainer.PortMapping{
|
||||
{
|
||||
Name: "fooContainer-TCP:80",
|
||||
Protocol: api.ProtocolTCP,
|
||||
ContainerPort: 80,
|
||||
HostPort: 8080,
|
||||
HostIP: "127.0.0.1",
|
||||
},
|
||||
{
|
||||
Name: "fooContainer-TCP:443",
|
||||
Protocol: api.ProtocolTCP,
|
||||
ContainerPort: 443,
|
||||
HostPort: 4343,
|
||||
HostIP: "192.168.0.1",
|
||||
},
|
||||
{
|
||||
Name: "fooContainer-foo",
|
||||
Protocol: api.ProtocolUDP,
|
||||
ContainerPort: 555,
|
||||
HostPort: 5555,
|
||||
HostIP: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
actual := makePortMappings(tt.container)
|
||||
if !reflect.DeepEqual(tt.expectedPortMappings, actual) {
|
||||
t.Errorf("%d: Expected: %#v, saw: %#v", i, tt.expectedPortMappings, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user