2014-06-06 23:40:48 +00:00
|
|
|
/*
|
|
|
|
Copyright 2014 Google Inc. All rights reserved.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
2014-06-18 23:01:49 +00:00
|
|
|
|
2014-08-14 19:46:08 +00:00
|
|
|
package service
|
2014-06-06 23:40:48 +00:00
|
|
|
|
|
|
|
import (
|
2014-07-12 07:15:30 +00:00
|
|
|
"fmt"
|
2014-06-26 22:00:55 +00:00
|
|
|
"net"
|
|
|
|
"strconv"
|
2014-06-06 23:40:48 +00:00
|
|
|
|
2014-06-12 20:17:34 +00:00
|
|
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
2014-07-18 20:22:26 +00:00
|
|
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
2014-06-17 02:10:43 +00:00
|
|
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
2014-08-11 07:34:59 +00:00
|
|
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/service"
|
2014-07-12 07:15:30 +00:00
|
|
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
2014-08-11 07:34:59 +00:00
|
|
|
|
2014-06-25 03:51:57 +00:00
|
|
|
"github.com/golang/glog"
|
2014-06-06 23:40:48 +00:00
|
|
|
)
|
|
|
|
|
2014-09-02 10:00:28 +00:00
|
|
|
// EndpointController manages service endpoints.
|
2014-06-06 23:40:48 +00:00
|
|
|
type EndpointController struct {
|
2014-07-18 20:22:26 +00:00
|
|
|
client *client.Client
|
2014-08-11 07:34:59 +00:00
|
|
|
serviceRegistry service.Registry
|
2014-06-06 23:40:48 +00:00
|
|
|
}
|
|
|
|
|
2014-08-11 07:34:59 +00:00
|
|
|
// NewEndpointController returns a new *EndpointController.
|
|
|
|
func NewEndpointController(serviceRegistry service.Registry, client *client.Client) *EndpointController {
|
|
|
|
return &EndpointController{
|
|
|
|
serviceRegistry: serviceRegistry,
|
|
|
|
client: client,
|
2014-07-12 07:15:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-11 07:34:59 +00:00
|
|
|
// SyncServiceEndpoints syncs service endpoints.
|
2014-06-06 23:40:48 +00:00
|
|
|
func (e *EndpointController) SyncServiceEndpoints() error {
|
|
|
|
services, err := e.serviceRegistry.ListServices()
|
|
|
|
if err != nil {
|
2014-07-18 20:22:26 +00:00
|
|
|
glog.Errorf("Failed to list services!")
|
2014-06-06 23:40:48 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
var resultErr error
|
|
|
|
for _, service := range services.Items {
|
2014-07-18 20:22:26 +00:00
|
|
|
pods, err := e.client.ListPods(labels.Set(service.Selector).AsSelector())
|
2014-06-06 23:40:48 +00:00
|
|
|
if err != nil {
|
2014-06-25 03:51:57 +00:00
|
|
|
glog.Errorf("Error syncing service: %#v, skipping.", service)
|
2014-06-06 23:40:48 +00:00
|
|
|
resultErr = err
|
|
|
|
continue
|
|
|
|
}
|
2014-07-18 20:22:26 +00:00
|
|
|
endpoints := make([]string, len(pods.Items))
|
|
|
|
for ix, pod := range pods.Items {
|
2014-07-12 07:15:30 +00:00
|
|
|
port, err := findPort(&pod.DesiredState.Manifest, service.ContainerPort)
|
|
|
|
if err != nil {
|
|
|
|
glog.Errorf("Failed to find port for service: %v, %v", service, err)
|
|
|
|
continue
|
|
|
|
}
|
2014-07-18 16:29:17 +00:00
|
|
|
if len(pod.CurrentState.PodIP) == 0 {
|
|
|
|
glog.Errorf("Failed to find an IP for pod: %v", pod)
|
|
|
|
continue
|
|
|
|
}
|
2014-07-12 07:15:30 +00:00
|
|
|
endpoints[ix] = net.JoinHostPort(pod.CurrentState.PodIP, strconv.Itoa(port))
|
2014-06-06 23:40:48 +00:00
|
|
|
}
|
2014-08-25 21:36:15 +00:00
|
|
|
// TODO: this is totally broken, we need to compute this and store inside an AtomicUpdate loop.
|
2014-06-12 20:17:34 +00:00
|
|
|
err = e.serviceRegistry.UpdateEndpoints(api.Endpoints{
|
2014-07-23 01:53:41 +00:00
|
|
|
JSONBase: api.JSONBase{ID: service.ID},
|
2014-06-06 23:40:48 +00:00
|
|
|
Endpoints: endpoints,
|
|
|
|
})
|
|
|
|
if err != nil {
|
2014-06-25 03:51:57 +00:00
|
|
|
glog.Errorf("Error updating endpoints: %#v", err)
|
2014-06-06 23:40:48 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return resultErr
|
|
|
|
}
|
2014-08-11 07:34:59 +00:00
|
|
|
|
|
|
|
// findPort locates the container port for the given manifest and portName.
|
|
|
|
func findPort(manifest *api.ContainerManifest, portName util.IntOrString) (int, error) {
|
|
|
|
if ((portName.Kind == util.IntstrString && len(portName.StrVal) == 0) ||
|
|
|
|
(portName.Kind == util.IntstrInt && portName.IntVal == 0)) &&
|
|
|
|
len(manifest.Containers[0].Ports) > 0 {
|
|
|
|
return manifest.Containers[0].Ports[0].ContainerPort, nil
|
|
|
|
}
|
|
|
|
if portName.Kind == util.IntstrInt {
|
|
|
|
return portName.IntVal, nil
|
|
|
|
}
|
|
|
|
name := portName.StrVal
|
|
|
|
for _, container := range manifest.Containers {
|
|
|
|
for _, port := range container.Ports {
|
|
|
|
if port.Name == name {
|
|
|
|
return port.ContainerPort, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1, fmt.Errorf("no suitable port for manifest: %s", manifest.ID)
|
|
|
|
}
|