@@ -24,6 +24,20 @@ import (
2424 "k8s.io/kubernetes/pkg/labels"
2525)
2626
27+ // DefaultNamespace is the Kubernetes default namespace.
28+ const DefaultNamespace = "default"
29+
30+ var (
31+ // EnvNamespace is the environment variable this looks for to get the namespace.
32+ //
33+ // You can set this via the Downward API.
34+ EnvNamespace = "POD_NAMESPACE"
35+ // EnvName is the environment variable this looks for to get the pod name.
36+ //
37+ // You can set this via the Downward API.
38+ EnvName = "POD_NAME"
39+ )
40+
2741type Me struct {
2842 ApiServer , Name string
2943 IP , NodeIP , Namespace , SelfLink , UID string
@@ -42,7 +56,7 @@ func FromEnv() (*Me, error) {
4256
4357 host := os .Getenv ("KUBERNETES_SERVICE_HOST" )
4458 port := os .Getenv ("KUBERNETES_SERVICE_PORT" )
45- name := os . Getenv ( "HOSTNAME" )
59+ name := NameFromEnv ( )
4660
4761 // FIXME: Better way? Probably scanning secrets for
4862 // an SSL cert would help?
@@ -53,10 +67,7 @@ func FromEnv() (*Me, error) {
5367 me := & Me {
5468 ApiServer : url ,
5569 Name : name ,
56-
57- // FIXME: This is a chicken-and-egg problem. We need the namespace
58- // to get pod info, and we can only get info from the pod.
59- Namespace : "default" ,
70+ Namespace : NamespaceFromEnv (),
6071 }
6172
6273 client , err := k8s .PodClient ()
@@ -75,6 +86,27 @@ func (me *Me) Client() *unversioned.Client {
7586 return me .c
7687}
7788
89+ // NameFromEnv gets the pod name from either the Downward API or the hostname.
90+ func NameFromEnv () string {
91+ n := os .Getenv (EnvName )
92+ if n == "" {
93+ return os .Getenv ("HOSTNAME" )
94+ }
95+ return n
96+ }
97+
98+ //NamespaceFromEnv attempts to get the namespace from the downward API.
99+ //
100+ // If EnvNamespace is not set, or if the name is not recovered from the
101+ // environment, then the DefaultNamespace is used.
102+ func NamespaceFromEnv () string {
103+ ns := os .Getenv (EnvNamespace )
104+ if ns == "" {
105+ return DefaultNamespace
106+ }
107+ return ns
108+ }
109+
78110// ShuntEnv puts the Me object into the environment.
79111//
80112// The properties of Me are placed into the environment according to the
@@ -108,7 +140,7 @@ func (me *Me) ShuntEnv() {
108140}
109141
110142func (me * Me ) init () error {
111- p , n , err := me .findPodInNamespaces ()
143+ p , n , err := me .loadPod ()
112144 if err != nil {
113145 return err
114146 }
@@ -125,7 +157,7 @@ func (me *Me) init() error {
125157 // PodIP, even though the pod is issued an IP. We need to figure out why,
126158 // and if this is an expected case. In the meantime, we get the IP by
127159 // scanning interfaces.
128- if me .IP == "" {
160+ if strings . TrimSpace ( me .IP ) == "" {
129161 // We swallow the error, letting me.IP set the interface address to
130162 // 0.0.0.0.
131163 me .IP , _ = MyIP ()
@@ -134,17 +166,22 @@ func (me *Me) init() error {
134166 return nil
135167}
136168
169+ // loadPod loads a pod using the downward API.
170+ func (me * Me ) loadPod () (* api.Pod , string , error ) {
171+ ns := NamespaceFromEnv ()
172+ p , err := me .c .Pods (ns ).Get (me .Name )
173+ return p , ns , err
174+ }
175+
137176// findPodInNamespaces searches relevant namespaces for this pod.
138177//
139178// It returns a PodInterface for working with the pod, a namespace name as a
140179// string, and an error if something goes wrong.
141180//
142- // The search pattern is to look for namespaces that have the "deis" name in
143- // their labels, and then to fall back to default. We don't look at all
144- // namespaces.
145- func (me * Me ) findPodInNamespaces () (* api.Pod , string , error ) {
181+ // The selector must be a label selector.
182+ func (me * Me ) findPodInNamespaces (selector string ) (* api.Pod , string , error ) {
146183 // Get the deis namespace. If it does not exist, get the default namespce.
147- s , err := labels .Parse ("name=deis" )
184+ s , err := labels .Parse (selector )
148185 if err == nil {
149186 ns , err := me .c .Namespaces ().List (s , nil )
150187 if err != nil {
0 commit comments