pkg/flags: Add support for IPv6 addresses

Support IPv6 address for ETCD_ADDR and ETCD_PEER_ADDR

pkg/flags: Support IPv6 address for ETCD_ADDR and ETCD_PEER_ADDR

pkg/flags: tests for IPv6 addr and bind-addr flags

pkg/flags: IPAddressPort.Host: do not enclose IPv6 address in square brackets

pkg/flags: set default bind address to [::] instead of 0.0.0.0

pkg/flags: we don't need fmt any more

also, one minor fix: net.JoinHostPort takes string as a port value

pkg/flags: fix ipv6 tests

pkg/flags: test both IPv4 and IPv6 addresses in TestIPAddressPortString

etcdmain: test: use [::] instead of 0.0.0.0
This commit is contained in:
kmeaw 2015-03-10 20:20:03 +03:00 committed by Yicheng Qin
parent 0fb9362c5c
commit 4c9e1686b1
5 changed files with 33 additions and 20 deletions

View File

@ -157,9 +157,9 @@ func TestConfigParsingV1Flags(t *testing.T) {
"-addr=127.0.0.1:4001", "-addr=127.0.0.1:4001",
} }
wcfg := NewConfig() wcfg := NewConfig()
wcfg.lpurls = []url.URL{{Scheme: "http", Host: "0.0.0.0:7001"}} wcfg.lpurls = []url.URL{{Scheme: "http", Host: "[::]:7001"}}
wcfg.apurls = []url.URL{{Scheme: "http", Host: "127.0.0.1:7001"}} wcfg.apurls = []url.URL{{Scheme: "http", Host: "127.0.0.1:7001"}}
wcfg.lcurls = []url.URL{{Scheme: "http", Host: "0.0.0.0:4001"}} wcfg.lcurls = []url.URL{{Scheme: "http", Host: "[::]:4001"}}
wcfg.acurls = []url.URL{{Scheme: "http", Host: "127.0.0.1:4001"}} wcfg.acurls = []url.URL{{Scheme: "http", Host: "127.0.0.1:4001"}}
cfg := NewConfig() cfg := NewConfig()

View File

