implement begin-port+offset port range parsing

This commit is contained in:
yue9944882 2018-01-24 11:30:19 +08:00
parent 24516c5a96
commit 6203e52324
3 changed files with 59 additions and 17 deletions

View File

@ -137,7 +137,7 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&o.config.ResourceContainer, "resource-container", o.config.ResourceContainer, "Absolute name of the resource-only container to create and run the Kube-proxy in (Default: /kube-proxy).") fs.StringVar(&o.config.ResourceContainer, "resource-container", o.config.ResourceContainer, "Absolute name of the resource-only container to create and run the Kube-proxy in (Default: /kube-proxy).")
fs.MarkDeprecated("resource-container", "This feature will be removed in a later release.") fs.MarkDeprecated("resource-container", "This feature will be removed in a later release.")
fs.StringVar(&o.config.ClientConnection.KubeConfigFile, "kubeconfig", o.config.ClientConnection.KubeConfigFile, "Path to kubeconfig file with authorization information (the master location is set by the master flag).") fs.StringVar(&o.config.ClientConnection.KubeConfigFile, "kubeconfig", o.config.ClientConnection.KubeConfigFile, "Path to kubeconfig file with authorization information (the master location is set by the master flag).")
fs.Var(componentconfig.PortRangeVar{Val: &o.config.PortRange}, "proxy-port-range", "Range of host ports (beginPort-endPort, inclusive) that may be consumed in order to proxy service traffic. If unspecified (0-0) then ports will be randomly chosen.") fs.Var(componentconfig.PortRangeVar{Val: &o.config.PortRange}, "proxy-port-range", "Range of host ports (beginPort-endPort, single port or beginPort+offset, inclusive) that may be consumed in order to proxy service traffic. If unspecified (0-0) then ports will be randomly chosen.")
fs.StringVar(&o.config.HostnameOverride, "hostname-override", o.config.HostnameOverride, "If non-empty, will use this string as identification instead of the actual hostname.") fs.StringVar(&o.config.HostnameOverride, "hostname-override", o.config.HostnameOverride, "If non-empty, will use this string as identification instead of the actual hostname.")
fs.Var(&o.config.Mode, "proxy-mode", "Which proxy mode to use: 'userspace' (older) or 'iptables' (faster) or 'ipvs' (experimental). If blank, use the best-available proxy (currently iptables). If the iptables proxy is selected, regardless of how, but the system's kernel or iptables versions are insufficient, this always falls back to the userspace proxy.") fs.Var(&o.config.Mode, "proxy-mode", "Which proxy mode to use: 'userspace' (older) or 'iptables' (faster) or 'ipvs' (experimental). If blank, use the best-available proxy (currently iptables). If the iptables proxy is selected, regardless of how, but the system's kernel or iptables versions are insufficient, this always falls back to the userspace proxy.")
fs.Int32Var(o.config.IPTables.MasqueradeBit, "iptables-masquerade-bit", utilpointer.Int32PtrDerefOr(o.config.IPTables.MasqueradeBit, 14), "If using the pure iptables proxy, the bit of the fwmark space to mark packets requiring SNAT with. Must be within the range [0, 31].") fs.Int32Var(o.config.IPTables.MasqueradeBit, "iptables-masquerade-bit", utilpointer.Int32PtrDerefOr(o.config.IPTables.MasqueradeBit, 14), "If using the pure iptables proxy, the bit of the fwmark space to mark packets requiring SNAT with. Must be within the range [0, 31].")

View File

