Skip to content

Commit 760b566

Browse files
authored
canal: support ipv6 address (#943)
* feat(canal): support ipv6 address * feat: use net.SplitHostPort to parse ip with ports * chore: optimze validate error message * feat(ci): complete test cases * feat(dumper): use net.SplitHostPort to parse address
1 parent f230d5f commit 760b566

File tree

5 files changed

+44
-12
lines changed

5 files changed

+44
-12
lines changed

.github/workflows/ci.yml

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ jobs:
1717
echo -n "mysqldump -V: " ; mysqldump -V
1818
1919
echo -e '[mysqld]\nserver-id=1\nlog-bin=mysql\nbinlog-format=row\ngtid-mode=ON\nenforce_gtid_consistency=ON\n' | sudo tee /etc/mysql/conf.d/replication.cnf
20+
21+
# bind to :: for dual-stack listening
22+
sudo sed -i 's/bind-address.*= 127.0.0.1/bind-address = ::/' /etc/mysql/mysql.conf.d/mysqld.cnf
23+
sudo sed -i 's/mysqlx-bind-address.*= 127.0.0.1/mysqlx-bind-address = ::/' /etc/mysql/mysql.conf.d/mysqld.cnf
24+
2025
sudo service mysql start
2126
2227
# apply this for mysql5 & mysql8 compatibility
@@ -109,5 +114,6 @@ jobs:
109114
uses: actions/setup-go@v5
110115
with:
111116
go-version: "1.22"
117+
112118
- name: Build on ${{ matrix.os }}/${{ matrix.arch }}
113119
run: GOARCH=${{ matrix.arch }} GOOS=${{ matrix.os }} go build ./...

canal/canal.go

+6-7
Original file line numberDiff line numberDiff line change
@@ -481,18 +481,17 @@ func (c *Canal) prepareSyncer() error {
481481
if strings.Contains(c.cfg.Addr, "/") {
482482
cfg.Host = c.cfg.Addr
483483
} else {
484-
seps := strings.Split(c.cfg.Addr, ":")
485-
if len(seps) != 2 {
486-
return errors.Errorf("invalid mysql addr format %s, must host:port", c.cfg.Addr)
484+
host, port, err := net.SplitHostPort(c.cfg.Addr)
485+
if err != nil {
486+
return errors.Errorf("invalid MySQL address format %s, must host:port", c.cfg.Addr)
487487
}
488-
489-
port, err := strconv.ParseUint(seps[1], 10, 16)
488+
portNumber, err := strconv.ParseUint(port, 10, 16)
490489
if err != nil {
491490
return errors.Trace(err)
492491
}
493492

494-
cfg.Host = seps[0]
495-
cfg.Port = uint16(port)
493+
cfg.Host = host
494+
cfg.Port = uint16(portNumber)
496495
}
497496

498497
c.syncer = replication.NewBinlogSyncer(cfg)

canal/canal_test.go

+22-1
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,30 @@ import (
1616
)
1717

1818
type canalTestSuite struct {
19+
addr string
1920
suite.Suite
2021
c *Canal
2122
}
2223

24+
type canalTestSuiteOption func(c *canalTestSuite)
25+
26+
func withAddr(addr string) canalTestSuiteOption {
27+
return func(c *canalTestSuite) {
28+
c.addr = addr
29+
}
30+
}
31+
32+
func newCanalTestSuite(opts ...canalTestSuiteOption) *canalTestSuite {
33+
c := new(canalTestSuite)
34+
for _, opt := range opts {
35+
opt(c)
36+
}
37+
return c
38+
}
39+
2340
func TestCanalSuite(t *testing.T) {
24-
suite.Run(t, new(canalTestSuite))
41+
suite.Run(t, newCanalTestSuite())
42+
suite.Run(t, newCanalTestSuite(withAddr(mysql.DEFAULT_IPV6_ADDR)))
2543
}
2644

2745
const (
@@ -37,6 +55,9 @@ const (
3755
func (s *canalTestSuite) SetupSuite() {
3856
cfg := NewDefaultConfig()
3957
cfg.Addr = fmt.Sprintf("%s:%s", *test_util.MysqlHost, *test_util.MysqlPort)
58+
if s.addr != "" {
59+
cfg.Addr = s.addr
60+
}
4061
cfg.User = "root"
4162
cfg.HeartbeatPeriod = 200 * time.Millisecond
4263
cfg.ReadTimeout = 300 * time.Millisecond

dump/dumper.go

+9-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"fmt"
66
"io"
7+
"net"
78
"os"
89
"os/exec"
910
"regexp"
@@ -212,10 +213,14 @@ func (d *Dumper) Dump(w io.Writer) error {
212213
if strings.Contains(d.Addr, "/") {
213214
args = append(args, fmt.Sprintf("--socket=%s", d.Addr))
214215
} else {
215-
seps := strings.SplitN(d.Addr, ":", 2)
216-
args = append(args, fmt.Sprintf("--host=%s", seps[0]))
217-
if len(seps) > 1 {
218-
args = append(args, fmt.Sprintf("--port=%s", seps[1]))
216+
host, port, err := net.SplitHostPort(d.Addr)
217+
if err != nil {
218+
host = d.Addr
219+
}
220+
221+
args = append(args, fmt.Sprintf("--host=%s", host))
222+
if port != "" {
223+
args = append(args, fmt.Sprintf("--port=%s", port))
219224
}
220225
}
221226

mysql/const.go

+1
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ const (
172172

173173
const (
174174
DEFAULT_ADDR = "127.0.0.1:3306"
175+
DEFAULT_IPV6_ADDR = "[::1]:3306"
175176
DEFAULT_USER = "root"
176177
DEFAULT_PASSWORD = ""
177178
DEFAULT_FLAVOR = "mysql"

0 commit comments

Comments
 (0)