@ -88,13 +88,13 @@ func SetFlagsFromEnv(fs *flag.FlagSet) error {
// SetBindAddrFromAddr sets the value of bindAddr flag from the value // SetBindAddrFromAddr sets the value of bindAddr flag from the value
// of addr flag. Both flags' Value must be of type IPAddressPort. If the // of addr flag. Both flags' Value must be of type IPAddressPort. If the
// bindAddr flag is set and the addr flag is unset, it will set bindAddr to // bindAddr flag is set and the addr flag is unset, it will set bindAddr to
// 0.0.0.0:port of addr. Otherwise, it keeps the original values. // [::]:port of addr. Otherwise, it keeps the original values.
func SetBindAddrFromAddr(fs *flag.FlagSet, bindAddrFlagName, addrFlagName string) { func SetBindAddrFromAddr(fs *flag.FlagSet, bindAddrFlagName, addrFlagName string) {
if IsSet(fs, bindAddrFlagName) || !IsSet(fs, addrFlagName) { if IsSet(fs, bindAddrFlagName) || !IsSet(fs, addrFlagName) {
return return
} }
addr := *fs.Lookup(addrFlagName).Value.(*IPAddressPort) addr := *fs.Lookup(addrFlagName).Value.(*IPAddressPort)
addr.IP = "0.0.0.0" addr.IP = "::"
if err := fs.Set(bindAddrFlagName, addr.String()); err != nil { if err := fs.Set(bindAddrFlagName, addr.String()); err != nil {
log.Panicf("etcdmain: unexpected flags set error: %v", err) log.Panicf("etcdmain: unexpected flags set error: %v", err)
} }

View File

@ -94,7 +94,7 @@ func TestSetBindAddrFromAddr(t *testing.T) {
// addr flag set // addr flag set
{ {
args: []string{"-addr=192.0.3.17:4001"}, args: []string{"-addr=192.0.3.17:4001"},
waddr: &IPAddressPort{IP: "0.0.0.0", Port: 4001}, waddr: &IPAddressPort{IP: "::", Port: 4001},
}, },
// bindAddr flag set // bindAddr flag set
{ {
@ -106,6 +106,11 @@ func TestSetBindAddrFromAddr(t *testing.T) {
args: []string{"-bind-addr=127.0.0.1:4001", "-addr=192.0.3.17:4001"}, args: []string{"-bind-addr=127.0.0.1:4001", "-addr=192.0.3.17:4001"},
waddr: &IPAddressPort{IP: "127.0.0.1", Port: 4001}, waddr: &IPAddressPort{IP: "127.0.0.1", Port: 4001},
}, },
// both addr flags set, IPv6
{
args: []string{"-bind-addr=[2001:db8::4:9]:4001", "-addr=[2001:db8::4:f0]:4001"},
waddr: &IPAddressPort{IP: "2001:db8::4:9", Port: 4001},
},
} }
for i, tt := range tests { for i, tt := range tests {
fs := flag.NewFlagSet("test", flag.PanicOnError) fs := flag.NewFlagSet("test", flag.PanicOnError)

View File

@ -16,7 +16,6 @@ package flags
import ( import (
"errors" "errors"
"fmt"
"net" "net"
"strconv" "strconv"
"strings" "strings"
@ -32,26 +31,26 @@ type IPAddressPort struct {
func (a *IPAddressPort) Set(arg string) error { func (a *IPAddressPort) Set(arg string) error {
arg = strings.TrimSpace(arg) arg = strings.TrimSpace(arg)
parts := strings.SplitN(arg, ":", 2) host, portStr, err := net.SplitHostPort(arg)
if len(parts) != 2 { if err != nil {
return errors.New("bad format in address specification") return err
} }
if net.ParseIP(parts[0]) == nil { if net.ParseIP(host) == nil {
return errors.New("bad IP in address specification") return errors.New("bad IP in address specification")
} }
port, err := strconv.Atoi(parts[1]) port, err := strconv.Atoi(portStr)
if err != nil { if err != nil {
return errors.New("bad port in address specification") return errors.New("bad port in address specification")
} }
a.IP = parts[0] a.IP = host
a.Port = port a.Port = port
return nil return nil
} }
func (a *IPAddressPort) String() string { func (a *IPAddressPort) String() string {
return fmt.Sprintf("%s:%d", a.IP, a.Port) return net.JoinHostPort(a.IP, strconv.Itoa(a.Port))
} }

View File

@ -22,6 +22,7 @@ func TestIPAddressPortSet(t *testing.T) {
pass := []string{ pass := []string{
"1.2.3.4:8080", "1.2.3.4:8080",
"10.1.1.1:80", "10.1.1.1:80",
"[2001:db8::1]:8080",
} }
fail := []string{ fail := []string{
@ -40,6 +41,8 @@ func TestIPAddressPortSet(t *testing.T) {
"234#$", "234#$",
"file://foo/bar", "file://foo/bar",
"http://hello", "http://hello",
"2001:db8::1",
"2001:db8::1:1",
} }
for i, tt := range pass { for i, tt := range pass {
@ -58,14 +61,20 @@ func TestIPAddressPortSet(t *testing.T) {
} }
func TestIPAddressPortString(t *testing.T) { func TestIPAddressPortString(t *testing.T) {
addresses := []string{
"[2001:db8::1:1234]:4001",
"127.0.0.1:4001",
}
for i, tt := range addresses {
f := &IPAddressPort{} f := &IPAddressPort{}
if err := f.Set("127.0.0.1:4001"); err != nil { if err := f.Set(tt); err != nil {
t.Fatalf("unexpected error: %v", err) t.Errorf("#%d: unexpected error: %v", i, err)
} }
want := "127.0.0.1:4001" want := tt
got := f.String() got := f.String()
if want != got { if want != got {
t.Fatalf("IPAddressPort.String() value should be %q, got %q", want, got) t.Errorf("#%d: IPAddressPort.String() value should be %q, got %q", i, want, got)
}
} }
} }