@ -43,14 +43,20 @@ func (pr PortRange) String() string {
return fmt.Sprintf("%d-%d", pr.Base, pr.Base+pr.Size-1) return fmt.Sprintf("%d-%d", pr.Base, pr.Base+pr.Size-1)
} }
const (
SinglePortNotation = iota
HyphenNotation = 1 << iota
PlusNotation
)
// Set parses a string of the form "min-max", inclusive at both ends, and // Set parses a string of the form "min-max", inclusive at both ends, and
// sets the PortRange from it. This is part of the flag.Value and pflag.Value // sets the PortRange from it. This is part of the flag.Value and pflag.Value
// interfaces. // interfaces.
func (pr *PortRange) Set(value string) error { func (pr *PortRange) Set(value string) error {
value = strings.TrimSpace(value)
// TODO: Accept "80" syntax value = strings.TrimSpace(value)
// TODO: Accept "80+8" syntax hyphenIndex := strings.Index(value, "-")
plusIndex := strings.Index(value, "+")
if value == "" { if value == "" {
pr.Base = 0 pr.Base = 0
@ -58,20 +64,48 @@ func (pr *PortRange) Set(value string) error {
return nil return nil
} }
hyphenIndex := strings.Index(value, "-") var err error
if hyphenIndex == -1 { var notation int
return fmt.Errorf("expected hyphen in port range") var low, high int
if hyphenIndex >= 0 {
notation |= HyphenNotation
}
if plusIndex != -1 {
notation |= PlusNotation
} }
var err error switch notation {
var low int case SinglePortNotation:
var high int var port int
low, err = strconv.Atoi(value[:hyphenIndex]) port, err = strconv.Atoi(value)
if err == nil { if err != nil {
return err
}
low = port
high = port
case HyphenNotation:
low, err = strconv.Atoi(value[:hyphenIndex])
if err != nil {
return err
}
high, err = strconv.Atoi(value[hyphenIndex+1:]) high, err = strconv.Atoi(value[hyphenIndex+1:])
} if err != nil {
if err != nil { return err
return fmt.Errorf("unable to parse port range: %s: %v", value, err) }
case PlusNotation:
var offset int
low, err = strconv.Atoi(value[:plusIndex])
if err != nil {
return err
}
offset, err = strconv.Atoi(value[plusIndex+1:])
if err != nil {
return err
}
high = low + offset
default:
return fmt.Errorf("unable to parse port range: %s", value)
} }
if low > 65535 || high > 65535 { if low > 65535 || high > 65535 {

View File

@ -34,13 +34,21 @@ func TestPortRange(t *testing.T) {
{" 100-200 ", true, "100-200", 200, 201}, {" 100-200 ", true, "100-200", 200, 201},
{"0-0", true, "0-0", 0, 1}, {"0-0", true, "0-0", 0, 1},
{"", true, "", -1, 0}, {"", true, "", -1, 0},
{"100", false, "", -1, -1}, {"100", true, "100-100", 100, 101},
{"100 - 200", false, "", -1, -1}, {"100 - 200", false, "", -1, -1},
{"-100", false, "", -1, -1}, {"-100", false, "", -1, -1},
{"100-", false, "", -1, -1}, {"100-", false, "", -1, -1},
{"200-100", false, "", -1, -1}, {"200-100", false, "", -1, -1},
{"60000-70000", false, "", -1, -1}, {"60000-70000", false, "", -1, -1},
{"70000-80000", false, "", -1, -1}, {"70000-80000", false, "", -1, -1},
{"70000+80000", false, "", -1, -1},
{"1+0", true, "1-1", 1, 2},
{"0+0", true, "0-0", 0, 1},
{"1+-1", false, "", -1, -1},
{"1-+1", false, "", -1, -1},
{"100+200", true, "100-300", 300, 301},
{"1+65535", false, "", -1, -1},
{"0+65535", true, "0-65535", 65535, 65536},
} }
for i := range testCases { for i := range testCases {
@ -52,7 +60,7 @@ func TestPortRange(t *testing.T) {
t.Errorf("expected success, got %q", err) t.Errorf("expected success, got %q", err)
continue continue
} else if err == nil && tc.success == false { } else if err == nil && tc.success == false {
t.Errorf("expected failure") t.Errorf("expected failure %#v", testCases[i])
continue continue
} else if tc.success { } else if tc.success {
if f.String() != tc.expected { if f.String() != tc.expected {