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
commit 8a764c02d5
31 changed files with 182 additions and 170 deletions

View File

@ -312,7 +312,7 @@ func TestKubeletSendsEvent(c *client.Client) bool {
labels.Everything(),
labels.Set{
"involvedObject.kind": "Pod",
"involvedObject.uid": podWithUid.UID,
"involvedObject.uid": string(podWithUid.UID),
"involvedObject.namespace": api.NamespaceDefault,
"source": "scheduler",
}.AsSelector(),
@ -331,7 +331,7 @@ func TestKubeletSendsEvent(c *client.Client) bool {
events, err = c.Events(api.NamespaceDefault).List(
labels.Everything(),
labels.Set{
"involvedObject.uid": podWithUid.UID,
"involvedObject.uid": string(podWithUid.UID),
"involvedObject.kind": "BoundPod",
"involvedObject.namespace": api.NamespaceDefault,
"source": "kubelet",

View File

@ -23,7 +23,7 @@ import (
// FillObjectMetaSystemFields populates fields that are managed by the system on ObjectMeta.
func FillObjectMetaSystemFields(ctx Context, meta *ObjectMeta) {
meta.CreationTimestamp = util.Now()
meta.UID = util.NewUUID().String()
meta.UID = util.NewUUID()
}
// HasObjectMetaSystemFieldValues returns true if fields that are managed by the system on ObjectMeta have values.

View File

@ -18,6 +18,7 @@ package meta
import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
// VersionInterfaces contains the interfaces one should use for dealing with types of a particular version.
@ -36,8 +37,8 @@ type Interface interface {
SetNamespace(namespace string)
Name() string
SetName(name string)
UID() string
SetUID(uid string)
UID() util.UID
SetUID(uid util.UID)
APIVersion() string
SetAPIVersion(version string)
Kind() string
@ -71,8 +72,8 @@ type MetadataAccessor interface {
Name(obj runtime.Object) (string, error)
SetName(obj runtime.Object, name string) error
UID(obj runtime.Object) (string, error)
SetUID(obj runtime.Object, uid string) error
UID(obj runtime.Object) (util.UID, error)
SetUID(obj runtime.Object, uid util.UID) error
SelfLink(obj runtime.Object) (string, error)
SetSelfLink(obj runtime.Object, selfLink string) error

View File

@ -22,6 +22,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
// Accessor takes an arbitary object pointer and returns meta.Interface.
@ -151,7 +152,7 @@ func (resourceAccessor) SetName(obj runtime.Object, name string) error {
return nil
}
func (resourceAccessor) UID(obj runtime.Object) (string, error) {
func (resourceAccessor) UID(obj runtime.Object) (util.UID, error) {
accessor, err := Accessor(obj)
if err != nil {
return "", err
@ -159,7 +160,7 @@ func (resourceAccessor) UID(obj runtime.Object) (string, error) {
return accessor.UID(), nil
}
func (resourceAccessor) SetUID(obj runtime.Object, uid string) error {
func (resourceAccessor) SetUID(obj runtime.Object, uid util.UID) error {
accessor, err := Accessor(obj)
if err != nil {
return err
@ -241,7 +242,7 @@ func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) e
type genericAccessor struct {
namespace *string
name *string
uid *string
uid *util.UID
apiVersion *string
kind *string
resourceVersion *string
@ -278,14 +279,14 @@ func (a genericAccessor) SetName(name string) {
*a.name = name
}
func (a genericAccessor) UID() string {
func (a genericAccessor) UID() util.UID {
if a.uid == nil {
return ""
}
return *a.uid
}
func (a genericAccessor) SetUID(uid string) {
func (a genericAccessor) SetUID(uid util.UID) {
if a.uid == nil {
return
}

View File

@ -63,7 +63,7 @@ func TestGenericTypeMeta(t *testing.T) {
if e, a := "foo", accessor.Name(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "uid", accessor.UID(); e != a {
if e, a := "uid", string(accessor.UID()); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "a", accessor.APIVersion(); e != a {
@ -162,7 +162,7 @@ func TestGenericTypeMetaAccessor(t *testing.T) {
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if e, a := "uid", uid; e != a {
if e, a := "uid", string(uid); e != a {
t.Errorf("expected %v, got %v", e, a)
}
apiVersion, err := accessor.APIVersion(j)
@ -311,7 +311,7 @@ func TestGenericObjectMeta(t *testing.T) {
if e, a := "foo", accessor.Name(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "uid", accessor.UID(); e != a {
if e, a := "uid", string(accessor.UID()); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "a", accessor.APIVersion(); e != a {
@ -403,7 +403,7 @@ func TestGenericListMeta(t *testing.T) {
if e, a := "", accessor.Name(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "", accessor.UID(); e != a {
if e, a := "", string(accessor.UID()); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "a", accessor.APIVersion(); e != a {

View File

@ -93,7 +93,7 @@ type ObjectMeta struct {
// UID is the unique in time and space value for this object. It is typically generated by
// the server on successful creation of a resource and is not allowed to change on PUT
// operations.
UID string `json:"uid,omitempty"`
UID util.UID `json:"uid,omitempty"`
// An opaque value that represents the version of this resource. May be used for optimistic
// concurrency, change detection, and the watch operation on a resource or set of resources.
@ -1004,12 +1004,12 @@ type OperationList struct {
// ObjectReference contains enough information to let you inspect or modify the referred object.
type ObjectReference struct {
Kind string `json:"kind,omitempty"`
Namespace string `json:"namespace,omitempty"`
Name string `json:"name,omitempty"`
UID string `json:"uid,omitempty"`
APIVersion string `json:"apiVersion,omitempty"`
ResourceVersion string `json:"resourceVersion,omitempty"`
Kind string `json:"kind,omitempty"`
Namespace string `json:"namespace,omitempty"`
Name string `json:"name,omitempty"`
UID util.UID `json:"uid,omitempty"`
APIVersion string `json:"apiVersion,omitempty"`
ResourceVersion string `json:"resourceVersion,omitempty"`
// Optional. If referring to a piece of an object instead of an entire object, this string
// should contain information to identify the sub-object. For example, if the object
@ -1085,7 +1085,7 @@ type ContainerManifest struct {
// 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 `json:"uuid,omitempty"`
UUID util.UID `json:"uuid,omitempty"`
Volumes []Volume `json:"volumes"`
Containers []Container `json:"containers"`
RestartPolicy RestartPolicy `json:"restartPolicy,omitempty"`

View File

@ -56,7 +56,7 @@ type ContainerManifest struct {
// 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 `json:"uuid,omitempty" description:"manifest UUID"`
UUID util.UID `json:"uuid,omitempty" description:"manifest UUID"`
Volumes []Volume `json:"volumes" description:"list of volumes that can be mounted by containers belonging to the pod"`
Containers []Container `json:"containers" description:"list of containers belonging to the pod"`
RestartPolicy RestartPolicy `json:"restartPolicy,omitempty" description:"restart policy for all containers within the pod; one of RestartPolicyAlways, RestartPolicyOnFailure, RestartPolicyNever"`
@ -297,7 +297,7 @@ type Lifecycle struct {
type TypeMeta struct {
Kind string `json:"kind,omitempty" description:"kind of object, in CamelCase"`
ID string `json:"id,omitempty" description:"name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs"`
UID string `json:"uid,omitempty" description:"UUID assigned by the system upon creation, unique across space and time"`
UID util.UID `json:"uid,omitempty" description:"UUID assigned by the system upon creation, unique across space and time"`
CreationTimestamp util.Time `json:"creationTimestamp,omitempty" description:"RFC 3339 date and time at which the object was created; recorded by the system; null for lists"`
SelfLink string `json:"selfLink,omitempty" description:"URL for the object"`
ResourceVersion uint64 `json:"resourceVersion,omitempty" description:"string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server"`
@ -776,12 +776,12 @@ type ServerOpList struct {
// ObjectReference contains enough information to let you inspect or modify the referred object.
type ObjectReference struct {
Kind string `json:"kind,omitempty" description:"kind of the referent"`
Namespace string `json:"namespace,omitempty" description:"namespace of the referent"`
ID string `json:"name,omitempty" description:"id of the referent"`
UID string `json:"uid,omitempty" description:"uid of the referent"`
APIVersion string `json:"apiVersion,omitempty" description:"API version of the referent"`
ResourceVersion string `json:"resourceVersion,omitempty" description:"specific resourceVersion to which this reference is made, if any"`
Kind string `json:"kind,omitempty" description:"kind of the referent"`
Namespace string `json:"namespace,omitempty" description:"namespace of the referent"`
ID string `json:"name,omitempty" description:"id of the referent"`
UID util.UID `json:"uid,omitempty" description:"uid of the referent"`
APIVersion string `json:"apiVersion,omitempty" description:"API version of the referent"`
ResourceVersion string `json:"resourceVersion,omitempty" description:"specific resourceVersion to which this reference is made, if any"`
// Optional. If referring to a piece of an object instead of an entire object, this string
// should contain information to identify the sub-object. For example, if the object

View File

@ -260,7 +260,7 @@ type Lifecycle struct {
type TypeMeta struct {
Kind string `json:"kind,omitempty" description:"kind of object, in CamelCase"`
ID string `json:"id,omitempty" description:"name of the object; must be a DNS_SUBDOMAIN and unique among all objects of the same kind within the same namespace; used in resource URLs"`
UID string `json:"uid,omitempty" description:"UUID assigned by the system upon creation, unique across space and time"`
UID util.UID `json:"uid,omitempty" description:"UUID assigned by the system upon creation, unique across space and time"`
CreationTimestamp util.Time `json:"creationTimestamp,omitempty" description:"RFC 3339 date and time at which the object was created; recorded by the system; null for lists"`
SelfLink string `json:"selfLink,omitempty" description:"URL for the object"`
ResourceVersion uint64 `json:"resourceVersion,omitempty" description:"string that identifies the internal version of this object that can be used by clients to determine when objects have changed; value must be treated as opaque by clients and passed unmodified back to the server"`
@ -749,12 +749,12 @@ type ServerOpList struct {
// ObjectReference contains enough information to let you inspect or modify the referred object.
type ObjectReference struct {
Kind string `json:"kind,omitempty" description:"kind of the referent"`
Namespace string `json:"namespace,omitempty" description:"namespace of the referent"`
ID string `json:"name,omitempty" description:"id of the referent"`
UID string `json:"uid,omitempty" description:"uid of the referent"`
APIVersion string `json:"apiVersion,omitempty" description:"API version of the referent"`
ResourceVersion string `json:"resourceVersion,omitempty" description:"specific resourceVersion to which this reference is made, if any"`
Kind string `json:"kind,omitempty" description:"kind of the referent"`
Namespace string `json:"namespace,omitempty" description:"namespace of the referent"`
ID string `json:"name,omitempty" description:"id of the referent"`
UID util.UID `json:"uid,omitempty" description:"uid of the referent"`
APIVersion string `json:"apiVersion,omitempty" description:"API version of the referent"`
ResourceVersion string `json:"resourceVersion,omitempty" description:"specific resourceVersion to which this reference is made, if any"`
// Optional. If referring to a piece of an object instead of an entire object, this string
// should contain information to identify the sub-object. For example, if the object
@ -824,7 +824,7 @@ type ContainerManifest struct {
// 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 `json:"uuid,omitempty" description:"manifest UUID"`
UUID util.UID `json:"uuid,omitempty" description:"manifest UUID"`
Volumes []Volume `json:"volumes" description:"list of volumes that can be mounted by containers belonging to the pod"`
Containers []Container `json:"containers" description:"list of containers belonging to the pod"`
RestartPolicy RestartPolicy `json:"restartPolicy,omitempty" description:"restart policy for all containers within the pod; one of RestartPolicyAlways, RestartPolicyOnFailure, RestartPolicyNever"`

View File

@ -93,7 +93,7 @@ type ObjectMeta struct {
// UID is the unique in time and space value for this object. It is typically generated by
// the server on successful creation of a resource and is not allowed to change on PUT
// operations.
UID string `json:"uid,omitempty"`
UID util.UID `json:"uid,omitempty"`
// An opaque value that represents the version of this resource. May be used for optimistic
// concurrency, change detection, and the watch operation on a resource or set of resources.
@ -138,7 +138,7 @@ const (
// // 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 `json:"uuid,omitempty"`
// UUID util.UID `json:"uuid,omitempty"`
// Volumes []Volume `json:"volumes"`
// Containers []Container `json:"containers"`
// RestartPolicy RestartPolicy `json:"restartPolicy,omitempty"`
@ -995,12 +995,12 @@ type OperationList struct {
// ObjectReference contains enough information to let you inspect or modify the referred object.
type ObjectReference struct {
Kind string `json:"kind,omitempty"`
Namespace string `json:"namespace,omitempty"`
Name string `json:"name,omitempty"`
UID string `json:"uid,omitempty"`
APIVersion string `json:"apiVersion,omitempty"`
ResourceVersion string `json:"resourceVersion,omitempty"`
Kind string `json:"kind,omitempty"`
Namespace string `json:"namespace,omitempty"`
Name string `json:"name,omitempty"`
UID util.UID `json:"uid,omitempty"`
APIVersion string `json:"apiVersion,omitempty"`
ResourceVersion string `json:"resourceVersion,omitempty"`
// Optional. If referring to a piece of an object instead of an entire object, this string
// should contain information to identify the sub-object. For example, if the object

View File

@ -136,7 +136,7 @@ func (e *events) Search(objOrRef runtime.Object) (*api.EventList, error) {
fields["involvedObject.name"] = ref.Name
}
if ref.UID != "" {
fields["involvedObject.uid"] = ref.UID
fields["involvedObject.uid"] = string(ref.UID)
}
return e.List(labels.Everything(), fields.AsSelector())
}

View File

@ -21,13 +21,14 @@ import (
"strings"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/golang/glog"
)
const defaultHealthyOutput = "ok"
type CommandRunner interface {
RunInContainer(podFullName, uuid, containerName string, cmd []string) ([]byte, error)
RunInContainer(podFullName string, uid util.UID, containerName string, cmd []string) ([]byte, error)
}
type ExecHealthChecker struct {
@ -38,11 +39,11 @@ func NewExecHealthChecker(runner CommandRunner) HealthChecker {
return &ExecHealthChecker{runner}
}
func (e *ExecHealthChecker) HealthCheck(podFullName, podUUID string, status api.PodStatus, container api.Container) (Status, error) {
func (e *ExecHealthChecker) HealthCheck(podFullName string, podUID util.UID, status api.PodStatus, container api.Container) (Status, error) {
if container.LivenessProbe.Exec == nil {
return Unknown, fmt.Errorf("missing exec parameters")
}
data, err := e.runner.RunInContainer(podFullName, podUUID, container.Name, container.LivenessProbe.Exec.Command)
data, err := e.runner.RunInContainer(podFullName, podUID, container.Name, container.LivenessProbe.Exec.Command)
glog.V(1).Infof("container %s health check response: %s", podFullName, string(data))
if err != nil {
return Unknown, err

View File

@ -22,6 +22,7 @@ import (
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
type FakeExec struct {
@ -30,7 +31,7 @@ type FakeExec struct {
err error
}
func (f *FakeExec) RunInContainer(podFullName, uuid, container string, cmd []string) ([]byte, error) {
func (f *FakeExec) RunInContainer(podFullName string, uid util.UID, container string, cmd []string) ([]byte, error) {
f.cmd = cmd
return f.out, f.err
}

View File

@ -20,6 +20,7 @@ import (
"sync"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/golang/glog"
)
@ -35,7 +36,7 @@ const (
// HealthChecker defines an abstract interface for checking container health.
type HealthChecker interface {
HealthCheck(podFullName, podUUID string, status api.PodStatus, container api.Container) (Status, error)
HealthCheck(podFullName string, podUID util.UID, status api.PodStatus, container api.Container) (Status, error)
CanCheck(probe *api.LivenessProbe) bool
}
@ -78,13 +79,13 @@ func (m *muxHealthChecker) findCheckerFor(probe *api.LivenessProbe) HealthChecke
// HealthCheck delegates the health-checking of the container to one of the bundled implementations.
// If there is no health checker that can check container it returns Unknown, nil.
func (m *muxHealthChecker) HealthCheck(podFullName, podUUID string, status api.PodStatus, container api.Container) (Status, error) {
func (m *muxHealthChecker) HealthCheck(podFullName string, podUID util.UID, status api.PodStatus, container api.Container) (Status, error) {
checker := m.findCheckerFor(container.LivenessProbe)
if checker == nil {
glog.Warningf("Failed to find health checker for %s %+v", container.Name, container.LivenessProbe)
return Unknown, nil
}
return checker.HealthCheck(podFullName, podUUID, status, container)
return checker.HealthCheck(podFullName, podUID, status, container)
}
func (m *muxHealthChecker) CanCheck(probe *api.LivenessProbe) bool {

View File

@ -105,7 +105,7 @@ func DoHTTPCheck(url string, client HTTPGetInterface) (Status, error) {
}
// HealthCheck checks if the container is healthy by trying sending HTTP Get requests to the container.
func (h *HTTPHealthChecker) HealthCheck(podFullName, podUUID string, status api.PodStatus, container api.Container) (Status, error) {
func (h *HTTPHealthChecker) HealthCheck(podFullName string, podUID util.UID, status api.PodStatus, container api.Container) (Status, error) {
host, port, path, err := getURLParts(status, container)
if err != nil {
return Unknown, err

View File

@ -74,7 +74,7 @@ func DoTCPCheck(addr string) (Status, error) {
return Healthy, nil
}
func (t *TCPHealthChecker) HealthCheck(podFullName, podUUID string, status api.PodStatus, container api.Container) (Status, error) {
func (t *TCPHealthChecker) HealthCheck(podFullName string, podUID util.UID, status api.PodStatus, container api.Container) (Status, error) {
host, port, err := getTCPAddrParts(status, container)
if err != nil {
return Unknown, err

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)

View File

@ -63,7 +63,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE
}
if len(controller.Name) == 0 {
controller.Name = util.NewUUID().String()
controller.Name = string(util.NewUUID())
}
if errs := validation.ValidateReplicationController(controller); len(errs) > 0 {
return nil, errors.NewInvalid("replicationController", controller.Name, errs)

View File

@ -102,7 +102,7 @@ func (rs *REST) getAttrs(obj runtime.Object) (objLabels, objFields labels.Set, e
"involvedObject.kind": event.InvolvedObject.Kind,
"involvedObject.namespace": event.InvolvedObject.Namespace,
"involvedObject.name": event.InvolvedObject.Name,
"involvedObject.uid": event.InvolvedObject.UID,
"involvedObject.uid": string(event.InvolvedObject.UID),
"involvedObject.apiVersion": event.InvolvedObject.APIVersion,
"involvedObject.resourceVersion": fmt.Sprintf("%s", event.InvolvedObject.ResourceVersion),
"involvedObject.fieldPath": event.InvolvedObject.FieldPath,

View File

@ -62,7 +62,7 @@ func (rs *REST) Create(ctx api.Context, obj runtime.Object) (<-chan apiserver.RE
if len(pod.Name) == 0 {
// TODO properly handle auto-generated names.
// See https://github.com/GoogleCloudPlatform/kubernetes/issues/148 170 & 1135
pod.Name = pod.UID
pod.Name = string(pod.UID)
}
if errs := validation.ValidatePod(pod); len(errs) > 0 {
return nil, errors.NewInvalid("pod", pod.Name, errs)

View File

@ -23,9 +23,10 @@ import (
"code.google.com/p/go-uuid/uuid"
)
type UUID interface {
String() string
}
// UID is a type that holds unique ID values, including UUIDs. Because we
// don't ONLY use UUIDs, this is an alias to string. Being a type captures
// intent and helps make sure that UIDs and names do not get conflated.
type UID string
var uuidLock sync.Mutex
@ -35,12 +36,12 @@ var uuidLock sync.Mutex
* Blocks in a go routine, so that the caller doesn't have to wait.
* TODO: save old unused UUIDs so that no one has to block.
*/
func NewUUID() UUID {
func NewUUID() UID {
uuidLock.Lock()
result := uuid.NewUUID()
go func() {
time.Sleep(200 * time.Nanosecond)
uuidLock.Unlock()
}()
return result
return UID(result.String())
}