// WildcardMapper maps k8s wildcard ports (hostPort == 0) to any available offer port func WildcardMapper(t *T, offer *mesos.Offer) ([]HostPortMapping, error) { mapping, err := FixedMapper(t, offer) if err != nil { return nil, err } taken := make(map[uint64]struct{}) for _, entry := range mapping { taken[entry.OfferPort] = struct{}{} } wildports := []HostPortMapping{} for i, container := range t.Pod.Spec.Containers { for pi, port := range container.Ports { if port.HostPort == 0 { wildports = append(wildports, HostPortMapping{ ContainerIdx: i, PortIdx: pi, }) } } } remaining := len(wildports) foreachPortsRange(offer.GetResources(), t.Roles(), func(bp, ep uint64, role string) { log.V(3).Infof("Searching for wildcard port in range {%d:%d}", bp, ep) for i := range wildports { if wildports[i].OfferPort != 0 { continue } for port := bp; port <= ep && remaining > 0; port++ { if _, inuse := taken[port]; inuse { continue } wildports[i].OfferPort = port wildports[i].Role = starredRole(role) mapping = append(mapping, wildports[i]) remaining-- taken[port] = struct{}{} break } } }) if remaining > 0 { err := &PortAllocationError{ PodId: t.Pod.Name, } // it doesn't make sense to include a port list here because they were all zero (wildcards) return nil, err } return mapping, nil }
// FixedMapper maps k8s host ports to offered ports ignoring hostPorts == 0 (remaining pod-private) func FixedMapper(t *T, offer *mesos.Offer) ([]HostPortMapping, error) { requiredPorts := make(map[uint64]HostPortMapping) mapping := []HostPortMapping{} for i, container := range t.Pod.Spec.Containers { // strip all port==0 from this array; k8s already knows what to do with zero- // ports (it does not create 'port bindings' on the minion-host); we need to // remove the wildcards from this array since they don't consume host resources for pi, port := range container.Ports { if port.HostPort == 0 { continue // ignore } m := HostPortMapping{ ContainerIdx: i, PortIdx: pi, OfferPort: uint64(port.HostPort), } if entry, inuse := requiredPorts[uint64(port.HostPort)]; inuse { return nil, &DuplicateHostPortError{entry, m} } requiredPorts[uint64(port.HostPort)] = m } } foreachPortsRange(offer.GetResources(), t.Roles(), func(bp, ep uint64, role string) { for port := range requiredPorts { log.V(3).Infof("evaluating port range {%d:%d} %d", bp, ep, port) if (bp <= port) && (port <= ep) { m := requiredPorts[port] m.Role = starredRole(role) mapping = append(mapping, m) delete(requiredPorts, port) } } }) unsatisfiedPorts := len(requiredPorts) if unsatisfiedPorts > 0 { err := &PortAllocationError{ PodId: t.Pod.Name, } for p := range requiredPorts { err.Ports = append(err.Ports, p) } return nil, err } return mapping, nil }
func Offer(offer *mesos.Offer) string { var buffer bytes.Buffer buffer.WriteString(offer.GetHostname()) buffer.WriteString(ID(offer.GetId().GetValue())) resources := Resources(offer.GetResources()) if resources != "" { buffer.WriteString(" ") buffer.WriteString(resources) } attributes := Attributes(offer.GetAttributes()) if attributes != "" { buffer.WriteString(" ") buffer.WriteString(attributes) } return buffer.String() }
func offerString(offer *mesos.Offer) string { return fmt.Sprintf("\n%s%s %s %s", offer.GetHostname(), idString(offer.GetId().GetValue()), resourcesString(offer.GetResources()), attributesString(offer.GetAttributes())) }