diff --git a/pkg/cloudprovider/cloud.go b/pkg/cloudprovider/cloud.go index 1cf38f49ebc..ca45e96a85a 100644 --- a/pkg/cloudprovider/cloud.go +++ b/pkg/cloudprovider/cloud.go @@ -16,10 +16,16 @@ limitations under the License. package cloudprovider +import ( + "net" +) + // CloudInterface is an abstract, pluggable interface for cloud providers type Interface interface { // TCPLoadBalancer returns a balancer interface, or nil if none is supported. Returns an error if one occurs. TCPLoadBalancer() (TCPLoadBalancer, error) + // Instances returns an instances interface, or nil if none is supported. Returns an error if one occurs. + Instances() (Instances, error) } type TCPLoadBalancer interface { @@ -29,3 +35,7 @@ type TCPLoadBalancer interface { UpdateTCPLoadBalancer(name, region string, hosts []string) error DeleteTCPLoadBalancer(name, region string) error } + +type Instances interface { + IPAddress(name string) (net.IP, error) +} diff --git a/pkg/cloudprovider/gce.go b/pkg/cloudprovider/gce.go index ecc4e9c24c0..78e1bbc9379 100644 --- a/pkg/cloudprovider/gce.go +++ b/pkg/cloudprovider/gce.go @@ -19,6 +19,7 @@ package cloudprovider import ( "fmt" "io/ioutil" + "net" "net/http" "strconv" "strings" @@ -82,6 +83,10 @@ func (gce *GCECloud) TCPLoadBalancer() (TCPLoadBalancer, error) { return gce, nil } +func (gce *GCECloud) Instances() (Instances, error) { + return gce, nil +} + func makeHostLink(projectID, zone, host string) string { ix := strings.Index(host, ".") if ix != -1 { @@ -162,3 +167,15 @@ func (gce *GCECloud) DeleteTCPLoadBalancer(name, region string) error { _, err = gce.service.TargetPools.Delete(gce.projectID, region, name).Do() return err } + +func (gce *GCECloud) IPAddress(instance string) (net.IP, error) { + res, err := gce.service.Instances.Get(gce.projectID, gce.zone, instance).Do() + if err != nil { + return nil, err + } + ip := net.ParseIP(res.NetworkInterfaces[0].AccessConfigs[0].NatIP) + if ip == nil { + return nil, fmt.Errorf("Invalid network IP: %s", res.NetworkInterfaces[0].AccessConfigs[0].NatIP) + } + return ip, nil +} diff --git a/pkg/registry/pod_registry.go b/pkg/registry/pod_registry.go index c57a7c7f725..2b7f3fede3b 100644 --- a/pkg/registry/pod_registry.go +++ b/pkg/registry/pod_registry.go @@ -18,10 +18,14 @@ package registry import ( "encoding/json" "fmt" + "log" + "net" + "strings" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver" "github.com/GoogleCloudPlatform/kubernetes/pkg/client" + "github.com/GoogleCloudPlatform/kubernetes/pkg/cloudprovider" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" ) @@ -30,13 +34,15 @@ type PodRegistryStorage struct { registry PodRegistry containerInfo client.ContainerInfo scheduler Scheduler + cloud cloudprovider.Interface } -func MakePodRegistryStorage(registry PodRegistry, containerInfo client.ContainerInfo, scheduler Scheduler) apiserver.RESTStorage { +func MakePodRegistryStorage(registry PodRegistry, containerInfo client.ContainerInfo, scheduler Scheduler, cloud cloudprovider.Interface) apiserver.RESTStorage { return &PodRegistryStorage{ registry: registry, containerInfo: containerInfo, scheduler: scheduler, + cloud: cloud, } } @@ -63,6 +69,31 @@ func makePodStatus(info interface{}) string { return "Pending" } +func getInstanceIP(cloud cloudprovider.Interface, host string) string { + if cloud == nil { + return "" + } + instances, err := cloud.Instances() + if instances == nil { + return "" + } + if err != nil { + log.Printf("Error getting instances: %#v", err) + return "" + } + ix := strings.Index(host, ".") + if ix != -1 { + host = host[:ix] + } + var addr net.IP + addr, err = instances.IPAddress(host) + if err != nil { + log.Printf("Error getting instance IP: %#v", err) + return "" + } + return addr.String() +} + func (storage *PodRegistryStorage) Get(id string) (interface{}, error) { pod, err := storage.registry.GetPod(id) if err != nil { @@ -74,6 +105,8 @@ func (storage *PodRegistryStorage) Get(id string) (interface{}, error) { } pod.CurrentState.Info = info pod.CurrentState.Status = makePodStatus(info) + pod.CurrentState.HostIP = getInstanceIP(storage.cloud, pod.CurrentState.Host) + pod.Kind = "cluster#pod" return pod, err }