Skip to content

Commit e99b915

Browse files
Merge pull request #640 from github/ipv6
Parsing ipv6 addresses
2 parents 447a98a + 8c4cd10 commit e99b915

File tree

4 files changed

+106
-14
lines changed

4 files changed

+106
-14
lines changed

go/logic/migrator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ func (this *Migrator) initiateInspector() (err error) {
741741
this.migrationContext.Log.Infof("Master found to be %+v", *this.migrationContext.ApplierConnectionConfig.ImpliedKey)
742742
} else {
743743
// Forced master host.
744-
key, err := mysql.ParseRawInstanceKeyLoose(this.migrationContext.AssumeMasterHostname)
744+
key, err := mysql.ParseInstanceKey(this.migrationContext.AssumeMasterHostname)
745745
if err != nil {
746746
return err
747747
}

go/mysql/instance_key.go

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package mysql
77

88
import (
99
"fmt"
10+
"regexp"
1011
"strconv"
1112
"strings"
1213
)
@@ -15,6 +16,13 @@ const (
1516
DefaultInstancePort = 3306
1617
)
1718

19+
var (
20+
ipv4HostPortRegexp = regexp.MustCompile("^([^:]+):([0-9]+)$")
21+
ipv4HostRegexp = regexp.MustCompile("^([^:]+)$")
22+
ipv6HostPortRegexp = regexp.MustCompile("^\\[([:0-9a-fA-F]+)\\]:([0-9]+)$") // e.g. [2001:db8:1f70::999:de8:7648:6e8]:3308
23+
ipv6HostRegexp = regexp.MustCompile("^([:0-9a-fA-F]+)$") // e.g. 2001:db8:1f70::999:de8:7648:6e8
24+
)
25+
1826
// InstanceKey is an instance indicator, identified by hostname and port
1927
type InstanceKey struct {
2028
Hostname string
@@ -25,25 +33,35 @@ const detachHint = "//"
2533

2634
// ParseInstanceKey will parse an InstanceKey from a string representation such as 127.0.0.1:3306
2735
func NewRawInstanceKey(hostPort string) (*InstanceKey, error) {
28-
tokens := strings.SplitN(hostPort, ":", 2)
29-
if len(tokens) != 2 {
30-
return nil, fmt.Errorf("Cannot parse InstanceKey from %s. Expected format is host:port", hostPort)
36+
hostname := ""
37+
port := ""
38+
if submatch := ipv4HostPortRegexp.FindStringSubmatch(hostPort); len(submatch) > 0 {
39+
hostname = submatch[1]
40+
port = submatch[2]
41+
} else if submatch := ipv4HostRegexp.FindStringSubmatch(hostPort); len(submatch) > 0 {
42+
hostname = submatch[1]
43+
} else if submatch := ipv6HostPortRegexp.FindStringSubmatch(hostPort); len(submatch) > 0 {
44+
hostname = submatch[1]
45+
port = submatch[2]
46+
} else if submatch := ipv6HostRegexp.FindStringSubmatch(hostPort); len(submatch) > 0 {
47+
hostname = submatch[1]
48+
} else {
49+
return nil, fmt.Errorf("Cannot parse address: %s", hostPort)
3150
}
32-
instanceKey := &InstanceKey{Hostname: tokens[0]}
33-
var err error
34-
if instanceKey.Port, err = strconv.Atoi(tokens[1]); err != nil {
35-
return instanceKey, fmt.Errorf("Invalid port: %s", tokens[1])
51+
instanceKey := &InstanceKey{Hostname: hostname, Port: DefaultInstancePort}
52+
if port != "" {
53+
var err error
54+
if instanceKey.Port, err = strconv.Atoi(port); err != nil {
55+
return instanceKey, fmt.Errorf("Invalid port: %s", port)
56+
}
3657
}
3758

3859
return instanceKey, nil
3960
}
4061

41-
// ParseRawInstanceKeyLoose will parse an InstanceKey from a string representation such as 127.0.0.1:3306.
62+
// ParseInstanceKey will parse an InstanceKey from a string representation such as 127.0.0.1:3306.
4263
// The port part is optional; there will be no name resolve
43-
func ParseRawInstanceKeyLoose(hostPort string) (*InstanceKey, error) {
44-
if !strings.Contains(hostPort, ":") {
45-
return &InstanceKey{Hostname: hostPort, Port: DefaultInstancePort}, nil
46-
}
64+
func ParseInstanceKey(hostPort string) (*InstanceKey, error) {
4765
return NewRawInstanceKey(hostPort)
4866
}
4967

go/mysql/instance_key_map.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func (this *InstanceKeyMap) ReadCommaDelimitedList(list string) error {
9292
}
9393
tokens := strings.Split(list, ",")
9494
for _, token := range tokens {
95-
key, err := ParseRawInstanceKeyLoose(token)
95+
key, err := ParseInstanceKey(token)
9696
if err != nil {
9797
return err
9898
}

go/mysql/instance_key_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
Copyright 2016 GitHub Inc.
3+
See https://github.com/github/gh-ost/blob/master/LICENSE
4+
*/
5+
6+
package mysql
7+
8+
import (
9+
"testing"
10+
11+
"github.com/outbrain/golib/log"
12+
test "github.com/outbrain/golib/tests"
13+
)
14+
15+
func init() {
16+
log.SetLevel(log.ERROR)
17+
}
18+
19+
func TestParseInstanceKey(t *testing.T) {
20+
{
21+
key, err := ParseInstanceKey("myhost:1234")
22+
test.S(t).ExpectNil(err)
23+
test.S(t).ExpectEquals(key.Hostname, "myhost")
24+
test.S(t).ExpectEquals(key.Port, 1234)
25+
}
26+
{
27+
key, err := ParseInstanceKey("myhost")
28+
test.S(t).ExpectNil(err)
29+
test.S(t).ExpectEquals(key.Hostname, "myhost")
30+
test.S(t).ExpectEquals(key.Port, 3306)
31+
}
32+
{
33+
key, err := ParseInstanceKey("10.0.0.3:3307")
34+
test.S(t).ExpectNil(err)
35+
test.S(t).ExpectEquals(key.Hostname, "10.0.0.3")
36+
test.S(t).ExpectEquals(key.Port, 3307)
37+
}
38+
{
39+
key, err := ParseInstanceKey("10.0.0.3")
40+
test.S(t).ExpectNil(err)
41+
test.S(t).ExpectEquals(key.Hostname, "10.0.0.3")
42+
test.S(t).ExpectEquals(key.Port, 3306)
43+
}
44+
{
45+
key, err := ParseInstanceKey("[2001:db8:1f70::999:de8:7648:6e8]:3308")
46+
test.S(t).ExpectNil(err)
47+
test.S(t).ExpectEquals(key.Hostname, "2001:db8:1f70::999:de8:7648:6e8")
48+
test.S(t).ExpectEquals(key.Port, 3308)
49+
}
50+
{
51+
key, err := ParseInstanceKey("::1")
52+
test.S(t).ExpectNil(err)
53+
test.S(t).ExpectEquals(key.Hostname, "::1")
54+
test.S(t).ExpectEquals(key.Port, 3306)
55+
}
56+
{
57+
key, err := ParseInstanceKey("0:0:0:0:0:0:0:0")
58+
test.S(t).ExpectNil(err)
59+
test.S(t).ExpectEquals(key.Hostname, "0:0:0:0:0:0:0:0")
60+
test.S(t).ExpectEquals(key.Port, 3306)
61+
}
62+
{
63+
_, err := ParseInstanceKey("[2001:xxxx:1f70::999:de8:7648:6e8]:3308")
64+
test.S(t).ExpectNotNil(err)
65+
}
66+
{
67+
_, err := ParseInstanceKey("10.0.0.4:")
68+
test.S(t).ExpectNotNil(err)
69+
}
70+
{
71+
_, err := ParseInstanceKey("10.0.0.4:5.6.7")
72+
test.S(t).ExpectNotNil(err)
73+
}
74+
}

0 commit comments

Comments
 (0)