From e86d4cd3c6a3a5474d27b79f85479b075a19609b Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Wed, 14 Jan 2015 13:53:43 -0800 Subject: [PATCH] Use a strong type for UID fields --- cmd/e2e/e2e.go | 4 +- pkg/api/meta.go | 2 +- pkg/api/meta/interfaces.go | 9 ++- pkg/api/meta/meta.go | 11 +-- pkg/api/meta/meta_test.go | 8 +- pkg/api/types.go | 16 ++-- pkg/api/v1beta1/types.go | 16 ++-- pkg/api/v1beta2/types.go | 16 ++-- pkg/api/v1beta3/types.go | 16 ++-- pkg/client/events.go | 2 +- pkg/health/exec.go | 7 +- pkg/health/exec_test.go | 3 +- pkg/health/health.go | 7 +- pkg/health/http.go | 2 +- pkg/health/tcp.go | 2 +- pkg/kubelet/cadvisor.go | 5 +- pkg/kubelet/config/config_test.go | 3 +- pkg/kubelet/config/file.go | 2 +- pkg/kubelet/config/file_test.go | 5 +- pkg/kubelet/config/http.go | 2 +- pkg/kubelet/dockertools/docker.go | 20 ++--- pkg/kubelet/dockertools/docker_test.go | 6 +- pkg/kubelet/handlers.go | 8 +- pkg/kubelet/kubelet.go | 102 ++++++++++++------------- pkg/kubelet/kubelet_test.go | 2 +- pkg/kubelet/server.go | 24 +++--- pkg/kubelet/server_test.go | 35 ++++----- pkg/registry/controller/rest.go | 2 +- pkg/registry/event/rest.go | 2 +- pkg/registry/pod/rest.go | 2 +- pkg/util/uuid.go | 11 +-- 31 files changed, 182 insertions(+), 170 deletions(-) diff --git a/cmd/e2e/e2e.go b/cmd/e2e/e2e.go index 1658afc3045..6fccb351cc2 100644 --- a/cmd/e2e/e2e.go +++ b/cmd/e2e/e2e.go @@ -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", diff --git a/pkg/api/meta.go b/pkg/api/meta.go index 1b7da4d2674..4bdfcdacd73 100644 --- a/pkg/api/meta.go +++ b/pkg/api/meta.go @@ -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. diff --git a/pkg/api/meta/interfaces.go b/pkg/api/meta/interfaces.go index 9ae4a001bb2..f5f6a0fe888 100644 --- a/pkg/api/meta/interfaces.go +++ b/pkg/api/meta/interfaces.go @@ -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 diff --git a/pkg/api/meta/meta.go b/pkg/api/meta/meta.go index 54dcf5679fc..b9800e2d7d7 100644 --- a/pkg/api/meta/meta.go +++ b/pkg/api/meta/meta.go @@ -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 } diff --git a/pkg/api/meta/meta_test.go b/pkg/api/meta/meta_test.go index 2309c11f365..d8b3f0fe82b 100644 --- a/pkg/api/meta/meta_test.go +++ b/pkg/api/meta/meta_test.go @@ -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 { diff --git a/pkg/api/types.go b/pkg/api/types.go index b30de6c32c5..c3150b6a36b 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -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"` diff --git a/pkg/api/v1beta1/types.go b/pkg/api/v1beta1/types.go index 77e19b6b9b5..099ae1885ae 100644 --- a/pkg/api/v1beta1/types.go +++ b/pkg/api/v1beta1/types.go @@ -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 diff --git a/pkg/api/v1beta2/types.go b/pkg/api/v1beta2/types.go index e8c26dab202..7fe85ece288 100644 --- a/pkg/api/v1beta2/types.go +++ b/pkg/api/v1beta2/types.go @@ -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"` diff --git a/pkg/api/v1beta3/types.go b/pkg/api/v1beta3/types.go index cca9fed96d3..e327473c3b9 100644 --- a/pkg/api/v1beta3/types.go +++ b/pkg/api/v1beta3/types.go @@ -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 diff --git a/pkg/client/events.go b/pkg/client/events.go index 11464056adf..6a68b7f6ceb 100644 --- a/pkg/client/events.go +++ b/pkg/client/events.go @@ -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()) } diff --git a/pkg/health/exec.go b/pkg/health/exec.go index 579875ac970..ad06cffe120 100644 --- a/pkg/health/exec.go +++ b/pkg/health/exec.go @@ -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 diff --git a/pkg/health/exec_test.go b/pkg/health/exec_test.go index 462379a741c..0a7f2be8a5b 100644 --- a/pkg/health/exec_test.go +++ b/pkg/health/exec_test.go @@ -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 } diff --git a/pkg/health/health.go b/pkg/health/health.go index 61260b30cee..caa694543cf 100644 --- a/pkg/health/health.go +++ b/pkg/health/health.go @@ -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 { diff --git a/pkg/health/http.go b/pkg/health/http.go index 3e7998132c1..67ac1c707de 100644 --- a/pkg/health/http.go +++ b/pkg/health/http.go @@ -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 diff --git a/pkg/health/tcp.go b/pkg/health/tcp.go index 4d0cdc9305f..4eec9f19001 100644 --- a/pkg/health/tcp.go +++ b/pkg/health/tcp.go @@ -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 diff --git a/pkg/kubelet/cadvisor.go b/pkg/kubelet/cadvisor.go index fdabb7f3c0d..ae24ea2592e 100644 --- a/pkg/kubelet/cadvisor.go +++ b/pkg/kubelet/cadvisor.go @@ -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") } diff --git a/pkg/kubelet/config/config_test.go b/pkg/kubelet/config/config_test.go index 29aee090eca..5f375cca61e 100644 --- a/pkg/kubelet/config/config_test.go +++ b/pkg/kubelet/config/config_test.go @@ -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}, diff --git a/pkg/kubelet/config/file.go b/pkg/kubelet/config/file.go index f1300d9d680..00c2f3def38 100644 --- a/pkg/kubelet/config/file.go +++ b/pkg/kubelet/config/file.go @@ -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 { diff --git a/pkg/kubelet/config/file_test.go b/pkg/kubelet/config/file_test.go index 0c8874b938c..0b3a5b1ada3 100644 --- a/pkg/kubelet/config/file_test.go +++ b/pkg/kubelet/config/file_test.go @@ -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{ diff --git a/pkg/kubelet/config/http.go b/pkg/kubelet/config/http.go index 9703aa22d40..c69989ce446 100644 --- a/pkg/kubelet/config/http.go +++ b/pkg/kubelet/config/http.go @@ -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 { diff --git a/pkg/kubelet/dockertools/docker.go b/pkg/kubelet/dockertools/docker.go index ac98be6e2bb..136a10f76a5 100644 --- a/pkg/kubelet/dockertools/docker.go +++ b/pkg/kubelet/dockertools/docker.go @@ -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 } diff --git a/pkg/kubelet/dockertools/docker_test.go b/pkg/kubelet/dockertools/docker_test.go index 5a47ec3083c..539f2f7c1b2 100644 --- a/pkg/kubelet/dockertools/docker_test.go +++ b/pkg/kubelet/dockertools/docker_test.go @@ -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) } } diff --git a/pkg/kubelet/handlers.go b/pkg/kubelet/handlers.go index 2b02e5960be..f8f8e3f07d1 100644 --- a/pkg/kubelet/handlers.go +++ b/pkg/kubelet/handlers.go @@ -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 diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index a65fb55045c..50e0a88ce66 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -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.") diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index e7babf7fd3a..ea6afc66654 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -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 } diff --git a/pkg/kubelet/server.go b/pkg/kubelet/server.go index 60ee5e0d0b9..d73026de599 100644 --- a/pkg/kubelet/server.go +++ b/pkg/kubelet/server.go @@ -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// or /stats//// + // /stats// or /stats//// 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 diff --git a/pkg/kubelet/server_test.go b/pkg/kubelet/server_test.go index 2f04fc5ab69..f190c4ba0ed 100644 --- a/pkg/kubelet/server_test.go +++ b/pkg/kubelet/server_test.go @@ -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) diff --git a/pkg/registry/controller/rest.go b/pkg/registry/controller/rest.go index 0a38fef53d0..350985f1f2a 100644 --- a/pkg/registry/controller/rest.go +++ b/pkg/registry/controller/rest.go @@ -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) diff --git a/pkg/registry/event/rest.go b/pkg/registry/event/rest.go index 8432c09c3d0..e2e44c7b6e0 100644 --- a/pkg/registry/event/rest.go +++ b/pkg/registry/event/rest.go @@ -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, diff --git a/pkg/registry/pod/rest.go b/pkg/registry/pod/rest.go index 99bc58ff4b0..d6a3f47145e 100644 --- a/pkg/registry/pod/rest.go +++ b/pkg/registry/pod/rest.go @@ -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) diff --git a/pkg/util/uuid.go b/pkg/util/uuid.go index bfd01b22ba4..542118d2746 100644 --- a/pkg/util/uuid.go +++ b/pkg/util/uuid.go @@ -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()) }