github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/cmd/swarmctl/service/flagparser/port.go (about) 1 package flagparser 2 3 import ( 4 "strconv" 5 "strings" 6 7 "github.com/docker/swarmkit/api" 8 "github.com/pkg/errors" 9 "github.com/spf13/pflag" 10 ) 11 12 func parsePorts(flags *pflag.FlagSet, spec *api.ServiceSpec) error { 13 if !flags.Changed("ports") { 14 return nil 15 } 16 portConfigs, err := flags.GetStringSlice("ports") 17 if err != nil { 18 return err 19 } 20 21 ports := []*api.PortConfig{} 22 for _, portConfig := range portConfigs { 23 name, protocol, port, swarmPort, err := parsePortConfig(portConfig) 24 if err != nil { 25 return err 26 } 27 28 ports = append(ports, &api.PortConfig{ 29 Name: name, 30 Protocol: protocol, 31 TargetPort: port, 32 PublishedPort: swarmPort, 33 // In swarmctl all ports are by default 34 // PublishModeHost 35 PublishMode: api.PublishModeHost, 36 }) 37 } 38 39 spec.Endpoint = &api.EndpointSpec{ 40 Ports: ports, 41 } 42 43 return nil 44 } 45 46 func parsePortConfig(portConfig string) (string, api.PortConfig_Protocol, uint32, uint32, error) { 47 protocol := api.ProtocolTCP 48 parts := strings.Split(portConfig, ":") 49 if len(parts) < 2 { 50 return "", protocol, 0, 0, errors.New("insufficient parameters in port configuration") 51 } 52 53 name := parts[0] 54 55 portSpec := parts[1] 56 protocol, port, err := parsePortSpec(portSpec) 57 if err != nil { 58 return "", protocol, 0, 0, errors.Wrap(err, "failed to parse port") 59 } 60 61 if len(parts) > 2 { 62 var err error 63 64 portSpec := parts[2] 65 nodeProtocol, swarmPort, err := parsePortSpec(portSpec) 66 if err != nil { 67 return "", protocol, 0, 0, errors.Wrap(err, "failed to parse node port") 68 } 69 70 if nodeProtocol != protocol { 71 return "", protocol, 0, 0, errors.New("protocol mismatch") 72 } 73 74 return name, protocol, port, swarmPort, nil 75 } 76 77 return name, protocol, port, 0, nil 78 } 79 80 func parsePortSpec(portSpec string) (api.PortConfig_Protocol, uint32, error) { 81 parts := strings.Split(portSpec, "/") 82 p := parts[0] 83 port, err := strconv.ParseUint(p, 10, 32) 84 if err != nil { 85 return 0, 0, err 86 } 87 88 if len(parts) > 1 { 89 proto := parts[1] 90 protocol, ok := api.PortConfig_Protocol_value[strings.ToUpper(proto)] 91 if !ok { 92 return 0, 0, errors.Errorf("invalid protocol string: %s", proto) 93 } 94 95 return api.PortConfig_Protocol(protocol), uint32(port), nil 96 } 97 98 return api.ProtocolTCP, uint32(port), nil 99 }