func ServiceSpec(srvcSpecs []interface{}) api.ServiceSpec {
	if len(srvcSpecs) == 0 {
		return api.ServiceSpec{}
	}

	userServiceSpec := srvcSpecs[0].(map[string]interface{})

	srvcSpec := api.ServiceSpec{
		Ports: ServicePorts(userServiceSpec["ports"].([]interface{})),
	}

	if _, ok := userServiceSpec["selector"]; ok {
		srvcSpec.Selector = convertMapTypeToStringMap(userServiceSpec["selector"].(map[string]interface{}))
	}

	if _, ok := userServiceSpec["cluster_ip"]; ok {
		srvcSpec.ClusterIP = userServiceSpec["cluster_ip"].(string)
	}

	if _, ok := userServiceSpec["type"]; ok {
		srvcSpec.Type = api.ServiceType(userServiceSpec["type"].(string))
	}

	if _, ok := userServiceSpec["session_affinity"]; ok {
		srvcSpec.SessionAffinity = api.ServiceAffinity(userServiceSpec["session_affinity"].(string))
	}

	return srvcSpec
}
예제 #2
0
// OnEndpointsUpdate manages the registered service endpoints.
// Registered endpoints are updated if found in the update set or
// unregistered if missing from the update set.
func (lb *LoadBalancerRR) OnEndpointsUpdate(allEndpoints []api.Endpoints) {
	registeredEndpoints := make(map[proxy.ServicePortName]bool)
	lb.lock.Lock()
	defer lb.lock.Unlock()

	// Update endpoints for services.
	for i := range allEndpoints {
		svcEndpoints := &allEndpoints[i]

		// We need to build a map of portname -> all ip:ports for that
		// portname.  Explode Endpoints.Subsets[*] into this structure.
		portsToEndpoints := map[string][]hostPortPair{}
		for i := range svcEndpoints.Subsets {
			ss := &svcEndpoints.Subsets[i]
			for i := range ss.Ports {
				port := &ss.Ports[i]
				for i := range ss.Addresses {
					addr := &ss.Addresses[i]
					portsToEndpoints[port.Name] = append(portsToEndpoints[port.Name], hostPortPair{addr.IP, port.Port})
					// Ignore the protocol field - we'll get that from the Service objects.
				}
			}
		}

		for portname := range portsToEndpoints {
			svcPort := proxy.ServicePortName{NamespacedName: types.NamespacedName{Namespace: svcEndpoints.Namespace, Name: svcEndpoints.Name}, Port: portname}
			state, exists := lb.services[svcPort]
			curEndpoints := []string{}
			if state != nil {
				curEndpoints = state.endpoints
			}
			newEndpoints := flattenValidEndpoints(portsToEndpoints[portname])

			if !exists || state == nil || len(curEndpoints) != len(newEndpoints) || !slicesEquiv(slice.CopyStrings(curEndpoints), newEndpoints) {
				glog.V(1).Infof("LoadBalancerRR: Setting endpoints for %s to %+v", svcPort, newEndpoints)
				lb.updateAffinityMap(svcPort, newEndpoints)
				// OnEndpointsUpdate can be called without NewService being called externally.
				// To be safe we will call it here.  A new service will only be created
				// if one does not already exist.  The affinity will be updated
				// later, once NewService is called.
				state = lb.newServiceInternal(svcPort, api.ServiceAffinity(""), 0)
				state.endpoints = slice.ShuffleStrings(newEndpoints)

				// Reset the round-robin index.
				state.index = 0
			}
			registeredEndpoints[svcPort] = true
		}
	}
	// Remove endpoints missing from the update.
	for k := range lb.services {
		if _, exists := registeredEndpoints[k]; !exists {
			glog.V(2).Infof("LoadBalancerRR: Removing endpoints for %s", k)
			delete(lb.services, k)
		}
	}
}
예제 #3
0
func convert_v1beta3_ServiceSpec_To_api_ServiceSpec(in *ServiceSpec, out *api.ServiceSpec, s conversion.Scope) error {
	if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
		defaulting.(func(*ServiceSpec))(in)
	}
	if in.Ports != nil {
		out.Ports = make([]api.ServicePort, len(in.Ports))
		for i := range in.Ports {
			if err := convert_v1beta3_ServicePort_To_api_ServicePort(&in.Ports[i], &out.Ports[i], s); err != nil {
				return err
			}
		}
	} else {
		out.Ports = nil
	}
	if in.Selector != nil {
		out.Selector = make(map[string]string)
		for key, val := range in.Selector {
			out.Selector[key] = val
		}
	} else {
		out.Selector = nil
	}
	out.ClusterIP = in.PortalIP

	typeIn := in.Type
	if typeIn == "" {
		if in.CreateExternalLoadBalancer {
			typeIn = ServiceTypeLoadBalancer
		} else {
			typeIn = ServiceTypeClusterIP
		}
	}
	if err := s.Convert(&typeIn, &out.Type, 0); err != nil {
		return err
	}

	if in.PublicIPs != nil {
		out.ExternalIPs = make([]string, len(in.PublicIPs))
		for i := range in.PublicIPs {
			out.ExternalIPs[i] = in.PublicIPs[i]
		}
	} else {
		out.ExternalIPs = nil
	}
	out.SessionAffinity = api.ServiceAffinity(in.SessionAffinity)
	out.LoadBalancerIP = in.LoadBalancerIP
	return nil
}
예제 #4
0
func (testServiceGenerator) Generate(genericParams map[string]interface{}) (runtime.Object, error) {
	params := map[string]string{}
	for key, value := range genericParams {
		strVal, isString := value.(string)
		if !isString {
			return nil, fmt.Errorf("expected string, saw %v for '%s'", value, key)
		}
		params[key] = strVal
	}
	labelsString, found := params["labels"]
	var labels map[string]string
	var err error
	if found && len(labelsString) > 0 {
		labels, err = kubectl.ParseLabels(labelsString)
		if err != nil {
			return nil, err
		}
	}

	name, found := params["name"]
	if !found || len(name) == 0 {
		name, found = params["default-name"]
		if !found || len(name) == 0 {
			return nil, fmt.Errorf("'name' is a required parameter.")
		}
	}
	portString, found := params["port"]
	if !found {
		return nil, fmt.Errorf("'port' is a required parameter.")
	}
	port, err := strconv.Atoi(portString)
	if err != nil {
		return nil, err
	}
	servicePortName, found := params["port-name"]
	if !found {
		// Leave the port unnamed.
		servicePortName = ""
	}
	service := api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:   name,
			Labels: labels,
		},
		Spec: api.ServiceSpec{
			Ports: []api.ServicePort{
				{
					Name:     servicePortName,
					Port:     port,
					Protocol: api.Protocol(params["protocol"]),
				},
			},
		},
	}
	targetPort, found := params["target-port"]
	if !found {
		targetPort, found = params["container-port"]
	}
	if found && len(targetPort) > 0 {
		if portNum, err := strconv.Atoi(targetPort); err != nil {
			service.Spec.Ports[0].TargetPort = intstr.FromString(targetPort)
		} else {
			service.Spec.Ports[0].TargetPort = intstr.FromInt(portNum)
		}
	} else {
		service.Spec.Ports[0].TargetPort = intstr.FromInt(port)
	}
	if params["create-external-load-balancer"] == "true" {
		service.Spec.Type = api.ServiceTypeLoadBalancer
	}
	if len(params["external-ip"]) > 0 {
		service.Spec.ExternalIPs = []string{params["external-ip"]}
	}
	if len(params["type"]) != 0 {
		service.Spec.Type = api.ServiceType(params["type"])
	}
	if len(params["session-affinity"]) != 0 {
		switch api.ServiceAffinity(params["session-affinity"]) {
		case api.ServiceAffinityNone:
			service.Spec.SessionAffinity = api.ServiceAffinityNone
		case api.ServiceAffinityClientIP:
			service.Spec.SessionAffinity = api.ServiceAffinityClientIP
		default:
			return nil, fmt.Errorf("unknown session affinity: %s", params["session-affinity"])
		}
	}
	return &service, nil
}
예제 #5
0
파일: service.go 프로젝트: 40a/bootkube
func generate(genericParams map[string]interface{}) (runtime.Object, error) {
	params := map[string]string{}
	for key, value := range genericParams {
		strVal, isString := value.(string)
		if !isString {
			return nil, fmt.Errorf("expected string, saw %v for '%s'", value, key)
		}
		params[key] = strVal
	}
	selectorString, found := params["selector"]
	if !found || len(selectorString) == 0 {
		return nil, fmt.Errorf("'selector' is a required parameter.")
	}
	selector, err := ParseLabels(selectorString)
	if err != nil {
		return nil, err
	}

	labelsString, found := params["labels"]
	var labels map[string]string
	if found && len(labelsString) > 0 {
		labels, err = ParseLabels(labelsString)
		if err != nil {
			return nil, err
		}
	}

	name, found := params["name"]
	if !found || len(name) == 0 {
		name, found = params["default-name"]
		if !found || len(name) == 0 {
			return nil, fmt.Errorf("'name' is a required parameter.")
		}
	}
	ports := []api.ServicePort{}
	servicePortName, found := params["port-name"]
	if !found {
		// Leave the port unnamed.
		servicePortName = ""
	}

	protocolsString, found := params["protocols"]
	var portProtocolMap map[string]string
	if found && len(protocolsString) > 0 {
		portProtocolMap, err = ParseProtocols(protocolsString)
		if err != nil {
			return nil, err
		}
	}
	// ports takes precedence over port since it will be
	// specified only when the user hasn't specified a port
	// via --port and the exposed object has multiple ports.
	var portString string
	if portString, found = params["ports"]; !found {
		portString, found = params["port"]
		if !found {
			return nil, fmt.Errorf("'port' is a required parameter.")
		}
	}

	portStringSlice := strings.Split(portString, ",")
	for i, stillPortString := range portStringSlice {
		port, err := strconv.Atoi(stillPortString)
		if err != nil {
			return nil, err
		}
		name := servicePortName
		// If we are going to assign multiple ports to a service, we need to
		// generate a different name for each one.
		if len(portStringSlice) > 1 {
			name = fmt.Sprintf("port-%d", i+1)
		}
		protocol := params["protocol"]

		switch {
		case len(protocol) == 0 && len(portProtocolMap) == 0:
			// Default to TCP, what the flag was doing previously.
			protocol = "TCP"
		case len(protocol) > 0 && len(portProtocolMap) > 0:
			// User has specified the --protocol while exposing a multiprotocol resource
			// We should stomp multiple protocols with the one specified ie. do nothing
		case len(protocol) == 0 && len(portProtocolMap) > 0:
			// no --protocol and we expose a multiprotocol resource
			protocol = "TCP" // have the default so we can stay sane
			if exposeProtocol, found := portProtocolMap[stillPortString]; found {
				protocol = exposeProtocol
			}
		}
		ports = append(ports, api.ServicePort{
			Name:     name,
			Port:     int32(port),
			Protocol: api.Protocol(protocol),
		})
	}

	service := api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:   name,
			Labels: labels,
		},
		Spec: api.ServiceSpec{
			Selector: selector,
			Ports:    ports,
		},
	}
	targetPortString, found := params["target-port"]
	if !found {
		targetPortString, found = params["container-port"]
	}
	if found && len(targetPortString) > 0 {
		var targetPort intstr.IntOrString
		if portNum, err := strconv.Atoi(targetPortString); err != nil {
			targetPort = intstr.FromString(targetPortString)
		} else {
			targetPort = intstr.FromInt(portNum)
		}
		// Use the same target-port for every port
		for i := range service.Spec.Ports {
			service.Spec.Ports[i].TargetPort = targetPort
		}
	} else {
		// If --target-port or --container-port haven't been specified, this
		// should be the same as Port
		for i := range service.Spec.Ports {
			port := service.Spec.Ports[i].Port
			service.Spec.Ports[i].TargetPort = intstr.FromInt(int(port))
		}
	}
	if params["create-external-load-balancer"] == "true" {
		service.Spec.Type = api.ServiceTypeLoadBalancer
	}
	if len(params["external-ip"]) > 0 {
		service.Spec.ExternalIPs = []string{params["external-ip"]}
	}
	if len(params["type"]) != 0 {
		service.Spec.Type = api.ServiceType(params["type"])
	}
	if service.Spec.Type == api.ServiceTypeLoadBalancer {
		service.Spec.LoadBalancerIP = params["load-balancer-ip"]
	}
	if len(params["session-affinity"]) != 0 {
		switch api.ServiceAffinity(params["session-affinity"]) {
		case api.ServiceAffinityNone:
			service.Spec.SessionAffinity = api.ServiceAffinityNone
		case api.ServiceAffinityClientIP:
			service.Spec.SessionAffinity = api.ServiceAffinityClientIP
		default:
			return nil, fmt.Errorf("unknown session affinity: %s", params["session-affinity"])
		}
	}
	return &service, nil
}
예제 #6
0
func generate(params map[string]string) (runtime.Object, error) {
	selectorString, found := params["selector"]
	if !found || len(selectorString) == 0 {
		return nil, fmt.Errorf("'selector' is a required parameter.")
	}
	selector, err := ParseLabels(selectorString)
	if err != nil {
		return nil, err
	}

	labelsString, found := params["labels"]
	var labels map[string]string
	if found && len(labelsString) > 0 {
		labels, err = ParseLabels(labelsString)
		if err != nil {
			return nil, err
		}
	}

	name, found := params["name"]
	if !found || len(name) == 0 {
		name, found = params["default-name"]
		if !found || len(name) == 0 {
			return nil, fmt.Errorf("'name' is a required parameter.")
		}
	}
	portString, found := params["port"]
	if !found {
		return nil, fmt.Errorf("'port' is a required parameter.")
	}
	port, err := strconv.Atoi(portString)
	if err != nil {
		return nil, err
	}
	servicePortName, found := params["port-name"]
	if !found {
		// Leave the port unnamed.
		servicePortName = ""
	}
	service := api.Service{
		ObjectMeta: api.ObjectMeta{
			Name:   name,
			Labels: labels,
		},
		Spec: api.ServiceSpec{
			Selector: selector,
			Ports: []api.ServicePort{
				{
					Name:     servicePortName,
					Port:     port,
					Protocol: api.Protocol(params["protocol"]),
				},
			},
		},
	}
	targetPort, found := params["target-port"]
	if !found {
		targetPort, found = params["container-port"]
	}
	if found && len(targetPort) > 0 {
		if portNum, err := strconv.Atoi(targetPort); err != nil {
			service.Spec.Ports[0].TargetPort = util.NewIntOrStringFromString(targetPort)
		} else {
			service.Spec.Ports[0].TargetPort = util.NewIntOrStringFromInt(portNum)
		}
	} else {
		service.Spec.Ports[0].TargetPort = util.NewIntOrStringFromInt(port)
	}
	if params["create-external-load-balancer"] == "true" {
		service.Spec.Type = api.ServiceTypeLoadBalancer
	}
	if len(params["public-ip"]) != 0 {
		service.Spec.DeprecatedPublicIPs = []string{params["public-ip"]}
	}
	if len(params["type"]) != 0 {
		service.Spec.Type = api.ServiceType(params["type"])
	}
	if len(params["session-affinity"]) != 0 {
		switch api.ServiceAffinity(params["session-affinity"]) {
		case api.ServiceAffinityNone:
			service.Spec.SessionAffinity = api.ServiceAffinityNone
		case api.ServiceAffinityClientIP:
			service.Spec.SessionAffinity = api.ServiceAffinityClientIP
		default:
			return nil, fmt.Errorf("unknown session affinity: %s", params["session-affinity"])
		}
	}
	return &service, nil
}