Merge pull request #3478 from thockin/uid_type

Use a strong type for UID fields
This commit is contained in:
Daniel Smith
2015-01-14 14:20:22 -08:00
31 changed files with 182 additions and 170 deletions

View File

@@ -20,6 +20,7 @@ import (
"fmt"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
cadvisor "github.com/google/cadvisor/info"
)
@@ -53,7 +54,7 @@ func (kl *Kubelet) statsFromDockerContainer(cc cadvisorInterface, containerId st
}
// GetContainerInfo returns stats (from Cadvisor) for a container.
func (kl *Kubelet) GetContainerInfo(podFullName, uuid, containerName string, req *cadvisor.ContainerInfoRequest) (*cadvisor.ContainerInfo, error) {
func (kl *Kubelet) GetContainerInfo(podFullName string, uid util.UID, containerName string, req *cadvisor.ContainerInfoRequest) (*cadvisor.ContainerInfo, error) {
cc := kl.GetCadvisorClient()
if cc == nil {
return nil, nil
@@ -62,7 +63,7 @@ func (kl *Kubelet) GetContainerInfo(podFullName, uuid, containerName string, req
if err != nil {
return nil, err
}
dockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uuid, containerName)
dockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uid, containerName)
if !found {
return nil, fmt.Errorf("couldn't find container")
}

View File

@@ -22,6 +22,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
const (
@@ -52,7 +53,7 @@ func (s sortedPods) Less(i, j int) bool {
func CreateValidPod(name, namespace, source string) api.BoundPod {
return api.BoundPod{
ObjectMeta: api.ObjectMeta{
UID: name, // for the purpose of testing, this is unique enough
UID: util.UID(name), // for the purpose of testing, this is unique enough
Name: name,
Namespace: namespace,
Annotations: map[string]string{kubelet.ConfigSourceAnnotationKey: source},

View File

@@ -164,7 +164,7 @@ func extractFromFile(filename string) (api.BoundPod, error) {
fmt.Fprintf(hasher, "host:%s", hostname)
fmt.Fprintf(hasher, "file:%s", filename)
util.DeepHashObject(hasher, pod)
pod.UID = hex.EncodeToString(hasher.Sum(nil)[0:])
pod.UID = util.UID(hex.EncodeToString(hasher.Sum(nil)[0:]))
glog.V(5).Infof("Generated UID %q for pod %q from file %s", pod.UID, pod.Name, filename)
}
if len(pod.Namespace) == 0 {

View File

@@ -28,12 +28,13 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
func ExampleManifestAndPod(id string) (api.ContainerManifest, api.BoundPod) {
manifest := api.ContainerManifest{
ID: id,
UUID: id,
UUID: util.UID(id),
Containers: []api.Container{
{
Name: "c" + id,
@@ -53,7 +54,7 @@ func ExampleManifestAndPod(id string) (api.ContainerManifest, api.BoundPod) {
expectedPod := api.BoundPod{
ObjectMeta: api.ObjectMeta{
Name: id,
UID: id,
UID: util.UID(id),
},
Spec: api.PodSpec{
Containers: []api.Container{

View File

@@ -147,7 +147,7 @@ func applyDefaults(pod *api.BoundPod, url string) {
hasher := md5.New()
fmt.Fprintf(hasher, "url:%s", url)
util.DeepHashObject(hasher, pod)
pod.UID = hex.EncodeToString(hasher.Sum(nil)[0:])
pod.UID = util.UID(hex.EncodeToString(hasher.Sum(nil)[0:]))
glog.V(5).Infof("Generated UID %q for pod %q from URL %s", pod.UID, pod.Name, url)
}
if len(pod.Namespace) == 0 {

View File

@@ -254,7 +254,7 @@ func (p throttledDockerPuller) IsImagePresent(name string) (bool, error) {
// DockerContainers is a map of containers
type DockerContainers map[DockerID]*docker.APIContainers
func (c DockerContainers) FindPodContainer(podFullName, uuid, containerName string) (*docker.APIContainers, bool, uint64) {
func (c DockerContainers) FindPodContainer(podFullName string, uid util.UID, containerName string) (*docker.APIContainers, bool, uint64) {
for _, dockerContainer := range c {
if len(dockerContainer.Names) == 0 {
continue
@@ -262,7 +262,7 @@ func (c DockerContainers) FindPodContainer(podFullName, uuid, containerName stri
// TODO(proppy): build the docker container name and do a map lookup instead?
dockerManifestID, dockerUUID, dockerContainerName, hash := ParseDockerName(dockerContainer.Names[0])
if dockerManifestID == podFullName &&
(uuid == "" || dockerUUID == uuid) &&
(uid == "" || dockerUUID == uid) &&
dockerContainerName == containerName {
return dockerContainer, true, hash
}
@@ -313,8 +313,8 @@ func GetKubeletDockerContainers(client DockerInterface, allContainers bool) (Doc
}
// GetRecentDockerContainersWithNameAndUUID returns a list of dead docker containers which matches the name
// and uuid given.
func GetRecentDockerContainersWithNameAndUUID(client DockerInterface, podFullName, uuid, containerName string) ([]*docker.Container, error) {
// and uid given.
func GetRecentDockerContainersWithNameAndUUID(client DockerInterface, podFullName string, uid util.UID, containerName string) ([]*docker.Container, error) {
var result []*docker.Container
containers, err := client.ListContainers(docker.ListContainersOptions{All: true})
if err != nil {
@@ -328,7 +328,7 @@ func GetRecentDockerContainersWithNameAndUUID(client DockerInterface, podFullNam
if dockerPodName != podFullName {
continue
}
if uuid != "" && dockerUUID != uuid {
if uid != "" && dockerUUID != uid {
continue
}
if dockerContainerName != containerName {
@@ -447,7 +447,7 @@ func inspectContainer(client DockerInterface, dockerID, containerName, tPath str
}
// GetDockerPodInfo returns docker info for all containers in the pod/manifest.
func GetDockerPodInfo(client DockerInterface, manifest api.PodSpec, podFullName, uuid string) (api.PodInfo, error) {
func GetDockerPodInfo(client DockerInterface, manifest api.PodSpec, podFullName string, uid util.UID) (api.PodInfo, error) {
info := api.PodInfo{}
expectedContainers := make(map[string]api.Container)
for _, container := range manifest.Containers {
@@ -468,7 +468,7 @@ func GetDockerPodInfo(client DockerInterface, manifest api.PodSpec, podFullName,
if dockerManifestID != podFullName {
continue
}
if uuid != "" && dockerUUID != uuid {
if uid != "" && dockerUUID != uid {
continue
}
c, found := expectedContainers[dockerContainerName]
@@ -545,7 +545,7 @@ func HashContainer(container *api.Container) uint64 {
}
// Creates a name which can be reversed to identify both full pod name and container name.
func BuildDockerName(podUID, podFullName string, container *api.Container) string {
func BuildDockerName(podUID util.UID, podFullName string, container *api.Container) string {
containerName := container.Name + "." + strconv.FormatUint(HashContainer(container), 16)
return fmt.Sprintf("%s_%s_%s_%s_%08x",
containerNamePrefix,
@@ -557,7 +557,7 @@ func BuildDockerName(podUID, podFullName string, container *api.Container) strin
// Unpacks 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 the one we created, we may return empty strings.
func ParseDockerName(name string) (podFullName, podUID, containerName string, hash uint64) {
func ParseDockerName(name string) (podFullName string, podUID util.UID, containerName string, hash uint64) {
// For some reason docker appears to be appending '/' to names.
// If it's there, strip it.
if name[0] == '/' {
@@ -590,7 +590,7 @@ func ParseDockerName(name string) (podFullName, podUID, containerName string, ha
podFullName = parts[2]
// Pod UID.
podUID = parts[3]
podUID = util.UID(parts[3])
return
}

View File

@@ -91,9 +91,9 @@ func verifyPackUnpack(t *testing.T, podNamespace, podUID, podName, containerName
util.DeepHashObject(hasher, *container)
computedHash := uint64(hasher.Sum32())
podFullName := fmt.Sprintf("%s.%s", podName, podNamespace)
name := BuildDockerName(podUID, podFullName, container)
name := BuildDockerName(util.UID(podUID), podFullName, container)
returnedPodFullName, returnedUID, returnedContainerName, hash := ParseDockerName(name)
if podFullName != returnedPodFullName || podUID != returnedUID || containerName != returnedContainerName || computedHash != hash {
if podFullName != returnedPodFullName || podUID != string(returnedUID) || containerName != returnedContainerName || computedHash != hash {
t.Errorf("For (%s, %s, %s, %d), unpacked (%s, %s, %s, %d)", podFullName, podUID, containerName, computedHash, returnedPodFullName, returnedUID, returnedContainerName, hash)
}
}
@@ -114,7 +114,7 @@ func TestContainerManifestNaming(t *testing.T) {
podFullName := fmt.Sprintf("%s.%s", podName, podNamespace)
returnedPodFullName, returnedPodUID, returnedContainerName, hash := ParseDockerName(name)
if returnedPodFullName != podFullName || returnedPodUID != podUID || returnedContainerName != container.Name || hash != 0 {
if returnedPodFullName != podFullName || string(returnedPodUID) != podUID || returnedContainerName != container.Name || hash != 0 {
t.Errorf("unexpected parse: %s %s %s %d", returnedPodFullName, returnedPodUID, returnedContainerName, hash)
}
}

View File

@@ -32,8 +32,8 @@ type execActionHandler struct {
kubelet *Kubelet
}
func (e *execActionHandler) Run(podFullName, uuid string, container *api.Container, handler *api.Handler) error {
_, err := e.kubelet.RunInContainer(podFullName, uuid, container.Name, handler.Exec.Command)
func (e *execActionHandler) Run(podFullName string, uid util.UID, container *api.Container, handler *api.Handler) error {
_, err := e.kubelet.RunInContainer(podFullName, uid, container.Name, handler.Exec.Command)
return err
}
@@ -67,11 +67,11 @@ func ResolvePort(portReference util.IntOrString, container *api.Container) (int,
return -1, fmt.Errorf("couldn't find port: %v in %v", portReference, container)
}
func (h *httpActionHandler) Run(podFullName, uuid string, container *api.Container, handler *api.Handler) error {
func (h *httpActionHandler) Run(podFullName string, uid util.UID, container *api.Container, handler *api.Handler) error {
host := handler.HTTPGet.Host
if len(host) == 0 {
var info api.PodInfo
info, err := h.kubelet.GetPodInfo(podFullName, uuid)
info, err := h.kubelet.GetPodInfo(podFullName, uid)
if err != nil {
glog.Errorf("unable to get pod info, event handlers may be invalid.")
return err

View File

@@ -186,16 +186,16 @@ func (kl *Kubelet) GetPodsDir() string {
// GetPodDir returns the full path to the per-pod data directory for the
// specified pod. This directory may not exist if the pod does not exist.
func (kl *Kubelet) GetPodDir(podUID string) string {
func (kl *Kubelet) GetPodDir(podUID util.UID) string {
// Backwards compat. The "old" stuff should be removed before 1.0
// release. The thinking here is this:
// !old && !new = use new
// !old && new = use new
// old && !new = use old
// old && new = use new (but warn)
oldPath := path.Join(kl.GetRootDir(), podUID)
oldPath := path.Join(kl.GetRootDir(), string(podUID))
oldExists := dirExists(oldPath)
newPath := path.Join(kl.GetPodsDir(), podUID)
newPath := path.Join(kl.GetPodsDir(), string(podUID))
newExists := dirExists(newPath)
if oldExists && !newExists {
return oldPath
@@ -209,14 +209,14 @@ func (kl *Kubelet) GetPodDir(podUID string) string {
// GetPodVolumesDir returns the full path to the per-pod data directory under
// which volumes are created for the specified pod. This directory may not
// exist if the pod does not exist.
func (kl *Kubelet) GetPodVolumesDir(podUID string) string {
func (kl *Kubelet) GetPodVolumesDir(podUID util.UID) string {
return path.Join(kl.GetPodDir(podUID), "volumes")
}
// GetPodContainerDir returns the full path to the per-pod data directory under
// which container data is held for the specified pod. This directory may not
// exist if the pod or container does not exist.
func (kl *Kubelet) GetPodContainerDir(podUID, ctrName string) string {
func (kl *Kubelet) GetPodContainerDir(podUID util.UID, ctrName string) string {
// Backwards compat. The "old" stuff should be removed before 1.0
// release. The thinking here is this:
// !old && !new = use new
@@ -256,15 +256,15 @@ func (kl *Kubelet) setupDataDirs() error {
}
// Get a list of pods that have data directories.
func (kl *Kubelet) listPodsFromDisk() ([]string, error) {
func (kl *Kubelet) listPodsFromDisk() ([]util.UID, error) {
podInfos, err := ioutil.ReadDir(kl.GetPodsDir())
if err != nil {
return nil, err
}
pods := []string{}
pods := []util.UID{}
for i := range podInfos {
if podInfos[i].IsDir() {
pods = append(pods, podInfos[i].Name())
pods = append(pods, util.UID(podInfos[i].Name()))
}
}
return pods, nil
@@ -341,13 +341,13 @@ func (kl *Kubelet) GarbageCollectContainers() error {
if err != nil {
return err
}
uuidToIDMap := map[string][]string{}
uidToIDMap := map[string][]string{}
for _, container := range containers {
_, uuid, name, _ := dockertools.ParseDockerName(container.ID)
uuidName := uuid + "." + name
uuidToIDMap[uuidName] = append(uuidToIDMap[uuidName], container.ID)
_, uid, name, _ := dockertools.ParseDockerName(container.ID)
uidName := string(uid) + "." + name
uidToIDMap[uidName] = append(uidToIDMap[uidName], container.ID)
}
for _, list := range uuidToIDMap {
for _, list := range uidToIDMap {
if len(list) <= kl.maxContainerCount {
continue
}
@@ -516,7 +516,7 @@ func (kl *Kubelet) mountExternalVolumes(pod *api.BoundPod) (volumeMap, error) {
// A basic interface that knows how to execute handlers
type actionHandler interface {
Run(podFullName, uuid string, container *api.Container, handler *api.Handler) error
Run(podFullName string, uid util.UID, container *api.Container, handler *api.Handler) error
}
func (kl *Kubelet) newActionHandler(handler *api.Handler) actionHandler {
@@ -531,12 +531,12 @@ func (kl *Kubelet) newActionHandler(handler *api.Handler) actionHandler {
}
}
func (kl *Kubelet) runHandler(podFullName, uuid string, container *api.Container, handler *api.Handler) error {
func (kl *Kubelet) runHandler(podFullName string, uid util.UID, container *api.Container, handler *api.Handler) error {
actionHandler := kl.newActionHandler(handler)
if actionHandler == nil {
return fmt.Errorf("invalid handler")
}
return actionHandler.Run(podFullName, uuid, container, handler)
return actionHandler.Run(podFullName, uid, container, handler)
}
// fieldPath returns a fieldPath locating container within pod.
@@ -865,22 +865,22 @@ type empty struct{}
func (kl *Kubelet) syncPod(pod *api.BoundPod, dockerContainers dockertools.DockerContainers) error {
podFullName := GetPodFullName(pod)
uuid := pod.UID
uid := pod.UID
containersToKeep := make(map[dockertools.DockerID]empty)
killedContainers := make(map[dockertools.DockerID]empty)
glog.V(4).Infof("Syncing Pod, podFullName: %q, uuid: %q", podFullName, uuid)
glog.V(4).Infof("Syncing Pod, podFullName: %q, uid: %q", podFullName, uid)
// Make data dirs.
if err := os.Mkdir(kl.GetPodDir(uuid), 0750); err != nil && !os.IsExist(err) {
if err := os.Mkdir(kl.GetPodDir(uid), 0750); err != nil && !os.IsExist(err) {
return err
}
if err := os.Mkdir(kl.GetPodVolumesDir(uuid), 0750); err != nil && !os.IsExist(err) {
if err := os.Mkdir(kl.GetPodVolumesDir(uid), 0750); err != nil && !os.IsExist(err) {
return err
}
// Make sure we have a network container
var netID dockertools.DockerID
if netDockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uuid, networkContainerName); found {
if netDockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uid, networkContainerName); found {
netID = dockertools.DockerID(netDockerContainer.ID)
} else {
glog.V(2).Infof("Network container doesn't exist for pod %q, killing and re-creating the pod", podFullName)
@@ -911,9 +911,9 @@ func (kl *Kubelet) syncPod(pod *api.BoundPod, dockerContainers dockertools.Docke
}
podStatus := api.PodStatus{}
info, err := kl.GetPodInfo(podFullName, uuid)
info, err := kl.GetPodInfo(podFullName, uid)
if err != nil {
glog.Errorf("Unable to get pod with name %q and uuid %q info, health checks may be invalid", podFullName, uuid)
glog.Errorf("Unable to get pod with name %q and uid %q info, health checks may be invalid", podFullName, uid)
}
netInfo, found := info[networkContainerName]
if found {
@@ -922,14 +922,14 @@ func (kl *Kubelet) syncPod(pod *api.BoundPod, dockerContainers dockertools.Docke
for _, container := range pod.Spec.Containers {
expectedHash := dockertools.HashContainer(&container)
if dockerContainer, found, hash := dockerContainers.FindPodContainer(podFullName, uuid, container.Name); found {
if dockerContainer, found, hash := dockerContainers.FindPodContainer(podFullName, uid, container.Name); found {
containerID := dockertools.DockerID(dockerContainer.ID)
glog.V(3).Infof("pod %q container %q exists as %v", podFullName, container.Name, containerID)
// look for changes in the container.
if hash == 0 || hash == expectedHash {
// TODO: This should probably be separated out into a separate goroutine.
healthy, err := kl.healthy(podFullName, uuid, podStatus, container, dockerContainer)
healthy, err := kl.healthy(podFullName, uid, podStatus, container, dockerContainer)
if err != nil {
glog.V(1).Infof("health check errored: %v", err)
containersToKeep[containerID] = empty{}
@@ -950,7 +950,7 @@ func (kl *Kubelet) syncPod(pod *api.BoundPod, dockerContainers dockertools.Docke
killedContainers[containerID] = empty{}
// Also kill associated network container
if netContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uuid, networkContainerName); found {
if netContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uid, networkContainerName); found {
if err := kl.killContainer(netContainer); err != nil {
glog.V(1).Infof("Failed to kill network container %q: %v", netContainer.ID, err)
continue
@@ -959,29 +959,29 @@ func (kl *Kubelet) syncPod(pod *api.BoundPod, dockerContainers dockertools.Docke
}
// Check RestartPolicy for container
recentContainers, err := dockertools.GetRecentDockerContainersWithNameAndUUID(kl.dockerClient, podFullName, uuid, container.Name)
recentContainers, err := dockertools.GetRecentDockerContainersWithNameAndUUID(kl.dockerClient, podFullName, uid, container.Name)
if err != nil {
glog.Errorf("Error listing recent containers with name and uuid:%s--%s--%s", podFullName, uuid, container.Name)
glog.Errorf("Error listing recent containers with name and uid:%s--%s--%s", podFullName, uid, container.Name)
// TODO(dawnchen): error handling here?
}
if len(recentContainers) > 0 && pod.Spec.RestartPolicy.Always == nil {
if pod.Spec.RestartPolicy.Never != nil {
glog.V(3).Infof("Already ran container with name %s--%s--%s, do nothing",
podFullName, uuid, container.Name)
podFullName, uid, container.Name)
continue
}
if pod.Spec.RestartPolicy.OnFailure != nil {
// Check the exit code of last run
if recentContainers[0].State.ExitCode == 0 {
glog.V(3).Infof("Already successfully ran container with name %s--%s--%s, do nothing",
podFullName, uuid, container.Name)
podFullName, uid, container.Name)
continue
}
}
}
glog.V(3).Infof("Container with name %s--%s--%s doesn't exist, creating %#v", podFullName, uuid, container.Name, container)
glog.V(3).Infof("Container with name %s--%s--%s doesn't exist, creating %#v", podFullName, uid, container.Name, container)
ref, err := containerRef(pod, &container)
if err != nil {
glog.Errorf("Couldn't make a ref to pod %v, container %v: '%v'", pod.Name, container.Name, err)
@@ -1016,7 +1016,7 @@ func (kl *Kubelet) syncPod(pod *api.BoundPod, dockerContainers dockertools.Docke
// Kill any containers in this pod which were not identified above (guards against duplicates).
for id, container := range dockerContainers {
curPodFullName, curUUID, _, _ := dockertools.ParseDockerName(container.Names[0])
if curPodFullName == podFullName && curUUID == uuid {
if curPodFullName == podFullName && curUUID == uid {
// Don't kill containers we want to keep or those we already killed.
_, keep := containersToKeep[id]
_, killed := killedContainers[id]
@@ -1035,7 +1035,7 @@ func (kl *Kubelet) syncPod(pod *api.BoundPod, dockerContainers dockertools.Docke
type podContainer struct {
podFullName string
uuid string
uid util.UID
containerName string
}
@@ -1055,7 +1055,7 @@ func getDesiredVolumes(pods []api.BoundPod) map[string]api.Volume {
func (kl *Kubelet) cleanupOrphanedPods(pods []api.BoundPod) error {
desired := util.NewStringSet()
for i := range pods {
desired.Insert(pods[i].UID)
desired.Insert(string(pods[i].UID))
}
found, err := kl.listPodsFromDisk()
if err != nil {
@@ -1063,7 +1063,7 @@ func (kl *Kubelet) cleanupOrphanedPods(pods []api.BoundPod) error {
}
errlist := []error{}
for i := range found {
if !desired.Has(found[i]) {
if !desired.Has(string(found[i])) {
glog.V(3).Infof("Orphaned pod %q found, removing", found[i])
if err := os.RemoveAll(kl.GetPodDir(found[i])); err != nil {
errlist = append(errlist, err)
@@ -1098,7 +1098,7 @@ func (kl *Kubelet) SyncPods(pods []api.BoundPod) error {
glog.V(4).Infof("Desired: %#v", pods)
var err error
desiredContainers := make(map[podContainer]empty)
desiredPods := make(map[string]empty)
desiredPods := make(map[util.UID]empty)
dockerContainers, err := dockertools.GetKubeletDockerContainers(kl.dockerClient, false)
if err != nil {
@@ -1110,13 +1110,13 @@ func (kl *Kubelet) SyncPods(pods []api.BoundPod) error {
for ix := range pods {
pod := &pods[ix]
podFullName := GetPodFullName(pod)
uuid := pod.UID
desiredPods[uuid] = empty{}
uid := pod.UID
desiredPods[uid] = empty{}
// Add all containers (including net) to the map.
desiredContainers[podContainer{podFullName, uuid, networkContainerName}] = empty{}
desiredContainers[podContainer{podFullName, uid, networkContainerName}] = empty{}
for _, cont := range pod.Spec.Containers {
desiredContainers[podContainer{podFullName, uuid, cont.Name}] = empty{}
desiredContainers[podContainer{podFullName, uid, cont.Name}] = empty{}
}
// Run the sync in an async manifest worker.
@@ -1130,8 +1130,8 @@ func (kl *Kubelet) SyncPods(pods []api.BoundPod) error {
// Kill any containers we don't need.
for _, container := range dockerContainers {
// Don't kill containers that are in the desired pods.
podFullName, uuid, containerName, _ := dockertools.ParseDockerName(container.Names[0])
if _, found := desiredPods[uuid]; found {
podFullName, uid, containerName, _ := dockertools.ParseDockerName(container.Names[0])
if _, found := desiredPods[uid]; found {
// syncPod() will handle this one.
continue
}
@@ -1142,7 +1142,7 @@ func (kl *Kubelet) SyncPods(pods []api.BoundPod) error {
glog.V(4).Infof("Skipping delete of container (%q), source (%s) aren't ready yet.", podFullName, source)
continue
}
pc := podContainer{podFullName, uuid, containerName}
pc := podContainer{podFullName, uid, containerName}
if _, ok := desiredContainers[pc]; !ok {
glog.V(1).Infof("Killing unwanted container %+v", pc)
err = kl.killContainer(container)
@@ -1169,7 +1169,7 @@ func (kl *Kubelet) SyncPods(pods []api.BoundPod) error {
func updateBoundPods(changed []api.BoundPod, current []api.BoundPod) []api.BoundPod {
updated := []api.BoundPod{}
m := map[string]*api.BoundPod{}
m := map[util.UID]*api.BoundPod{}
for i := range changed {
pod := &changed[i]
m[pod.UID] = pod
@@ -1277,7 +1277,7 @@ func (kl *Kubelet) GetPodByName(namespace, name string) (*api.BoundPod, bool) {
}
// GetPodInfo returns information from Docker about the containers in a pod
func (kl *Kubelet) GetPodInfo(podFullName, uuid string) (api.PodInfo, error) {
func (kl *Kubelet) GetPodInfo(podFullName string, uid util.UID) (api.PodInfo, error) {
var manifest api.PodSpec
for _, pod := range kl.pods {
if GetPodFullName(&pod) == podFullName {
@@ -1285,10 +1285,10 @@ func (kl *Kubelet) GetPodInfo(podFullName, uuid string) (api.PodInfo, error) {
break
}
}
return dockertools.GetDockerPodInfo(kl.dockerClient, manifest, podFullName, uuid)
return dockertools.GetDockerPodInfo(kl.dockerClient, manifest, podFullName, uid)
}
func (kl *Kubelet) healthy(podFullName, podUUID string, status api.PodStatus, container api.Container, dockerContainer *docker.APIContainers) (health.Status, error) {
func (kl *Kubelet) healthy(podFullName string, podUID util.UID, status api.PodStatus, container api.Container, dockerContainer *docker.APIContainers) (health.Status, error) {
// Give the container 60 seconds to start up.
if container.LivenessProbe == nil {
return health.Healthy, nil
@@ -1299,7 +1299,7 @@ func (kl *Kubelet) healthy(podFullName, podUUID string, status api.PodStatus, co
if kl.healthChecker == nil {
return health.Healthy, nil
}
return kl.healthChecker.HealthCheck(podFullName, podUUID, status, container)
return kl.healthChecker.HealthCheck(podFullName, podUID, status, container)
}
// Returns logs of current machine.
@@ -1309,7 +1309,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
func (kl *Kubelet) RunInContainer(podFullName, uuid, container string, cmd []string) ([]byte, error) {
func (kl *Kubelet) RunInContainer(podFullName string, uid util.UID, container string, cmd []string) ([]byte, error) {
if kl.runner == nil {
return nil, fmt.Errorf("no runner specified.")
}
@@ -1317,7 +1317,7 @@ func (kl *Kubelet) RunInContainer(podFullName, uuid, container string, cmd []str
if err != nil {
return nil, err
}
dockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uuid, container)
dockerContainer, found, _ := dockerContainers.FindPodContainer(podFullName, uid, container)
if !found {
return nil, fmt.Errorf("container not found (%q)", container)
}
@@ -1332,7 +1332,7 @@ func (kl *Kubelet) BirthCry() {
ref := &api.ObjectReference{
Kind: "Minion",
Name: kl.hostname,
UID: kl.hostname,
UID: util.UID(kl.hostname),
Namespace: api.NamespaceDefault,
}
record.Eventf(ref, "", "starting", "Starting kubelet.")

View File

@@ -807,7 +807,7 @@ func TestSyncPodDeletesDuplicate(t *testing.T) {
type FalseHealthChecker struct{}
func (f *FalseHealthChecker) HealthCheck(podFullName, podUUID string, status api.PodStatus, container api.Container) (health.Status, error) {
func (f *FalseHealthChecker) HealthCheck(podFullName string, podUID util.UID, status api.PodStatus, container api.Container) (health.Status, error) {
return health.Unhealthy, nil
}

View File

@@ -34,6 +34,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/healthz"
"github.com/GoogleCloudPlatform/kubernetes/pkg/httplog"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/golang/glog"
"github.com/google/cadvisor/info"
)
@@ -61,13 +62,13 @@ func ListenAndServeKubeletServer(host HostInterface, address net.IP, port uint,
// HostInterface contains all the kubelet methods required by the server.
// For testablitiy.
type HostInterface interface {
GetContainerInfo(podFullName, uuid, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error)
GetContainerInfo(podFullName string, uid util.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error)
GetRootInfo(req *info.ContainerInfoRequest) (*info.ContainerInfo, error)
GetMachineInfo() (*info.MachineInfo, error)
GetBoundPods() ([]api.BoundPod, error)
GetPodByName(namespace, name string) (*api.BoundPod, bool)
GetPodInfo(name, uuid string) (api.PodInfo, error)
RunInContainer(name, uuid, container string, cmd []string) ([]byte, error)
GetPodInfo(name string, uid util.UID) (api.PodInfo, error)
RunInContainer(name string, uid util.UID, container string, cmd []string) ([]byte, error)
GetKubeletContainerLogs(podFullName, containerName, tail string, follow bool, stdout, stderr io.Writer) error
ServeLogs(w http.ResponseWriter, req *http.Request)
}
@@ -203,7 +204,7 @@ func (s *Server) handlePodInfo(w http.ResponseWriter, req *http.Request, version
return
}
podID := u.Query().Get("podID")
podUUID := u.Query().Get("UUID")
podUID := util.UID(u.Query().Get("UUID"))
podNamespace := u.Query().Get("podNamespace")
if len(podID) == 0 {
w.WriteHeader(http.StatusBadRequest)
@@ -220,7 +221,7 @@ func (s *Server) handlePodInfo(w http.ResponseWriter, req *http.Request, version
http.Error(w, "Pod does not exist", http.StatusNotFound)
return
}
info, err := s.host.GetPodInfo(GetPodFullName(pod), podUUID)
info, err := s.host.GetPodInfo(GetPodFullName(pod), podUID)
if err != nil {
s.error(w, err)
return
@@ -270,7 +271,8 @@ func (s *Server) handleRun(w http.ResponseWriter, req *http.Request) {
return
}
parts := strings.Split(u.Path, "/")
var podNamespace, podID, uuid, container string
var podNamespace, podID, container string
var uid util.UID
if len(parts) == 5 {
podNamespace = parts[2]
podID = parts[3]
@@ -278,7 +280,7 @@ func (s *Server) handleRun(w http.ResponseWriter, req *http.Request) {
} else if len(parts) == 6 {
podNamespace = parts[2]
podID = parts[3]
uuid = parts[4]
uid = util.UID(parts[4])
container = parts[5]
} else {
http.Error(w, "Unexpected path for command running", http.StatusBadRequest)
@@ -290,7 +292,7 @@ func (s *Server) handleRun(w http.ResponseWriter, req *http.Request) {
return
}
command := strings.Split(u.Query().Get("cmd"), " ")
data, err := s.host.RunInContainer(GetPodFullName(pod), uuid, container, command)
data, err := s.host.RunInContainer(GetPodFullName(pod), uid, container, command)
if err != nil {
s.error(w, err)
return
@@ -314,7 +316,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// serveStats implements stats logic.
func (s *Server) serveStats(w http.ResponseWriter, req *http.Request) {
// /stats/<podfullname>/<containerName> or /stats/<namespace>/<podfullname>/<uuid>/<containerName>
// /stats/<podfullname>/<containerName> or /stats/<namespace>/<podfullname>/<uid>/<containerName>
components := strings.Split(strings.TrimPrefix(path.Clean(req.URL.Path), "/"), "/")
var stats *info.ContainerInfo
var err error
@@ -333,7 +335,7 @@ func (s *Server) serveStats(w http.ResponseWriter, req *http.Request) {
// TODO(monnand) Implement this
errors.New("pod level status currently unimplemented")
case 3:
// Backward compatibility without uuid information, does not support namespace
// Backward compatibility without uid information, does not support namespace
pod, ok := s.host.GetPodByName(api.NamespaceDefault, components[1])
if !ok {
http.Error(w, "Pod does not exist", http.StatusNotFound)
@@ -346,7 +348,7 @@ func (s *Server) serveStats(w http.ResponseWriter, req *http.Request) {
http.Error(w, "Pod does not exist", http.StatusNotFound)
return
}
stats, err = s.host.GetContainerInfo(GetPodFullName(pod), components[3], components[4], &query)
stats, err = s.host.GetContainerInfo(GetPodFullName(pod), util.UID(components[3]), components[4], &query)
default:
http.Error(w, "unknown resource.", http.StatusNotFound)
return

View File

@@ -29,18 +29,19 @@ import (
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/google/cadvisor/info"
)
type fakeKubelet struct {
podByNameFunc func(namespace, name string) (*api.BoundPod, bool)
infoFunc func(name string) (api.PodInfo, error)
containerInfoFunc func(podFullName, uid, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error)
containerInfoFunc func(podFullName string, uid util.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error)
rootInfoFunc func(query *info.ContainerInfoRequest) (*info.ContainerInfo, error)
machineInfoFunc func() (*info.MachineInfo, error)
boundPodsFunc func() ([]api.BoundPod, error)
logFunc func(w http.ResponseWriter, req *http.Request)
runFunc func(podFullName, uuid, containerName string, cmd []string) ([]byte, error)
runFunc func(podFullName string, uid util.UID, containerName string, cmd []string) ([]byte, error)
containerLogsFunc func(podFullName, containerName, tail string, follow bool, stdout, stderr io.Writer) error
}
@@ -48,12 +49,12 @@ func (fk *fakeKubelet) GetPodByName(namespace, name string) (*api.BoundPod, bool
return fk.podByNameFunc(namespace, name)
}
func (fk *fakeKubelet) GetPodInfo(name, uuid string) (api.PodInfo, error) {
func (fk *fakeKubelet) GetPodInfo(name string, uid util.UID) (api.PodInfo, error) {
return fk.infoFunc(name)
}
func (fk *fakeKubelet) GetContainerInfo(podFullName, uuid, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
return fk.containerInfoFunc(podFullName, uuid, containerName, req)
func (fk *fakeKubelet) GetContainerInfo(podFullName string, uid util.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
return fk.containerInfoFunc(podFullName, uid, containerName, req)
}
func (fk *fakeKubelet) GetRootInfo(req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
@@ -76,8 +77,8 @@ func (fk *fakeKubelet) GetKubeletContainerLogs(podFullName, containerName, tail
return fk.containerLogsFunc(podFullName, containerName, tail, follow, stdout, stderr)
}
func (fk *fakeKubelet) RunInContainer(podFullName, uuid, containerName string, cmd []string) ([]byte, error) {
return fk.runFunc(podFullName, uuid, containerName, cmd)
func (fk *fakeKubelet) RunInContainer(podFullName string, uid util.UID, containerName string, cmd []string) ([]byte, error) {
return fk.runFunc(podFullName, uid, containerName, cmd)
}
type serverTestFramework struct {
@@ -161,7 +162,7 @@ func TestContainerInfo(t *testing.T) {
podID := "somepod"
expectedPodID := "somepod" + ".default.etcd"
expectedContainerName := "goodcontainer"
fw.fakeKubelet.containerInfoFunc = func(podID, uid, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
fw.fakeKubelet.containerInfoFunc = func(podID string, uid util.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
if podID != expectedPodID || containerName != expectedContainerName {
return nil, fmt.Errorf("bad podID or containerName: podID=%v; containerName=%v", podID, containerName)
}
@@ -191,8 +192,8 @@ func TestContainerInfoWithUidNamespace(t *testing.T) {
expectedPodID := "somepod" + "." + expectedNamespace + ".etcd"
expectedContainerName := "goodcontainer"
expectedUid := "9b01b80f-8fb4-11e4-95ab-4200af06647"
fw.fakeKubelet.containerInfoFunc = func(podID, uid, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
if podID != expectedPodID || uid != expectedUid || containerName != expectedContainerName {
fw.fakeKubelet.containerInfoFunc = func(podID string, uid util.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
if podID != expectedPodID || string(uid) != expectedUid || containerName != expectedContainerName {
return nil, fmt.Errorf("bad podID or uid or containerName: podID=%v; uid=%v; containerName=%v", podID, uid, containerName)
}
return expectedInfo, nil
@@ -296,7 +297,7 @@ func TestServeRunInContainer(t *testing.T) {
expectedPodName := podName + "." + podNamespace + ".etcd"
expectedContainerName := "baz"
expectedCommand := "ls -a"
fw.fakeKubelet.runFunc = func(podFullName, uuid, containerName string, cmd []string) ([]byte, error) {
fw.fakeKubelet.runFunc = func(podFullName string, uid util.UID, containerName string, cmd []string) ([]byte, error) {
if podFullName != expectedPodName {
t.Errorf("expected %s, got %s", expectedPodName, podFullName)
}
@@ -328,21 +329,21 @@ func TestServeRunInContainer(t *testing.T) {
}
}
func TestServeRunInContainerWithUUID(t *testing.T) {
func TestServeRunInContainerWithUID(t *testing.T) {
fw := newServerTest()
output := "foo bar"
podNamespace := "other"
podName := "foo"
expectedPodName := podName + "." + podNamespace + ".etcd"
expectedUuid := "7e00838d_-_3523_-_11e4_-_8421_-_42010af0a720"
expectedUID := "7e00838d_-_3523_-_11e4_-_8421_-_42010af0a720"
expectedContainerName := "baz"
expectedCommand := "ls -a"
fw.fakeKubelet.runFunc = func(podFullName, uuid, containerName string, cmd []string) ([]byte, error) {
fw.fakeKubelet.runFunc = func(podFullName string, uid util.UID, 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 string(uid) != expectedUID {
t.Errorf("expected %s, got %s", expectedUID, uid)
}
if containerName != expectedContainerName {
t.Errorf("expected %s, got %s", expectedContainerName, containerName)
@@ -354,7 +355,7 @@ func TestServeRunInContainerWithUUID(t *testing.T) {
return []byte(output), nil
}
resp, err := http.Get(fw.testHTTPServer.URL + "/run/" + podNamespace + "/" + podName + "/" + expectedUuid + "/" + expectedContainerName + "?cmd=ls%20-a")
resp, err := http.Get(fw.testHTTPServer.URL + "/run/" + podNamespace + "/" + podName + "/" + expectedUID + "/" + expectedContainerName + "?cmd=ls%20-a")
if err != nil {
t.Fatalf("Got error GETing: %v", err)