mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-18 16:21:13 +00:00
Passing pod UUID to Kubelet.
This commit is contained in:
parent
2221d33de1
commit
7ace5a3e83
@ -55,6 +55,10 @@ type ContainerManifest struct {
|
|||||||
// Required: This must be a DNS_SUBDOMAIN.
|
// Required: This must be a DNS_SUBDOMAIN.
|
||||||
// TODO: ID on Manifest is deprecated and will be removed in the future.
|
// TODO: ID on Manifest is deprecated and will be removed in the future.
|
||||||
ID string `yaml:"id" json:"id"`
|
ID string `yaml:"id" json:"id"`
|
||||||
|
// TODO: UUID on Manifest is deprecated in the future once we are done
|
||||||
|
// with the API refactoring. It is required for now to determine the instance
|
||||||
|
// of a Pod.
|
||||||
|
UUID string `yaml:"uuid,omitempty" json:"uuid,omitempty"`
|
||||||
Volumes []Volume `yaml:"volumes" json:"volumes"`
|
Volumes []Volume `yaml:"volumes" json:"volumes"`
|
||||||
Containers []Container `yaml:"containers" json:"containers"`
|
Containers []Container `yaml:"containers" json:"containers"`
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,10 @@ type ContainerManifest struct {
|
|||||||
// Required: This must be a DNS_SUBDOMAIN.
|
// Required: This must be a DNS_SUBDOMAIN.
|
||||||
// TODO: ID on Manifest is deprecated and will be removed in the future.
|
// TODO: ID on Manifest is deprecated and will be removed in the future.
|
||||||
ID string `yaml:"id" json:"id"`
|
ID string `yaml:"id" json:"id"`
|
||||||
|
// TODO: UUID on Manifext is deprecated in the future once we are done
|
||||||
|
// with the API refactory. It is required for now to determine the instance
|
||||||
|
// of a Pod.
|
||||||
|
UUID string `yaml:"uuid,omitempty" json:"uuid,omitempty"`
|
||||||
Volumes []Volume `yaml:"volumes" json:"volumes"`
|
Volumes []Volume `yaml:"volumes" json:"volumes"`
|
||||||
Containers []Container `yaml:"containers" json:"containers"`
|
Containers []Container `yaml:"containers" json:"containers"`
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import (
|
|||||||
const defaultHealthyRegex = "^OK$"
|
const defaultHealthyRegex = "^OK$"
|
||||||
|
|
||||||
type CommandRunner interface {
|
type CommandRunner interface {
|
||||||
RunInContainer(podFullName, containerName string, cmd []string) ([]byte, error)
|
RunInContainer(podFullName, uuid, containerName string, cmd []string) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExecHealthChecker struct {
|
type ExecHealthChecker struct {
|
||||||
@ -47,7 +47,7 @@ func (e *ExecHealthChecker) HealthCheck(podFullName string, currentState api.Pod
|
|||||||
if container.LivenessProbe.Exec == nil {
|
if container.LivenessProbe.Exec == nil {
|
||||||
return Unknown, fmt.Errorf("Missing exec parameters")
|
return Unknown, fmt.Errorf("Missing exec parameters")
|
||||||
}
|
}
|
||||||
data, err := e.runner.RunInContainer(podFullName, container.Name, container.LivenessProbe.Exec.Command)
|
data, err := e.runner.RunInContainer(podFullName, currentState.Manifest.UUID, container.Name, container.LivenessProbe.Exec.Command)
|
||||||
glog.V(1).Infof("container %s failed health check: %s", podFullName, string(data))
|
glog.V(1).Infof("container %s failed health check: %s", podFullName, string(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if IsExitError(err) {
|
if IsExitError(err) {
|
||||||
|
@ -31,7 +31,7 @@ type FakeExec struct {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeExec) RunInContainer(podFullName, container string, cmd []string) ([]byte, error) {
|
func (f *FakeExec) RunInContainer(podFullName, uuid, container string, cmd []string) ([]byte, error) {
|
||||||
f.cmd = cmd
|
f.cmd = cmd
|
||||||
return f.out, f.err
|
return f.out, f.err
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,9 @@ func eventToPods(ev watch.Event) ([]kubelet.Pod, error) {
|
|||||||
if name == "" {
|
if name == "" {
|
||||||
name = fmt.Sprintf("%d", i+1)
|
name = fmt.Sprintf("%d", i+1)
|
||||||
}
|
}
|
||||||
pods = append(pods, kubelet.Pod{Name: name, Manifest: manifest})
|
pods = append(pods, kubelet.Pod{
|
||||||
|
Name: name,
|
||||||
|
Manifest: manifest})
|
||||||
}
|
}
|
||||||
|
|
||||||
return pods, nil
|
return pods, nil
|
||||||
|
@ -109,21 +109,24 @@ func (p dockerPuller) Pull(image string) error {
|
|||||||
// DockerContainers is a map of containers
|
// DockerContainers is a map of containers
|
||||||
type DockerContainers map[DockerID]*docker.APIContainers
|
type DockerContainers map[DockerID]*docker.APIContainers
|
||||||
|
|
||||||
func (c DockerContainers) FindPodContainer(podFullName, containerName string) (*docker.APIContainers, bool, uint64) {
|
func (c DockerContainers) FindPodContainer(podFullName, uuid, containerName string) (*docker.APIContainers, bool, uint64) {
|
||||||
for _, dockerContainer := range c {
|
for _, dockerContainer := range c {
|
||||||
dockerManifestID, dockerContainerName, hash := parseDockerName(dockerContainer.Names[0])
|
dockerManifestID, dockerUUID, dockerContainerName, hash := parseDockerName(dockerContainer.Names[0])
|
||||||
if dockerManifestID == podFullName && dockerContainerName == containerName {
|
if dockerManifestID == podFullName &&
|
||||||
|
(uuid == "" || dockerUUID == uuid) &&
|
||||||
|
dockerContainerName == containerName {
|
||||||
return dockerContainer, true, hash
|
return dockerContainer, true, hash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, false, 0
|
return nil, false, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note, this might return containers belong to a different Pod instance with the same name
|
||||||
func (c DockerContainers) FindContainersByPodFullName(podFullName string) map[string]*docker.APIContainers {
|
func (c DockerContainers) FindContainersByPodFullName(podFullName string) map[string]*docker.APIContainers {
|
||||||
containers := make(map[string]*docker.APIContainers)
|
containers := make(map[string]*docker.APIContainers)
|
||||||
|
|
||||||
for _, dockerContainer := range c {
|
for _, dockerContainer := range c {
|
||||||
dockerManifestID, dockerContainerName, _ := parseDockerName(dockerContainer.Names[0])
|
dockerManifestID, _, dockerContainerName, _ := parseDockerName(dockerContainer.Names[0])
|
||||||
if dockerManifestID == podFullName {
|
if dockerManifestID == podFullName {
|
||||||
containers[dockerContainerName] = dockerContainer
|
containers[dockerContainerName] = dockerContainer
|
||||||
}
|
}
|
||||||
@ -154,7 +157,7 @@ func getKubeletDockerContainers(client DockerInterface) (DockerContainers, error
|
|||||||
var ErrNoContainersInPod = errors.New("no containers exist for this pod")
|
var ErrNoContainersInPod = errors.New("no containers exist for this pod")
|
||||||
|
|
||||||
// GetDockerPodInfo returns docker info for all containers in the pod/manifest.
|
// GetDockerPodInfo returns docker info for all containers in the pod/manifest.
|
||||||
func getDockerPodInfo(client DockerInterface, podFullName string) (api.PodInfo, error) {
|
func getDockerPodInfo(client DockerInterface, podFullName, uuid string) (api.PodInfo, error) {
|
||||||
info := api.PodInfo{}
|
info := api.PodInfo{}
|
||||||
|
|
||||||
containers, err := client.ListContainers(docker.ListContainersOptions{})
|
containers, err := client.ListContainers(docker.ListContainersOptions{})
|
||||||
@ -163,10 +166,13 @@ func getDockerPodInfo(client DockerInterface, podFullName string) (api.PodInfo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, value := range containers {
|
for _, value := range containers {
|
||||||
dockerManifestID, dockerContainerName, _ := parseDockerName(value.Names[0])
|
dockerManifestID, dockerUUID, dockerContainerName, _ := parseDockerName(value.Names[0])
|
||||||
if dockerManifestID != podFullName {
|
if dockerManifestID != podFullName {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if uuid != "" && dockerUUID != uuid {
|
||||||
|
continue
|
||||||
|
}
|
||||||
inspectResult, err := client.InspectContainer(value.ID)
|
inspectResult, err := client.InspectContainer(value.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -211,12 +217,25 @@ func hashContainer(container *api.Container) uint64 {
|
|||||||
func buildDockerName(pod *Pod, container *api.Container) string {
|
func buildDockerName(pod *Pod, container *api.Container) string {
|
||||||
containerName := escapeDash(container.Name) + "." + strconv.FormatUint(hashContainer(container), 16)
|
containerName := escapeDash(container.Name) + "." + strconv.FormatUint(hashContainer(container), 16)
|
||||||
// Note, manifest.ID could be blank.
|
// Note, manifest.ID could be blank.
|
||||||
return fmt.Sprintf("%s--%s--%s--%08x", containerNamePrefix, containerName, escapeDash(GetPodFullName(pod)), rand.Uint32())
|
if len(pod.Manifest.UUID) == 0 {
|
||||||
|
return fmt.Sprintf("%s--%s--%s--%08x",
|
||||||
|
containerNamePrefix,
|
||||||
|
containerName,
|
||||||
|
escapeDash(GetPodFullName(pod)),
|
||||||
|
rand.Uint32())
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%s--%s--%s--%s--%08x",
|
||||||
|
containerNamePrefix,
|
||||||
|
containerName,
|
||||||
|
escapeDash(GetPodFullName(pod)),
|
||||||
|
escapeDash(pod.Manifest.UUID),
|
||||||
|
rand.Uint32())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upacks a container name, returning the pod full name and container name we would have used to
|
// Upacks a container name, returning the pod full name and container name we would have used to
|
||||||
// construct the docker name. If the docker name isn't one we created, we may return empty strings.
|
// construct the docker name. If the docker name isn't one we created, we may return empty strings.
|
||||||
func parseDockerName(name string) (podFullName, containerName string, hash uint64) {
|
func parseDockerName(name string) (podFullName, uuid, containerName string, hash uint64) {
|
||||||
// For some reason docker appears to be appending '/' to names.
|
// For some reason docker appears to be appending '/' to names.
|
||||||
// If it's there, strip it.
|
// If it's there, strip it.
|
||||||
if name[0] == '/' {
|
if name[0] == '/' {
|
||||||
@ -240,11 +259,14 @@ func parseDockerName(name string) (podFullName, containerName string, hash uint6
|
|||||||
if len(parts) > 2 {
|
if len(parts) > 2 {
|
||||||
podFullName = unescapeDash(parts[2])
|
podFullName = unescapeDash(parts[2])
|
||||||
}
|
}
|
||||||
|
if len(parts) > 4 {
|
||||||
|
uuid = unescapeDash(parts[3])
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses image name including a tag and returns image name and tag.
|
// Parses image name including a tag and returns image name and tag.
|
||||||
// TODO: Future Docker versions can parse the tag on daemon side, see:
|
// TODO: Future Docker versions can parse the tag on daemon side, see
|
||||||
// https://github.com/dotcloud/docker/issues/6876
|
// https://github.com/dotcloud/docker/issues/6876
|
||||||
// So this can be deprecated at some point.
|
// So this can be deprecated at some point.
|
||||||
func parseImageName(image string) (string, string) {
|
func parseImageName(image string) (string, string) {
|
||||||
|
@ -30,8 +30,8 @@ type execActionHandler struct {
|
|||||||
kubelet *Kubelet
|
kubelet *Kubelet
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *execActionHandler) Run(podFullName string, container *api.Container, handler *api.Handler) error {
|
func (e *execActionHandler) Run(podFullName, uuid string, container *api.Container, handler *api.Handler) error {
|
||||||
_, err := e.kubelet.RunInContainer(podFullName, container.Name, handler.Exec.Command)
|
_, err := e.kubelet.RunInContainer(podFullName, uuid, container.Name, handler.Exec.Command)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,11 +65,11 @@ func ResolvePort(portReference util.IntOrString, container *api.Container) (int,
|
|||||||
return -1, fmt.Errorf("couldn't find port: %v in %v", portReference, container)
|
return -1, fmt.Errorf("couldn't find port: %v in %v", portReference, container)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *httpActionHandler) Run(podFullName string, container *api.Container, handler *api.Handler) error {
|
func (h *httpActionHandler) Run(podFullName, uuid string, container *api.Container, handler *api.Handler) error {
|
||||||
host := handler.HTTPGet.Host
|
host := handler.HTTPGet.Host
|
||||||
if len(host) == 0 {
|
if len(host) == 0 {
|
||||||
var info api.PodInfo
|
var info api.PodInfo
|
||||||
info, err := h.kubelet.GetPodInfo(podFullName)
|
info, err := h.kubelet.GetPodInfo(podFullName, uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("unable to get pod info, event handlers may be invalid.")
|
glog.Errorf("unable to get pod info, event handlers may be invalid.")
|
||||||
return err
|
return err
|
||||||
|
@ -292,7 +292,7 @@ func (kl *Kubelet) mountExternalVolumes(manifest *api.ContainerManifest) (volume
|
|||||||
|
|
||||||
// A basic interface that knows how to execute handlers
|
// A basic interface that knows how to execute handlers
|
||||||
type actionHandler interface {
|
type actionHandler interface {
|
||||||
Run(podFullName string, container *api.Container, handler *api.Handler) error
|
Run(podFullName, uuid string, container *api.Container, handler *api.Handler) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kl *Kubelet) newActionHandler(handler *api.Handler) actionHandler {
|
func (kl *Kubelet) newActionHandler(handler *api.Handler) actionHandler {
|
||||||
@ -307,12 +307,12 @@ func (kl *Kubelet) newActionHandler(handler *api.Handler) actionHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kl *Kubelet) runHandler(podFullName string, container *api.Container, handler *api.Handler) error {
|
func (kl *Kubelet) runHandler(podFullName, uuid string, container *api.Container, handler *api.Handler) error {
|
||||||
actionHandler := kl.newActionHandler(handler)
|
actionHandler := kl.newActionHandler(handler)
|
||||||
if actionHandler == nil {
|
if actionHandler == nil {
|
||||||
return fmt.Errorf("invalid handler")
|
return fmt.Errorf("invalid handler")
|
||||||
}
|
}
|
||||||
return actionHandler.Run(podFullName, container, handler)
|
return actionHandler.Run(podFullName, uuid, container, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run a single container from a pod. Returns the docker container ID
|
// Run a single container from a pod. Returns the docker container ID
|
||||||
@ -344,7 +344,7 @@ func (kl *Kubelet) runContainer(pod *Pod, container *api.Container, podVolumes v
|
|||||||
NetworkMode: netMode,
|
NetworkMode: netMode,
|
||||||
})
|
})
|
||||||
if err == nil && container.Lifecycle != nil && container.Lifecycle.PostStart != nil {
|
if err == nil && container.Lifecycle != nil && container.Lifecycle.PostStart != nil {
|
||||||
handlerErr := kl.runHandler(GetPodFullName(pod), container, container.Lifecycle.PostStart)
|
handlerErr := kl.runHandler(GetPodFullName(pod), pod.Manifest.UUID, container, container.Lifecycle.PostStart)
|
||||||
if handlerErr != nil {
|
if handlerErr != nil {
|
||||||
kl.killContainerByID(dockerContainer.ID, "")
|
kl.killContainerByID(dockerContainer.ID, "")
|
||||||
return DockerID(""), fmt.Errorf("failed to call event handler: %v", handlerErr)
|
return DockerID(""), fmt.Errorf("failed to call event handler: %v", handlerErr)
|
||||||
@ -364,12 +364,13 @@ func (kl *Kubelet) killContainerByID(ID, name string) error {
|
|||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
podFullName, containerName, _ := parseDockerName(name)
|
podFullName, uuid, containerName, _ := parseDockerName(name)
|
||||||
kl.LogEvent(&api.Event{
|
kl.LogEvent(&api.Event{
|
||||||
Event: "STOP",
|
Event: "STOP",
|
||||||
Manifest: &api.ContainerManifest{
|
Manifest: &api.ContainerManifest{
|
||||||
//TODO: This should be reported using either the apiserver schema or the kubelet schema
|
//TODO: This should be reported using either the apiserver schema or the kubelet schema
|
||||||
ID: podFullName,
|
ID: podFullName,
|
||||||
|
UUID: uuid,
|
||||||
},
|
},
|
||||||
Container: &api.Container{
|
Container: &api.Container{
|
||||||
Name: containerName,
|
Name: containerName,
|
||||||
@ -408,7 +409,7 @@ func (kl *Kubelet) deleteAllContainers(pod *Pod, podFullName string, dockerConta
|
|||||||
errs := make(chan error, len(pod.Manifest.Containers))
|
errs := make(chan error, len(pod.Manifest.Containers))
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
for _, container := range pod.Manifest.Containers {
|
for _, container := range pod.Manifest.Containers {
|
||||||
if dockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, container.Name); found {
|
if dockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, pod.Manifest.UUID, container.Name); found {
|
||||||
count++
|
count++
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
@ -437,12 +438,13 @@ type empty struct{}
|
|||||||
|
|
||||||
func (kl *Kubelet) syncPod(pod *Pod, dockerContainers DockerContainers) error {
|
func (kl *Kubelet) syncPod(pod *Pod, dockerContainers DockerContainers) error {
|
||||||
podFullName := GetPodFullName(pod)
|
podFullName := GetPodFullName(pod)
|
||||||
|
uuid := pod.Manifest.UUID
|
||||||
containersToKeep := make(map[DockerID]empty)
|
containersToKeep := make(map[DockerID]empty)
|
||||||
killedContainers := make(map[DockerID]empty)
|
killedContainers := make(map[DockerID]empty)
|
||||||
|
|
||||||
// Make sure we have a network container
|
// Make sure we have a network container
|
||||||
var netID DockerID
|
var netID DockerID
|
||||||
if networkDockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, networkContainerName); found {
|
if networkDockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uuid, networkContainerName); found {
|
||||||
netID = DockerID(networkDockerContainer.ID)
|
netID = DockerID(networkDockerContainer.ID)
|
||||||
} else {
|
} else {
|
||||||
glog.Infof("Network container doesn't exist, creating")
|
glog.Infof("Network container doesn't exist, creating")
|
||||||
@ -473,10 +475,11 @@ func (kl *Kubelet) syncPod(pod *Pod, dockerContainers DockerContainers) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
podState := api.PodState{}
|
podState := api.PodState{Manifest: api.ContainerManifest{UUID: uuid}}
|
||||||
info, err := kl.GetPodInfo(podFullName)
|
info, err := kl.GetPodInfo(podFullName, uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Unable to get pod info, health checks may be invalid.")
|
glog.Errorf("Unable to get pod with name %s and uuid %s info, health checks may be invalid.",
|
||||||
|
podFullName, uuid)
|
||||||
}
|
}
|
||||||
netInfo, found := info[networkContainerName]
|
netInfo, found := info[networkContainerName]
|
||||||
if found && netInfo.NetworkSettings != nil {
|
if found && netInfo.NetworkSettings != nil {
|
||||||
@ -485,9 +488,8 @@ func (kl *Kubelet) syncPod(pod *Pod, dockerContainers DockerContainers) error {
|
|||||||
|
|
||||||
for _, container := range pod.Manifest.Containers {
|
for _, container := range pod.Manifest.Containers {
|
||||||
expectedHash := hashContainer(&container)
|
expectedHash := hashContainer(&container)
|
||||||
if dockerContainer, found, hash := dockerContainers.FindPodContainer(podFullName, container.Name); found {
|
if dockerContainer, found, hash := dockerContainers.FindPodContainer(podFullName, uuid, container.Name); found {
|
||||||
containerID := DockerID(dockerContainer.ID)
|
containerID := DockerID(dockerContainer.ID)
|
||||||
glog.Infof("pod %s container %s exists as %v", podFullName, container.Name, containerID)
|
|
||||||
glog.V(1).Infof("pod %s container %s exists as %v", podFullName, container.Name, containerID)
|
glog.V(1).Infof("pod %s container %s exists as %v", podFullName, container.Name, containerID)
|
||||||
|
|
||||||
// look for changes in the container.
|
// look for changes in the container.
|
||||||
@ -530,8 +532,8 @@ func (kl *Kubelet) syncPod(pod *Pod, dockerContainers DockerContainers) error {
|
|||||||
|
|
||||||
// Kill any containers in this pod which were not identified above (guards against duplicates).
|
// Kill any containers in this pod which were not identified above (guards against duplicates).
|
||||||
for id, container := range dockerContainers {
|
for id, container := range dockerContainers {
|
||||||
curPodFullName, _, _ := parseDockerName(container.Names[0])
|
curPodFullName, curUUID, _, _ := parseDockerName(container.Names[0])
|
||||||
if curPodFullName == podFullName {
|
if curPodFullName == podFullName && curUUID == uuid {
|
||||||
// Don't kill containers we want to keep or those we already killed.
|
// Don't kill containers we want to keep or those we already killed.
|
||||||
_, keep := containersToKeep[id]
|
_, keep := containersToKeep[id]
|
||||||
_, killed := killedContainers[id]
|
_, killed := killedContainers[id]
|
||||||
@ -549,6 +551,7 @@ func (kl *Kubelet) syncPod(pod *Pod, dockerContainers DockerContainers) error {
|
|||||||
|
|
||||||
type podContainer struct {
|
type podContainer struct {
|
||||||
podFullName string
|
podFullName string
|
||||||
|
uuid string
|
||||||
containerName string
|
containerName string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,11 +604,12 @@ func (kl *Kubelet) SyncPods(pods []Pod) error {
|
|||||||
for i := range pods {
|
for i := range pods {
|
||||||
pod := &pods[i]
|
pod := &pods[i]
|
||||||
podFullName := GetPodFullName(pod)
|
podFullName := GetPodFullName(pod)
|
||||||
|
uuid := pod.Manifest.UUID
|
||||||
|
|
||||||
// Add all containers (including net) to the map.
|
// Add all containers (including net) to the map.
|
||||||
desiredContainers[podContainer{podFullName, networkContainerName}] = empty{}
|
desiredContainers[podContainer{podFullName, uuid, networkContainerName}] = empty{}
|
||||||
for _, cont := range pod.Manifest.Containers {
|
for _, cont := range pod.Manifest.Containers {
|
||||||
desiredContainers[podContainer{podFullName, cont.Name}] = empty{}
|
desiredContainers[podContainer{podFullName, uuid, cont.Name}] = empty{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the sync in an async manifest worker.
|
// Run the sync in an async manifest worker.
|
||||||
@ -625,8 +629,8 @@ func (kl *Kubelet) SyncPods(pods []Pod) error {
|
|||||||
}
|
}
|
||||||
for _, container := range existingContainers {
|
for _, container := range existingContainers {
|
||||||
// Don't kill containers that are in the desired pods.
|
// Don't kill containers that are in the desired pods.
|
||||||
podFullName, containerName, _ := parseDockerName(container.Names[0])
|
podFullName, uuid, containerName, _ := parseDockerName(container.Names[0])
|
||||||
if _, ok := desiredContainers[podContainer{podFullName, containerName}]; !ok {
|
if _, ok := desiredContainers[podContainer{podFullName, uuid, containerName}]; !ok {
|
||||||
err = kl.killContainer(container)
|
err = kl.killContainer(container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Error killing container: %v", err)
|
glog.Errorf("Error killing container: %v", err)
|
||||||
@ -716,12 +720,12 @@ func (kl *Kubelet) statsFromContainerPath(containerPath string, req *info.Contai
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetPodInfo returns information from Docker about the containers in a pod
|
// GetPodInfo returns information from Docker about the containers in a pod
|
||||||
func (kl *Kubelet) GetPodInfo(podFullName string) (api.PodInfo, error) {
|
func (kl *Kubelet) GetPodInfo(podFullName, uuid string) (api.PodInfo, error) {
|
||||||
return getDockerPodInfo(kl.dockerClient, podFullName)
|
return getDockerPodInfo(kl.dockerClient, podFullName, uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContainerInfo returns stats (from Cadvisor) for a container.
|
// GetContainerInfo returns stats (from Cadvisor) for a container.
|
||||||
func (kl *Kubelet) GetContainerInfo(podFullName, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
|
func (kl *Kubelet) GetContainerInfo(podFullName, uuid, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
|
||||||
if kl.cadvisorClient == nil {
|
if kl.cadvisorClient == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -729,7 +733,7 @@ func (kl *Kubelet) GetContainerInfo(podFullName, containerName string, req *info
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, containerName)
|
dockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uuid, containerName)
|
||||||
if !found {
|
if !found {
|
||||||
return nil, errors.New("couldn't find container")
|
return nil, errors.New("couldn't find container")
|
||||||
}
|
}
|
||||||
@ -766,7 +770,7 @@ func (kl *Kubelet) ServeLogs(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run a command in a container, returns the combined stdout, stderr as an array of bytes
|
// Run a command in a container, returns the combined stdout, stderr as an array of bytes
|
||||||
func (kl *Kubelet) RunInContainer(podFullName, container string, cmd []string) ([]byte, error) {
|
func (kl *Kubelet) RunInContainer(podFullName, uuid, container string, cmd []string) ([]byte, error) {
|
||||||
if kl.runner == nil {
|
if kl.runner == nil {
|
||||||
return nil, fmt.Errorf("no runner specified.")
|
return nil, fmt.Errorf("no runner specified.")
|
||||||
}
|
}
|
||||||
@ -774,7 +778,7 @@ func (kl *Kubelet) RunInContainer(podFullName, container string, cmd []string) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, container)
|
dockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uuid, container)
|
||||||
if !found {
|
if !found {
|
||||||
return nil, fmt.Errorf("container not found (%s)", container)
|
return nil, fmt.Errorf("container not found (%s)", container)
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ func verifyPackUnpack(t *testing.T, podNamespace, podName, containerName string)
|
|||||||
container,
|
container,
|
||||||
)
|
)
|
||||||
podFullName := fmt.Sprintf("%s.%s", podName, podNamespace)
|
podFullName := fmt.Sprintf("%s.%s", podName, podNamespace)
|
||||||
returnedPodFullName, returnedContainerName, hash := parseDockerName(name)
|
returnedPodFullName, _, returnedContainerName, hash := parseDockerName(name)
|
||||||
if podFullName != returnedPodFullName || containerName != returnedContainerName || computedHash != hash {
|
if podFullName != returnedPodFullName || containerName != returnedContainerName || computedHash != hash {
|
||||||
t.Errorf("For (%s, %s, %d), unpacked (%s, %s, %d)", podFullName, containerName, computedHash, returnedPodFullName, returnedContainerName, hash)
|
t.Errorf("For (%s, %s, %d), unpacked (%s, %s, %d)", podFullName, containerName, computedHash, returnedPodFullName, returnedContainerName, hash)
|
||||||
}
|
}
|
||||||
@ -108,7 +108,7 @@ func TestContainerManifestNaming(t *testing.T) {
|
|||||||
name := fmt.Sprintf("k8s--%s--%s.%s--12345", container.Name, pod.Name, pod.Namespace)
|
name := fmt.Sprintf("k8s--%s--%s.%s--12345", container.Name, pod.Name, pod.Namespace)
|
||||||
|
|
||||||
podFullName := fmt.Sprintf("%s.%s", pod.Name, pod.Namespace)
|
podFullName := fmt.Sprintf("%s.%s", pod.Name, pod.Namespace)
|
||||||
returnedPodFullName, returnedContainerName, hash := parseDockerName(name)
|
returnedPodFullName, _, returnedContainerName, hash := parseDockerName(name)
|
||||||
if returnedPodFullName != podFullName || returnedContainerName != container.Name || hash != 0 {
|
if returnedPodFullName != podFullName || returnedContainerName != container.Name || hash != 0 {
|
||||||
t.Errorf("unexpected parse: %s %s %d", returnedPodFullName, returnedContainerName, hash)
|
t.Errorf("unexpected parse: %s %s %d", returnedPodFullName, returnedContainerName, hash)
|
||||||
}
|
}
|
||||||
@ -139,13 +139,13 @@ func TestGetContainerID(t *testing.T) {
|
|||||||
t.Errorf("Expected %#v, Got %#v", fakeDocker.containerList, dockerContainers)
|
t.Errorf("Expected %#v, Got %#v", fakeDocker.containerList, dockerContainers)
|
||||||
}
|
}
|
||||||
verifyCalls(t, fakeDocker, []string{"list"})
|
verifyCalls(t, fakeDocker, []string{"list"})
|
||||||
dockerContainer, found, _ := dockerContainers.FindPodContainer("qux", "foo")
|
dockerContainer, found, _ := dockerContainers.FindPodContainer("qux", "", "foo")
|
||||||
if dockerContainer == nil || !found {
|
if dockerContainer == nil || !found {
|
||||||
t.Errorf("Failed to find container %#v", dockerContainer)
|
t.Errorf("Failed to find container %#v", dockerContainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeDocker.clearCalls()
|
fakeDocker.clearCalls()
|
||||||
dockerContainer, found, _ = dockerContainers.FindPodContainer("foobar", "foo")
|
dockerContainer, found, _ = dockerContainers.FindPodContainer("foobar", "", "foo")
|
||||||
verifyCalls(t, fakeDocker, []string{})
|
verifyCalls(t, fakeDocker, []string{})
|
||||||
if dockerContainer != nil || found {
|
if dockerContainer != nil || found {
|
||||||
t.Errorf("Should not have found container %#v", dockerContainer)
|
t.Errorf("Should not have found container %#v", dockerContainer)
|
||||||
@ -943,7 +943,7 @@ func TestGetContainerInfo(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
stats, err := kubelet.GetContainerInfo("qux", "foo", req)
|
stats, err := kubelet.GetContainerInfo("qux", "", "foo", req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -1009,11 +1009,11 @@ func TestGetContainerInfoWithoutCadvisor(t *testing.T) {
|
|||||||
ID: "foobar",
|
ID: "foobar",
|
||||||
// pod id: qux
|
// pod id: qux
|
||||||
// container id: foo
|
// container id: foo
|
||||||
Names: []string{"/k8s--foo--qux--1234"},
|
Names: []string{"/k8s--foo--qux--uuid--1234"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
stats, _ := kubelet.GetContainerInfo("qux", "foo", nil)
|
stats, _ := kubelet.GetContainerInfo("qux", "uuid", "foo", nil)
|
||||||
// When there's no cAdvisor, the stats should be either nil or empty
|
// When there's no cAdvisor, the stats should be either nil or empty
|
||||||
if stats == nil {
|
if stats == nil {
|
||||||
return
|
return
|
||||||
@ -1047,11 +1047,11 @@ func TestGetContainerInfoWhenCadvisorFailed(t *testing.T) {
|
|||||||
ID: containerID,
|
ID: containerID,
|
||||||
// pod id: qux
|
// pod id: qux
|
||||||
// container id: foo
|
// container id: foo
|
||||||
Names: []string{"/k8s--foo--qux--1234"},
|
Names: []string{"/k8s--foo--qux--uuid--1234"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
stats, err := kubelet.GetContainerInfo("qux", "foo", req)
|
stats, err := kubelet.GetContainerInfo("qux", "uuid", "foo", req)
|
||||||
if stats != nil {
|
if stats != nil {
|
||||||
t.Errorf("non-nil stats on error")
|
t.Errorf("non-nil stats on error")
|
||||||
}
|
}
|
||||||
@ -1072,7 +1072,7 @@ func TestGetContainerInfoOnNonExistContainer(t *testing.T) {
|
|||||||
kubelet.cadvisorClient = mockCadvisor
|
kubelet.cadvisorClient = mockCadvisor
|
||||||
fakeDocker.containerList = []docker.APIContainers{}
|
fakeDocker.containerList = []docker.APIContainers{}
|
||||||
|
|
||||||
stats, _ := kubelet.GetContainerInfo("qux", "foo", nil)
|
stats, _ := kubelet.GetContainerInfo("qux", "", "foo", nil)
|
||||||
if stats != nil {
|
if stats != nil {
|
||||||
t.Errorf("non-nil stats on non exist container")
|
t.Errorf("non-nil stats on non exist container")
|
||||||
}
|
}
|
||||||
@ -1102,6 +1102,7 @@ func TestRunInContainerNoSuchPod(t *testing.T) {
|
|||||||
containerName := "containerFoo"
|
containerName := "containerFoo"
|
||||||
output, err := kubelet.RunInContainer(
|
output, err := kubelet.RunInContainer(
|
||||||
GetPodFullName(&Pod{Name: podName, Namespace: podNamespace}),
|
GetPodFullName(&Pod{Name: podName, Namespace: podNamespace}),
|
||||||
|
"",
|
||||||
containerName,
|
containerName,
|
||||||
[]string{"ls"})
|
[]string{"ls"})
|
||||||
if output != nil {
|
if output != nil {
|
||||||
@ -1132,6 +1133,7 @@ func TestRunInContainer(t *testing.T) {
|
|||||||
cmd := []string{"ls"}
|
cmd := []string{"ls"}
|
||||||
_, err := kubelet.RunInContainer(
|
_, err := kubelet.RunInContainer(
|
||||||
GetPodFullName(&Pod{Name: podName, Namespace: podNamespace}),
|
GetPodFullName(&Pod{Name: podName, Namespace: podNamespace}),
|
||||||
|
"",
|
||||||
containerName,
|
containerName,
|
||||||
cmd)
|
cmd)
|
||||||
if fakeCommandRunner.ID != containerID {
|
if fakeCommandRunner.ID != containerID {
|
||||||
@ -1209,7 +1211,7 @@ func TestRunHandlerExec(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := kubelet.runHandler(podName+"."+podNamespace, &container, container.Lifecycle.PostStart)
|
err := kubelet.runHandler(podName+"."+podNamespace, "", &container, container.Lifecycle.PostStart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -1251,7 +1253,7 @@ func TestRunHandlerHttp(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := kubelet.runHandler(podName+"."+podNamespace, &container, container.Lifecycle.PostStart)
|
err := kubelet.runHandler(podName+"."+podNamespace, "", &container, container.Lifecycle.PostStart)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -62,11 +62,11 @@ func ListenAndServeKubeletServer(host HostInterface, updates chan<- interface{},
|
|||||||
// HostInterface contains all the kubelet methods required by the server.
|
// HostInterface contains all the kubelet methods required by the server.
|
||||||
// For testablitiy.
|
// For testablitiy.
|
||||||
type HostInterface interface {
|
type HostInterface interface {
|
||||||
GetContainerInfo(podFullName, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error)
|
GetContainerInfo(podFullName, uuid, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error)
|
||||||
GetRootInfo(req *info.ContainerInfoRequest) (*info.ContainerInfo, error)
|
GetRootInfo(req *info.ContainerInfoRequest) (*info.ContainerInfo, error)
|
||||||
GetMachineInfo() (*info.MachineInfo, error)
|
GetMachineInfo() (*info.MachineInfo, error)
|
||||||
GetPodInfo(name string) (api.PodInfo, error)
|
GetPodInfo(name, uuid string) (api.PodInfo, error)
|
||||||
RunInContainer(name, container string, cmd []string) ([]byte, error)
|
RunInContainer(name, uuid, container string, cmd []string) ([]byte, error)
|
||||||
ServeLogs(w http.ResponseWriter, req *http.Request)
|
ServeLogs(w http.ResponseWriter, req *http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +150,7 @@ func (s *Server) handlePodInfo(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
podID := u.Query().Get("podID")
|
podID := u.Query().Get("podID")
|
||||||
|
podUUID := u.Query().Get("UUID")
|
||||||
if len(podID) == 0 {
|
if len(podID) == 0 {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
http.Error(w, "Missing 'podID=' query entry.", http.StatusBadRequest)
|
http.Error(w, "Missing 'podID=' query entry.", http.StatusBadRequest)
|
||||||
@ -157,7 +158,7 @@ func (s *Server) handlePodInfo(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
// TODO: backwards compatibility with existing API, needs API change
|
// TODO: backwards compatibility with existing API, needs API change
|
||||||
podFullName := GetPodFullName(&Pod{Name: podID, Namespace: "etcd"})
|
podFullName := GetPodFullName(&Pod{Name: podID, Namespace: "etcd"})
|
||||||
info, err := s.host.GetPodInfo(podFullName)
|
info, err := s.host.GetPodInfo(podFullName, podUUID)
|
||||||
if err == ErrNoContainersInPod {
|
if err == ErrNoContainersInPod {
|
||||||
http.Error(w, "Pod does not exist", http.StatusNotFound)
|
http.Error(w, "Pod does not exist", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
@ -211,15 +212,21 @@ func (s *Server) handleRun(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
parts := strings.Split(u.Path, "/")
|
parts := strings.Split(u.Path, "/")
|
||||||
if len(parts) != 4 {
|
var podID, uuid, container string
|
||||||
|
if len(parts) == 4 {
|
||||||
|
podID = parts[2]
|
||||||
|
container = parts[3]
|
||||||
|
} else if len(parts) == 5 {
|
||||||
|
podID = parts[2]
|
||||||
|
uuid = parts[3]
|
||||||
|
container = parts[4]
|
||||||
|
} else {
|
||||||
http.Error(w, "Unexpected path for command running", http.StatusBadRequest)
|
http.Error(w, "Unexpected path for command running", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
podID := parts[2]
|
|
||||||
container := parts[3]
|
|
||||||
podFullName := GetPodFullName(&Pod{Name: podID, Namespace: "etcd"})
|
podFullName := GetPodFullName(&Pod{Name: podID, Namespace: "etcd"})
|
||||||
command := strings.Split(u.Query().Get("cmd"), " ")
|
command := strings.Split(u.Query().Get("cmd"), " ")
|
||||||
data, err := s.host.RunInContainer(podFullName, container, command)
|
data, err := s.host.RunInContainer(podFullName, uuid, container, command)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.error(w, err)
|
s.error(w, err)
|
||||||
return
|
return
|
||||||
@ -241,7 +248,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
// serveStats implements stats logic.
|
// serveStats implements stats logic.
|
||||||
func (s *Server) serveStats(w http.ResponseWriter, req *http.Request) {
|
func (s *Server) serveStats(w http.ResponseWriter, req *http.Request) {
|
||||||
// /stats/<podfullname>/<containerName>
|
// /stats/<podfullname>/<containerName> or /stats/<podfullname>/<uuid>/<containerName>
|
||||||
components := strings.Split(strings.TrimPrefix(path.Clean(req.URL.Path), "/"), "/")
|
components := strings.Split(strings.TrimPrefix(path.Clean(req.URL.Path), "/"), "/")
|
||||||
var stats *info.ContainerInfo
|
var stats *info.ContainerInfo
|
||||||
var err error
|
var err error
|
||||||
@ -260,7 +267,10 @@ func (s *Server) serveStats(w http.ResponseWriter, req *http.Request) {
|
|||||||
// TODO(monnand) Implement this
|
// TODO(monnand) Implement this
|
||||||
errors.New("pod level status currently unimplemented")
|
errors.New("pod level status currently unimplemented")
|
||||||
case 3:
|
case 3:
|
||||||
stats, err = s.host.GetContainerInfo(components[1], components[2], &query)
|
// Backward compatibility without uuid information
|
||||||
|
stats, err = s.host.GetContainerInfo(components[1], "", components[2], &query)
|
||||||
|
case 4:
|
||||||
|
stats, err = s.host.GetContainerInfo(components[1], components[2], components[2], &query)
|
||||||
default:
|
default:
|
||||||
http.Error(w, "unknown resource.", http.StatusNotFound)
|
http.Error(w, "unknown resource.", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
|
@ -40,14 +40,14 @@ type fakeKubelet struct {
|
|||||||
rootInfoFunc func(query *info.ContainerInfoRequest) (*info.ContainerInfo, error)
|
rootInfoFunc func(query *info.ContainerInfoRequest) (*info.ContainerInfo, error)
|
||||||
machineInfoFunc func() (*info.MachineInfo, error)
|
machineInfoFunc func() (*info.MachineInfo, error)
|
||||||
logFunc func(w http.ResponseWriter, req *http.Request)
|
logFunc func(w http.ResponseWriter, req *http.Request)
|
||||||
runFunc func(podFullName, containerName string, cmd []string) ([]byte, error)
|
runFunc func(podFullName, uuid, containerName string, cmd []string) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fk *fakeKubelet) GetPodInfo(name string) (api.PodInfo, error) {
|
func (fk *fakeKubelet) GetPodInfo(name, uuid string) (api.PodInfo, error) {
|
||||||
return fk.infoFunc(name)
|
return fk.infoFunc(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fk *fakeKubelet) GetContainerInfo(podFullName, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
|
func (fk *fakeKubelet) GetContainerInfo(podFullName, uuid, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
|
||||||
return fk.containerInfoFunc(podFullName, containerName, req)
|
return fk.containerInfoFunc(podFullName, containerName, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,8 +63,8 @@ func (fk *fakeKubelet) ServeLogs(w http.ResponseWriter, req *http.Request) {
|
|||||||
fk.logFunc(w, req)
|
fk.logFunc(w, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fk *fakeKubelet) RunInContainer(podFullName, containerName string, cmd []string) ([]byte, error) {
|
func (fk *fakeKubelet) RunInContainer(podFullName, uuid, containerName string, cmd []string) ([]byte, error) {
|
||||||
return fk.runFunc(podFullName, containerName, cmd)
|
return fk.runFunc(podFullName, uuid, containerName, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
type serverTestFramework struct {
|
type serverTestFramework struct {
|
||||||
@ -301,7 +301,7 @@ func TestServeRunInContainer(t *testing.T) {
|
|||||||
expectedPodName := podName + ".etcd"
|
expectedPodName := podName + ".etcd"
|
||||||
expectedContainerName := "baz"
|
expectedContainerName := "baz"
|
||||||
expectedCommand := "ls -a"
|
expectedCommand := "ls -a"
|
||||||
fw.fakeKubelet.runFunc = func(podFullName, containerName string, cmd []string) ([]byte, error) {
|
fw.fakeKubelet.runFunc = func(podFullName, uuid, containerName string, cmd []string) ([]byte, error) {
|
||||||
if podFullName != expectedPodName {
|
if podFullName != expectedPodName {
|
||||||
t.Errorf("expected %s, got %s", expectedPodName, podFullName)
|
t.Errorf("expected %s, got %s", expectedPodName, podFullName)
|
||||||
}
|
}
|
||||||
@ -332,3 +332,46 @@ func TestServeRunInContainer(t *testing.T) {
|
|||||||
t.Errorf("expected %s, got %s", output, result)
|
t.Errorf("expected %s, got %s", output, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestServeRunInContainerWithUUID(t *testing.T) {
|
||||||
|
fw := newServerTest()
|
||||||
|
output := "foo bar"
|
||||||
|
podName := "foo"
|
||||||
|
expectedPodName := podName + ".etcd"
|
||||||
|
expectedUuid := "7e00838d_-_3523_-_11e4_-_8421_-_42010af0a720"
|
||||||
|
expectedContainerName := "baz"
|
||||||
|
expectedCommand := "ls -a"
|
||||||
|
fw.fakeKubelet.runFunc = func(podFullName, uuid, containerName string, cmd []string) ([]byte, error) {
|
||||||
|
if podFullName != expectedPodName {
|
||||||
|
t.Errorf("expected %s, got %s", expectedPodName, podFullName)
|
||||||
|
}
|
||||||
|
if uuid != expectedUuid {
|
||||||
|
t.Errorf("expected %s, got %s", expectedUuid, uuid)
|
||||||
|
}
|
||||||
|
if containerName != expectedContainerName {
|
||||||
|
t.Errorf("expected %s, got %s", expectedContainerName, containerName)
|
||||||
|
}
|
||||||
|
if strings.Join(cmd, " ") != expectedCommand {
|
||||||
|
t.Errorf("expected: %s, got %v", expectedCommand, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte(output), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.Get(fw.testHTTPServer.URL + "/run/" + podName + "/" + expectedUuid + "/" + expectedContainerName + "?cmd=ls%20-a")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Got error GETing: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
// copying the response body did not work
|
||||||
|
t.Errorf("Cannot copy resp: %#v", err)
|
||||||
|
}
|
||||||
|
result := string(body)
|
||||||
|
if result != output {
|
||||||
|
t.Errorf("expected %s, got %s", output, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -67,8 +67,9 @@ func NewRegistryStorage(config *RegistryStorageConfig) apiserver.RESTStorage {
|
|||||||
|
|
||||||
func (rs *RegistryStorage) Create(obj runtime.Object) (<-chan runtime.Object, error) {
|
func (rs *RegistryStorage) Create(obj runtime.Object) (<-chan runtime.Object, error) {
|
||||||
pod := obj.(*api.Pod)
|
pod := obj.(*api.Pod)
|
||||||
|
pod.DesiredState.Manifest.UUID = uuid.NewUUID().String()
|
||||||
if len(pod.ID) == 0 {
|
if len(pod.ID) == 0 {
|
||||||
pod.ID = uuid.NewUUID().String()
|
pod.ID = pod.DesiredState.Manifest.UUID
|
||||||
}
|
}
|
||||||
pod.DesiredState.Manifest.ID = pod.ID
|
pod.DesiredState.Manifest.ID = pod.ID
|
||||||
if errs := validation.ValidatePod(pod); len(errs) > 0 {
|
if errs := validation.ValidatePod(pod); len(errs) > 0 {
|
||||||
|
@ -99,6 +99,29 @@ func TestCreatePodSetsIds(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCreatePodSetsUUIDs(t *testing.T) {
|
||||||
|
podRegistry := registrytest.NewPodRegistry(nil)
|
||||||
|
podRegistry.Err = fmt.Errorf("test error")
|
||||||
|
storage := RegistryStorage{
|
||||||
|
registry: podRegistry,
|
||||||
|
}
|
||||||
|
desiredState := api.PodState{
|
||||||
|
Manifest: api.ContainerManifest{
|
||||||
|
Version: "v1beta1",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pod := &api.Pod{DesiredState: desiredState}
|
||||||
|
ch, err := storage.Create(pod)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected %#v, Got %#v", nil, err)
|
||||||
|
}
|
||||||
|
expectApiStatusError(t, ch, podRegistry.Err.Error())
|
||||||
|
|
||||||
|
if len(podRegistry.Pod.DesiredState.Manifest.UUID) == 0 {
|
||||||
|
t.Errorf("Expected pod UUID to be set, Got %#v", pod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestListPodsError(t *testing.T) {
|
func TestListPodsError(t *testing.T) {
|
||||||
podRegistry := registrytest.NewPodRegistry(nil)
|
podRegistry := registrytest.NewPodRegistry(nil)
|
||||||
podRegistry.Err = fmt.Errorf("test error")
|
podRegistry.Err = fmt.Errorf("test error")
|
||||||
|
Loading…
Reference in New Issue
Block a user