WIP: Implement multi-port Services

This commit is contained in:
Tim Hockin
2015-03-13 08:16:41 -07:00
parent 9ed87612d0
commit 186818d787
70 changed files with 2118 additions and 815 deletions

View File

@@ -29,19 +29,30 @@ import (
// provided as an argument.
func FromServices(services *api.ServiceList) []api.EnvVar {
var result []api.EnvVar
for _, service := range services.Items {
for i := range services.Items {
service := &services.Items[i]
// ignore services where PortalIP is "None" or empty
// the services passed to this method should be pre-filtered
// only services that have the portal IP set should be included here
if !api.IsServiceIPSet(&service) {
if !api.IsServiceIPSet(service) {
continue
}
// Host
name := makeEnvVariableName(service.Name) + "_SERVICE_HOST"
result = append(result, api.EnvVar{Name: name, Value: service.Spec.PortalIP})
// Port
// First port - give it the backwards-compatible name
name = makeEnvVariableName(service.Name) + "_SERVICE_PORT"
result = append(result, api.EnvVar{Name: name, Value: strconv.Itoa(service.Spec.Port)})
result = append(result, api.EnvVar{Name: name, Value: strconv.Itoa(service.Spec.Ports[0].Port)})
// All named ports (only the first may be unnamed, checked in validation)
for i := range service.Spec.Ports {
sp := &service.Spec.Ports[i]
if sp.Name != "" {
pn := name + "_" + makeEnvVariableName(sp.Name)
result = append(result, api.EnvVar{Name: pn, Value: strconv.Itoa(sp.Port)})
}
}
// Docker-compatible vars.
result = append(result, makeLinkVariables(service)...)
}
@@ -56,33 +67,42 @@ func makeEnvVariableName(str string) string {
return strings.ToUpper(strings.Replace(str, "-", "_", -1))
}
func makeLinkVariables(service api.Service) []api.EnvVar {
func makeLinkVariables(service *api.Service) []api.EnvVar {
prefix := makeEnvVariableName(service.Name)
protocol := string(api.ProtocolTCP)
if service.Spec.Protocol != "" {
protocol = string(service.Spec.Protocol)
}
portPrefix := fmt.Sprintf("%s_PORT_%d_%s", prefix, service.Spec.Port, strings.ToUpper(protocol))
return []api.EnvVar{
{
Name: prefix + "_PORT",
Value: fmt.Sprintf("%s://%s:%d", strings.ToLower(protocol), service.Spec.PortalIP, service.Spec.Port),
},
{
Name: portPrefix,
Value: fmt.Sprintf("%s://%s:%d", strings.ToLower(protocol), service.Spec.PortalIP, service.Spec.Port),
},
{
Name: portPrefix + "_PROTO",
Value: strings.ToLower(protocol),
},
{
Name: portPrefix + "_PORT",
Value: strconv.Itoa(service.Spec.Port),
},
{
Name: portPrefix + "_ADDR",
Value: service.Spec.PortalIP,
},
all := []api.EnvVar{}
for i := range service.Spec.Ports {
sp := &service.Spec.Ports[i]
protocol := string(api.ProtocolTCP)
if sp.Protocol != "" {
protocol = string(sp.Protocol)
}
if i == 0 {
// Docker special-cases the first port.
all = append(all, api.EnvVar{
Name: prefix + "_PORT",
Value: fmt.Sprintf("%s://%s:%d", strings.ToLower(protocol), service.Spec.PortalIP, sp.Port),
})
}
portPrefix := fmt.Sprintf("%s_PORT_%d_%s", prefix, sp.Port, strings.ToUpper(protocol))
all = append(all, []api.EnvVar{
{
Name: portPrefix,
Value: fmt.Sprintf("%s://%s:%d", strings.ToLower(protocol), service.Spec.PortalIP, sp.Port),
},
{
Name: portPrefix + "_PROTO",
Value: strings.ToLower(protocol),
},
{
Name: portPrefix + "_PORT",
Value: strconv.Itoa(sp.Port),
},
{
Name: portPrefix + "_ADDR",
Value: service.Spec.PortalIP,
},
}...)
}
return all
}

View File

@@ -30,46 +30,53 @@ func TestFromServices(t *testing.T) {
{
ObjectMeta: api.ObjectMeta{Name: "foo-bar"},
Spec: api.ServiceSpec{
Port: 8080,
Selector: map[string]string{"bar": "baz"},
Protocol: "TCP",
PortalIP: "1.2.3.4",
Ports: []api.ServicePort{
{Port: 8080, Protocol: "TCP"},
},
},
},
{
ObjectMeta: api.ObjectMeta{Name: "abc-123"},
Spec: api.ServiceSpec{
Port: 8081,
Selector: map[string]string{"bar": "baz"},
Protocol: "UDP",
PortalIP: "5.6.7.8",
Ports: []api.ServicePort{
{Name: "u-d-p", Port: 8081, Protocol: "UDP"},
{Name: "t-c-p", Port: 8081, Protocol: "TCP"},
},
},
},
{
ObjectMeta: api.ObjectMeta{Name: "q-u-u-x"},
Spec: api.ServiceSpec{
Port: 8082,
Selector: map[string]string{"bar": "baz"},
Protocol: "TCP",
PortalIP: "9.8.7.6",
Ports: []api.ServicePort{
{Port: 8082, Protocol: "TCP"},
{Name: "8083", Port: 8083, Protocol: "TCP"},
},
},
},
{
ObjectMeta: api.ObjectMeta{Name: "svrc-portalip-none"},
Spec: api.ServiceSpec{
Port: 8082,
Selector: map[string]string{"bar": "baz"},
Protocol: "TCP",
PortalIP: "None",
Ports: []api.ServicePort{
{Port: 8082, Protocol: "TCP"},
},
},
},
{
ObjectMeta: api.ObjectMeta{Name: "svrc-portalip-empty"},
Spec: api.ServiceSpec{
Port: 8082,
Selector: map[string]string{"bar": "baz"},
Protocol: "TCP",
PortalIP: "",
Ports: []api.ServicePort{
{Port: 8082, Protocol: "TCP"},
},
},
},
},
@@ -85,18 +92,29 @@ func TestFromServices(t *testing.T) {
{Name: "FOO_BAR_PORT_8080_TCP_ADDR", Value: "1.2.3.4"},
{Name: "ABC_123_SERVICE_HOST", Value: "5.6.7.8"},
{Name: "ABC_123_SERVICE_PORT", Value: "8081"},
{Name: "ABC_123_SERVICE_PORT_U_D_P", Value: "8081"},
{Name: "ABC_123_SERVICE_PORT_T_C_P", Value: "8081"},
{Name: "ABC_123_PORT", Value: "udp://5.6.7.8:8081"},
{Name: "ABC_123_PORT_8081_UDP", Value: "udp://5.6.7.8:8081"},
{Name: "ABC_123_PORT_8081_UDP_PROTO", Value: "udp"},
{Name: "ABC_123_PORT_8081_UDP_PORT", Value: "8081"},
{Name: "ABC_123_PORT_8081_UDP_ADDR", Value: "5.6.7.8"},
{Name: "ABC_123_PORT_8081_TCP", Value: "tcp://5.6.7.8:8081"},
{Name: "ABC_123_PORT_8081_TCP_PROTO", Value: "tcp"},
{Name: "ABC_123_PORT_8081_TCP_PORT", Value: "8081"},
{Name: "ABC_123_PORT_8081_TCP_ADDR", Value: "5.6.7.8"},
{Name: "Q_U_U_X_SERVICE_HOST", Value: "9.8.7.6"},
{Name: "Q_U_U_X_SERVICE_PORT", Value: "8082"},
{Name: "Q_U_U_X_SERVICE_PORT_8083", Value: "8083"},
{Name: "Q_U_U_X_PORT", Value: "tcp://9.8.7.6:8082"},
{Name: "Q_U_U_X_PORT_8082_TCP", Value: "tcp://9.8.7.6:8082"},
{Name: "Q_U_U_X_PORT_8082_TCP_PROTO", Value: "tcp"},
{Name: "Q_U_U_X_PORT_8082_TCP_PORT", Value: "8082"},
{Name: "Q_U_U_X_PORT_8082_TCP_ADDR", Value: "9.8.7.6"},
{Name: "Q_U_U_X_PORT_8083_TCP", Value: "tcp://9.8.7.6:8083"},
{Name: "Q_U_U_X_PORT_8083_TCP_PROTO", Value: "tcp"},
{Name: "Q_U_U_X_PORT_8083_TCP_PORT", Value: "8083"},
{Name: "Q_U_U_X_PORT_8083_TCP_ADDR", Value: "9.8.7.6"},
}
if len(vars) != len(expected) {
t.Errorf("Expected %d env vars, got: %+v", len(expected), vars)