diff --git a/.typos.toml b/.typos.toml index 7fb9db2e..a1702340 100644 --- a/.typos.toml +++ b/.typos.toml @@ -61,6 +61,7 @@ extend-ignore-re = [ "RegexXtrabackupISTReceived" = "RegexXtrabackupISTReceived" "START_ND_SUMMARY" = "START_ND_SUMMARY" "START_ND_TOOLTIPS" = "START_ND_TOOLTIPS" +"thr" = "thr" # common abbreviation "TOI" = "TOI" "UNIONed" = "UNIONed" "UNIONs" = "UNIONs" diff --git a/bin/pt-archiver b/bin/pt-archiver index 563d6b6d..2bf7a99f 100755 --- a/bin/pt-archiver +++ b/bin/pt-archiver @@ -3781,7 +3781,8 @@ sub recurse_to_slaves { my $slave_dsn = $dsn; if ($slave_user) { $slave_dsn->{u} = $slave_user; - PTDEBUG && _d("Using slave user $slave_user on ".$slave_dsn->{h}.":".$slave_dsn->{P}); + PTDEBUG && _d("Using slave user $slave_user on " + . $slave_dsn->{h} . ":" . ( $slave_dsn->{P} ? $slave_dsn->{P} : "")); } if ($slave_password) { $slave_dsn->{p} = $slave_password; diff --git a/bin/pt-deadlock-logger b/bin/pt-deadlock-logger index 16176a7a..3b082258 100755 --- a/bin/pt-deadlock-logger +++ b/bin/pt-deadlock-logger @@ -5533,7 +5533,7 @@ is undefined which means an infinite number of iterations. The tool always exits for L<"--run-time">, regardless of the value specified for this option. For example, the tool will exit after 1 minute with C<--run-time 1m --iterations 4 --interval 30> because 4 iterations at 30 -second intervals would take 2 minutes, longer than the 1 mintue run-time. +second intervals would take 2 minutes, longer than the 1 minute run-time. =item --log diff --git a/bin/pt-fk-error-logger b/bin/pt-fk-error-logger index 72ec795e..8c4744d5 100755 --- a/bin/pt-fk-error-logger +++ b/bin/pt-fk-error-logger @@ -4530,7 +4530,7 @@ is undefined which means an infinite number of iterations. The tool always exits for L<"--run-time">, regardless of the value specified for this option. For example, the tool will exit after 1 minute with C<--run-time 1m --iterations 4 --interval 30> because 4 iterations at 30 -second intervals would take 2 minutes, longer than the 1 mintue run-time. +second intervals would take 2 minutes, longer than the 1 minute run-time. =item --log diff --git a/bin/pt-heartbeat b/bin/pt-heartbeat index e03c9001..a0cf5c02 100755 --- a/bin/pt-heartbeat +++ b/bin/pt-heartbeat @@ -242,7 +242,8 @@ sub recurse_to_slaves { my $slave_dsn = $dsn; if ($slave_user) { $slave_dsn->{u} = $slave_user; - PTDEBUG && _d("Using slave user $slave_user on ".$slave_dsn->{h}.":".$slave_dsn->{P}); + PTDEBUG && _d("Using slave user $slave_user on " + . $slave_dsn->{h} . ":" . ( $slave_dsn->{P} ? $slave_dsn->{P} : "")); } if ($slave_password) { $slave_dsn->{p} = $slave_password; diff --git a/bin/pt-ioprofile b/bin/pt-ioprofile index 785e7dfb..ae4f3698 100755 --- a/bin/pt-ioprofile +++ b/bin/pt-ioprofile @@ -408,7 +408,7 @@ _parse_command_line() { fi if $(echo $opt | grep '^[a-z-][a-z-]*=' >/dev/null 2>&1); then - val="$(echo $opt | awk -F= '{print $2}')" + val="$(echo "$opt" | awk '{ st = index($0,"="); print substr($0, st+1)}')" opt="$(echo $opt | awk -F= '{print $1}')" fi @@ -453,7 +453,7 @@ _parse_command_line() { val=$(size_to_bytes $val) fi - eval "OPT_$opt"="'$val'" + eval "OPT_$opt"='$val' opt="" val="" diff --git a/bin/pt-kill b/bin/pt-kill index 38cee058..3c2da447 100755 --- a/bin/pt-kill +++ b/bin/pt-kill @@ -4058,7 +4058,8 @@ sub recurse_to_slaves { my $slave_dsn = $dsn; if ($slave_user) { $slave_dsn->{u} = $slave_user; - PTDEBUG && _d("Using slave user $slave_user on ".$slave_dsn->{h}.":".$slave_dsn->{P}); + PTDEBUG && _d("Using slave user $slave_user on " + . $slave_dsn->{h} . ":" . ( $slave_dsn->{P} ? $slave_dsn->{P} : "")); } if ($slave_password) { $slave_dsn->{p} = $slave_password; diff --git a/bin/pt-mext b/bin/pt-mext index df068aab..42d6f787 100755 --- a/bin/pt-mext +++ b/bin/pt-mext @@ -449,7 +449,7 @@ _parse_command_line() { fi if $(echo $opt | grep '^[a-z-][a-z-]*=' >/dev/null 2>&1); then - val="$(echo $opt | awk -F= '{print $2}')" + val="$(echo "$opt" | awk '{ st = index($0,"="); print substr($0, st+1)}')" opt="$(echo $opt | awk -F= '{print $1}')" fi @@ -494,7 +494,7 @@ _parse_command_line() { val=$(size_to_bytes $val) fi - eval "OPT_$opt"="'$val'" + eval "OPT_$opt"='$val' opt="" val="" diff --git a/bin/pt-mysql-summary b/bin/pt-mysql-summary index 681b153f..8d8bbd54 100755 --- a/bin/pt-mysql-summary +++ b/bin/pt-mysql-summary @@ -410,7 +410,7 @@ _parse_command_line() { fi if $(echo $opt | grep '^[a-z-][a-z-]*=' >/dev/null 2>&1); then - val="$(echo $opt | awk -F= '{print $2}')" + val="$(echo "$opt" | awk '{ st = index($0,"="); print substr($0, st+1)}')" opt="$(echo $opt | awk -F= '{print $1}')" fi @@ -455,7 +455,7 @@ _parse_command_line() { val=$(size_to_bytes $val) fi - eval "OPT_$opt"="'$val'" + eval "OPT_$opt"='$val' opt="" val="" diff --git a/bin/pt-online-schema-change b/bin/pt-online-schema-change index fea52be9..42967021 100755 --- a/bin/pt-online-schema-change +++ b/bin/pt-online-schema-change @@ -4346,7 +4346,8 @@ sub recurse_to_slaves { my $slave_dsn = $dsn; if ($slave_user) { $slave_dsn->{u} = $slave_user; - PTDEBUG && _d("Using slave user $slave_user on ".$slave_dsn->{h}.":".$slave_dsn->{P}); + PTDEBUG && _d("Using slave user $slave_user on " + . $slave_dsn->{h} . ":" . ( $slave_dsn->{P} ? $slave_dsn->{P} : "")); } if ($slave_password) { $slave_dsn->{p} = $slave_password; diff --git a/bin/pt-pmp b/bin/pt-pmp index 0aacb473..8a8b7e0e 100755 --- a/bin/pt-pmp +++ b/bin/pt-pmp @@ -451,7 +451,7 @@ _parse_command_line() { fi if $(echo $opt | grep '^[a-z-][a-z-]*=' >/dev/null 2>&1); then - val="$(echo $opt | awk -F= '{print $2}')" + val="$(echo "$opt" | awk '{ st = index($0,"="); print substr($0, st+1)}')" opt="$(echo $opt | awk -F= '{print $1}')" fi @@ -496,7 +496,7 @@ _parse_command_line() { val=$(size_to_bytes $val) fi - eval "OPT_$opt"="'$val'" + eval "OPT_$opt"='$val' opt="" val="" diff --git a/bin/pt-query-digest b/bin/pt-query-digest index 1ccb8e5a..f12b0063 100755 --- a/bin/pt-query-digest +++ b/bin/pt-query-digest @@ -10652,7 +10652,8 @@ sub recurse_to_slaves { my $slave_dsn = $dsn; if ($slave_user) { $slave_dsn->{u} = $slave_user; - PTDEBUG && _d("Using slave user $slave_user on ".$slave_dsn->{h}.":".$slave_dsn->{P}); + PTDEBUG && _d("Using slave user $slave_user on " + . $slave_dsn->{h} . ":" . ( $slave_dsn->{P} ? $slave_dsn->{P} : "")); } if ($slave_password) { $slave_dsn->{p} = $slave_password; diff --git a/bin/pt-sift b/bin/pt-sift index bbf077cf..9e0c02fe 100755 --- a/bin/pt-sift +++ b/bin/pt-sift @@ -449,7 +449,7 @@ _parse_command_line() { fi if $(echo $opt | grep '^[a-z-][a-z-]*=' >/dev/null 2>&1); then - val="$(echo $opt | awk -F= '{print $2}')" + val="$(echo "$opt" | awk '{ st = index($0,"="); print substr($0, st+1)}')" opt="$(echo $opt | awk -F= '{print $1}')" fi @@ -494,7 +494,7 @@ _parse_command_line() { val=$(size_to_bytes $val) fi - eval "OPT_$opt"="'$val'" + eval "OPT_$opt"='$val' opt="" val="" diff --git a/bin/pt-slave-find b/bin/pt-slave-find index 5c6557d7..3a2b9295 100755 --- a/bin/pt-slave-find +++ b/bin/pt-slave-find @@ -2383,7 +2383,8 @@ sub recurse_to_slaves { my $slave_dsn = $dsn; if ($slave_user) { $slave_dsn->{u} = $slave_user; - PTDEBUG && _d("Using slave user $slave_user on ".$slave_dsn->{h}.":".$slave_dsn->{P}); + PTDEBUG && _d("Using slave user $slave_user on " + . $slave_dsn->{h} . ":" . ( $slave_dsn->{P} ? $slave_dsn->{P} : "")); } if ($slave_password) { $slave_dsn->{p} = $slave_password; diff --git a/bin/pt-slave-restart b/bin/pt-slave-restart index 046a2635..284f0367 100755 --- a/bin/pt-slave-restart +++ b/bin/pt-slave-restart @@ -2794,7 +2794,8 @@ sub recurse_to_slaves { my $slave_dsn = $dsn; if ($slave_user) { $slave_dsn->{u} = $slave_user; - PTDEBUG && _d("Using slave user $slave_user on ".$slave_dsn->{h}.":".$slave_dsn->{P}); + PTDEBUG && _d("Using slave user $slave_user on " + . $slave_dsn->{h} . ":" . ( $slave_dsn->{P} ? $slave_dsn->{P} : "")); } if ($slave_password) { $slave_dsn->{p} = $slave_password; diff --git a/bin/pt-stalk b/bin/pt-stalk index 9f8d86a6..e83228d4 100755 --- a/bin/pt-stalk +++ b/bin/pt-stalk @@ -462,7 +462,7 @@ _parse_command_line() { fi if $(echo $opt | grep '^[a-z-][a-z-]*=' >/dev/null 2>&1); then - val="$(echo $opt | awk -F= '{print $2}')" + val="$(echo "$opt" | awk '{ st = index($0,"="); print substr($0, st+1)}')" opt="$(echo $opt | awk -F= '{print $1}')" fi @@ -507,7 +507,7 @@ _parse_command_line() { val=$(size_to_bytes $val) fi - eval "OPT_$opt"="'$val'" + eval "OPT_$opt"='$val' opt="" val="" diff --git a/bin/pt-summary b/bin/pt-summary index cf000117..983df245 100755 --- a/bin/pt-summary +++ b/bin/pt-summary @@ -417,7 +417,7 @@ _parse_command_line() { fi if $(echo $opt | grep '^[a-z-][a-z-]*=' >/dev/null 2>&1); then - val="$(echo $opt | awk -F= '{print $2}')" + val="$(echo "$opt" | awk '{ st = index($0,"="); print substr($0, st+1)}')" opt="$(echo $opt | awk -F= '{print $1}')" fi @@ -462,7 +462,7 @@ _parse_command_line() { val=$(size_to_bytes $val) fi - eval "OPT_$opt"="'$val'" + eval "OPT_$opt"='$val' opt="" val="" diff --git a/bin/pt-table-checksum b/bin/pt-table-checksum index e0185f9a..78570d60 100755 --- a/bin/pt-table-checksum +++ b/bin/pt-table-checksum @@ -5298,7 +5298,8 @@ sub recurse_to_slaves { my $slave_dsn = $dsn; if ($slave_user) { $slave_dsn->{u} = $slave_user; - PTDEBUG && _d("Using slave user $slave_user on ".$slave_dsn->{h}.":".$slave_dsn->{P}); + PTDEBUG && _d("Using slave user $slave_user on " + . $slave_dsn->{h} . ":" . ( $slave_dsn->{P} ? $slave_dsn->{P} : "")); } if ($slave_password) { $slave_dsn->{p} = $slave_password; diff --git a/bin/pt-table-sync b/bin/pt-table-sync index f2193373..55ca97cd 100755 --- a/bin/pt-table-sync +++ b/bin/pt-table-sync @@ -6812,7 +6812,8 @@ sub recurse_to_slaves { my $slave_dsn = $dsn; if ($slave_user) { $slave_dsn->{u} = $slave_user; - PTDEBUG && _d("Using slave user $slave_user on ".$slave_dsn->{h}.":".$slave_dsn->{P}); + PTDEBUG && _d("Using slave user $slave_user on " + . $slave_dsn->{h} . ":" . ( $slave_dsn->{P} ? $slave_dsn->{P} : "")); } if ($slave_password) { $slave_dsn->{p} = $slave_password; @@ -10230,7 +10231,17 @@ sub main { unshift @dsns, $master; # dsn[0]=master, dsn[1]=slave $dsns[0]->{dbh} = get_cxn($dsns[0], %modules); if ( $o->get('check-master') ) { - $ms->is_master_of($dsns[0]->{dbh}, $dsns[1]->{dbh}); + my $is_master_of = eval { + $ms->is_master_of($dsns[0]->{dbh}, $dsns[1]->{dbh}); + }; + + # We should not die if replica connected via tunnel or port redirection + if ( $EVAL_ERROR ) { + $EVAL_ERROR =~ m/The slave is connected to (\d+) but the master's port is \d+/; + if ( !$1 || $1 != $dsns[0]->{P} ) { + die $EVAL_ERROR; + } + } } } diff --git a/go.mod b/go.mod index 633d746f..3968b439 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.9.0 github.com/xlab/treeprint v1.2.0 - go.mongodb.org/mongo-driver v1.14.0 + go.mongodb.org/mongo-driver v1.15.0 golang.org/x/crypto v0.22.0 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 diff --git a/go.sum b/go.sum index b4437c91..c94791a5 100644 --- a/go.sum +++ b/go.sum @@ -118,8 +118,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= -go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= +go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= diff --git a/lib/MasterSlave.pm b/lib/MasterSlave.pm index 007c4d6d..135411dc 100644 --- a/lib/MasterSlave.pm +++ b/lib/MasterSlave.pm @@ -181,7 +181,8 @@ sub recurse_to_slaves { my $slave_dsn = $dsn; if ($slave_user) { $slave_dsn->{u} = $slave_user; - PTDEBUG && _d("Using slave user $slave_user on ".$slave_dsn->{h}.":".$slave_dsn->{P}); + PTDEBUG && _d("Using slave user $slave_user on " + . $slave_dsn->{h} . ":" . ( $slave_dsn->{P} ? $slave_dsn->{P} : "")); } if ($slave_password) { $slave_dsn->{p} = $slave_password; diff --git a/lib/SchemaIterator.pm b/lib/SchemaIterator.pm index 4336d024..c4b36046 100644 --- a/lib/SchemaIterator.pm +++ b/lib/SchemaIterator.pm @@ -495,7 +495,7 @@ sub table_is_allowed { # then we'll get d1 tables when the user only wants d2 tables. So when # a table passes allow filters, reaching this point, meaning it is allowed, # we make this final to check to see if it's allowed in any database (*) - # or allowed in the specific database that the user qualifed the table with. + # or allowed in the specific database that the user qualified the table with. # The first two checks are to prevent auto-vivifying the filters which will # cause bad results (see a similar comment in _make_filters()). if ( $filter->{'tables'} diff --git a/lib/bash/parse_options.sh b/lib/bash/parse_options.sh index 97fe0c4e..1fee5c6b 100644 --- a/lib/bash/parse_options.sh +++ b/lib/bash/parse_options.sh @@ -475,7 +475,7 @@ _parse_command_line() { # Split opt=val pair. if $(echo $opt | grep '^[a-z-][a-z-]*=' >/dev/null 2>&1); then - val="$(echo $opt | awk -F= '{print $2}')" + val="$(echo "$opt" | awk '{ st = index($0,"="); print substr($0, st+1)}')" opt="$(echo $opt | awk -F= '{print $1}')" fi @@ -533,7 +533,7 @@ _parse_command_line() { fi # Re-eval the option to update its global variable value. - eval "OPT_$opt"="'$val'" + eval "OPT_$opt"='$val' opt="" val="" diff --git a/src/go/docker-compose.yml b/src/go/docker-compose.yml index f9458c45..1c0cb6b1 100644 --- a/src/go/docker-compose.yml +++ b/src/go/docker-compose.yml @@ -186,7 +186,7 @@ services: image: ${TEST_MONGODB_IMAGE:-mongo:4.2} ports: - "${TEST_MONGODB_STANDALONE_PORT:-27017}:27017" - command: mongod --replSet rs1 --shardsvr --port 27017 --oplogSize 16 + command: mongod --port 27017 --oplogSize 16 postgres9: image: ${POSTGRE_IMAGE:-postgres:9.6} container_name: go_postgres9_1 diff --git a/src/go/lib/versioncheck/version_check.go b/src/go/lib/versioncheck/version_check.go index 114b2148..37409908 100644 --- a/src/go/lib/versioncheck/version_check.go +++ b/src/go/lib/versioncheck/version_check.go @@ -73,15 +73,15 @@ func checkUpdates(url string, timeout time.Duration, toolName, version string) ( if err != nil { return "", err } - advices := []Advice{} - err = json.Unmarshal(body, &advices) + var advice []Advice + err = json.Unmarshal(body, &advice) if err != nil { return "", err } - for _, advice := range advices { - if advice.ToolName == PERCONA_TOOLKIT { - return advice.Advice, nil + for _, a := range advice { + if a.ToolName == PERCONA_TOOLKIT { + return a.Advice, nil } } diff --git a/src/go/lib/versioncheck/version_check_test.go b/src/go/lib/versioncheck/version_check_test.go index 0d449df0..357a0e74 100644 --- a/src/go/lib/versioncheck/version_check_test.go +++ b/src/go/lib/versioncheck/version_check_test.go @@ -16,7 +16,7 @@ func TestCheckUpdates(t *testing.T) { body, _ := ioutil.ReadAll(r.Body) m := strings.Split(string(body), ";") - advices := []Advice{ + advice := []Advice{ { Hash: m[0], ToolName: m[1], @@ -24,7 +24,7 @@ func TestCheckUpdates(t *testing.T) { }, } - buf, _ := json.Marshal(advices) + buf, _ := json.Marshal(advice) w.Header().Set("Content-Type", "application/json") fmt.Fprint(w, string(buf)) })) diff --git a/src/go/pt-k8s-debug-collector/dumper/dumper.go b/src/go/pt-k8s-debug-collector/dumper/dumper.go index 92f51a32..b8db95ba 100644 --- a/src/go/pt-k8s-debug-collector/dumper/dumper.go +++ b/src/go/pt-k8s-debug-collector/dumper/dumper.go @@ -451,7 +451,7 @@ func (d *Dumper) getPodSummary(resource, podName, crName string, namespace strin } ports = port + ":27017" summCmdName = "pt-mongodb-summary" - summCmdArgs = []string{"--username='" + user + "'", "--password=" + pass, "--authenticationDatabase=admin", "127.0.0.1:" + port} + summCmdArgs = []string{"--username=" + user, "--password=" + string(pass), "--authenticationDatabase=admin", "127.0.0.1:" + port} } cmdPortFwd := exec.Command(d.cmd, "port-forward", "pod/"+podName, ports, "-n", namespace, "--kubeconfig", d.kubeconfig) diff --git a/src/go/pt-mongodb-summary/main.go b/src/go/pt-mongodb-summary/main.go index 2fb7a209..3dce453c 100644 --- a/src/go/pt-mongodb-summary/main.go +++ b/src/go/pt-mongodb-summary/main.go @@ -374,14 +374,14 @@ func getHostInfo(ctx context.Context, client *mongo.Client) (*hostInfo, error) { } cmdOpts := proto.CommandLineOptions{} - query := primitive.D{{Key: "getCmdLineOpts", Value: 1}, {Key: "recordStats", Value: 1}} + query := primitive.D{{Key: "getCmdLineOpts", Value: 1}} err := client.Database("admin").RunCommand(ctx, query).Decode(&cmdOpts) if err != nil { return nil, errors.Wrap(err, "cannot get command line options") } ss := proto.ServerStatus{} - query = primitive.D{{Key: "serverStatus", Value: 1}, {Key: "recordStats", Value: 1}} + query = primitive.D{{Key: "serverStatus", Value: 1}} if err := client.Database("admin").RunCommand(ctx, query).Decode(&ss); err != nil { return nil, errors.Wrap(err, "GetHostInfo.serverStatus") } @@ -528,7 +528,6 @@ func getSecuritySettings(ctx context.Context, client *mongo.Client, ver string) cmdOpts := proto.CommandLineOptions{} err = client.Database("admin").RunCommand(ctx, primitive.D{ {Key: "getCmdLineOpts", Value: 1}, - {Key: "recordStats", Value: 1}, }).Decode(&cmdOpts) if err != nil { return nil, errors.Wrap(err, "cannot get command line options") @@ -633,7 +632,6 @@ func getOpCountersStats(ctx context.Context, client *mongo.Client, count int, err := client.Database("admin").RunCommand(ctx, primitive.D{ {Key: "serverStatus", Value: 1}, - {Key: "recordStats", Value: 1}, }).Decode(&ss) if err != nil { return nil, err diff --git a/t/pt-mysql-summary/pt-2327.t b/t/pt-mysql-summary/pt-2327.t new file mode 100644 index 00000000..69c68021 --- /dev/null +++ b/t/pt-mysql-summary/pt-2327.t @@ -0,0 +1,77 @@ +#!/usr/bin/env perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use PerconaTest; +use Sandbox; +use DSNParser; +require VersionParser; +use Test::More; + +local $ENV{PTDEBUG} = ""; + +my $dp = new DSNParser(opts=>$dsn_opts); +my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); +my $dbh = $sb->get_dbh_for('master'); +my $cnf = '/tmp/12345/my.sandbox.cnf'; +my $output; + +if ( !$dbh ) { + plan skip_all => 'Cannot connect to sandbox master'; +} +else { + plan tests => 5; +} + +$sb->do_as_root("master", q/create user pt2302 identified by "root_'f<=*password"/); +$sb->do_as_root("master", q/grant all on *.* to pt2302/); + +my $cmd = "$trunk/bin/pt-mysql-summary --sleep 1 -- --defaults-file=$cnf --user=pt2302 --password=\"root_'f<=*password\""; + +$output = `$cmd 2>&1`; + +unlike( + $output, + qr/eval: Syntax error: Unterminated quoted string/s, + "pt-mysql-summary does not stop with password containing an apostrophe" +); + +unlike( + $output, + qr/Access denied for user/s, + "pt-mysql-summary works fine with password containing an apostrophe" +); + +$sb->do_as_root("master", q/drop user pt2302/); +$sb->do_as_root("master", q/create user pt2302 identified by 'root_"f<=*password'/); +$sb->do_as_root("master", q/grant all on *.* to pt2302/); + +$cmd = "$trunk/bin/pt-mysql-summary --sleep 1 -- --defaults-file=$cnf --user=pt2302 --password='root_\"f<=*password'"; + +$output = `$cmd 2>&1`; + +unlike( + $output, + qr/eval: Syntax error: Unterminated quoted string/s, + "pt-mysql-summary does not stop with password containing a quote" +); + +unlike( + $output, + qr/Access denied for user/s, + "pt-mysql-summary works fine with password containing a quote" +); +# ############################################################################# +# Done. +# ############################################################################# +$sb->do_as_root("master", q/drop user pt2302/); +$sb->wipe_clean($dbh); +ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +exit; diff --git a/t/pt-online-schema-change/pt-2231.t b/t/pt-online-schema-change/pt-2231.t new file mode 100644 index 00000000..4ff53406 --- /dev/null +++ b/t/pt-online-schema-change/pt-2231.t @@ -0,0 +1,63 @@ +#!/usr/bin/env perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +use PerconaTest; +use Sandbox; +require "$trunk/bin/pt-online-schema-change"; + +my $dp = new DSNParser(opts=>$dsn_opts); +my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); +my $master_dbh = $sb->get_dbh_for('master'); +my $slave1_dbh = $sb->get_dbh_for('slave1'); +my $slave2_dbh = $sb->get_dbh_for('slave2'); + +if ( !$master_dbh ) { + plan skip_all => 'Cannot connect to sandbox master'; +} +elsif ( !$slave1_dbh ) { + plan skip_all => 'Cannot connect to sandbox slave1'; +} +elsif ( !$slave1_dbh ) { + plan skip_all => 'Cannot connect to sandbox slave2'; +} +else { + plan tests => 2; +} + +$sb->load_file('master', "t/pt-online-schema-change/samples/basic_no_fks.sql"); + +$sb->wait_for_slaves(); + +# Save original PTDEBUG env because we modify it below. +my $dbg = $ENV{PTDEBUG}; + +$ENV{PTDEBUG} = 1; + +my $output = `$trunk/bin/pt-online-schema-change h=localhost,S=/tmp/12345/mysql_sandbox12345.sock,D=pt_osc,t=t --user=msandbox --password=msandbox --slave-user=msandbox --slave-password=msandbox --alter "FORCE" --recursion-method=processlist --no-check-replication-filters --no-check-alter --no-check-plan --chunk-index=PRIMARY --no-version-check --execute 2>&1`; + +unlike( + $output, + qr/Use of uninitialized value in concatenation (.) or string/, + 'No error with PTDEBUG output' +) or diag($output); + +# Restore PTDEBUG env. +delete $ENV{PTDEBUG}; +$ENV{PTDEBUG} = $dbg || 0; + +# ############################################################################# +# Done. +# ############################################################################# +$sb->wipe_clean($master_dbh); +ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +exit; diff --git a/t/pt-table-sync/pt-1194.t b/t/pt-table-sync/pt-1194.t new file mode 100644 index 00000000..6e49b201 --- /dev/null +++ b/t/pt-table-sync/pt-1194.t @@ -0,0 +1,106 @@ +#!/usr/bin/env perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +use PerconaTest; +use Sandbox; +require "$trunk/bin/pt-table-sync"; + +my $dp = new DSNParser(opts=>$dsn_opts); +my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); +my $master_dbh = $sb->get_dbh_for('master'); +my $slave1_dbh = $sb->get_dbh_for('slave1'); +my $slave2_dbh = $sb->get_dbh_for('slave2'); +my $have_ncat = `which ncat 2>/dev/null`; + +if ( !$master_dbh ) { + plan skip_all => 'Cannot connect to sandbox master'; +} +elsif ( !$slave1_dbh ) { + plan skip_all => 'Cannot connect to sandbox slave1'; +} +elsif ( !$slave1_dbh ) { + plan skip_all => 'Cannot connect to sandbox slave2'; +} +elsif (!$have_ncat) { + plan skip_all => 'ncat, required for this test, is not installed or not in PATH'; +} +else { + plan tests => 3; +} + +$sb->load_file('master', "t/pt-table-sync/samples/pt-1205.sql"); +$sb->wait_for_slaves(); + +# Setting up tunnels +my $pid1 = fork(); + +if ( !$pid1 ) { + setpgrp; + system('ncat -k -l localhost 3333 --sh-exec "ncat 127.0.0.1 12345"'); + exit; +} + +my $pid2 = fork(); + +if ( !$pid2 ) { + setpgrp; + system('ncat -k -l localhost 3334 --sh-exec "ncat 127.0.0.1 12346"'); + exit; +} + +my $o = new OptionParser(); +my $q = new Quoter(); +my $ms = new MasterSlave( + OptionParser=>$o, + DSNParser=>$dp, + Quoter=>$q, + ); +my $ss = $ms->get_slave_status($slave1_dbh); + +$slave1_dbh->do('STOP SLAVE'); +$slave1_dbh->do("CHANGE MASTER TO MASTER_PORT=3333, MASTER_LOG_POS=$ss->{exec_master_log_pos}"); +$slave1_dbh->do('START SLAVE'); + +my $output = `$trunk/bin/pt-table-sync h=127.0.0.1,P=3334,u=msandbox,p=msandbox --database=test --table=t1 --sync-to-master --execute --verbose 2>&1`; + +unlike( + $output, + qr/The slave is connected to \d+ but the master's port is/, + 'No error for redirected replica' +) or diag($output); + +kill -1, getpgrp($pid1); +kill -1, getpgrp($pid2); + +$slave1_dbh->do('STOP SLAVE'); +$ss = $ms->get_slave_status($slave1_dbh); +$slave1_dbh->do("CHANGE MASTER TO MASTER_PORT=12347, MASTER_LOG_POS=$ss->{exec_master_log_pos}"); +$slave1_dbh->do('START SLAVE SQL_THREAD'); + +$output = `$trunk/bin/pt-table-sync h=127.0.0.1,P=12346,u=msandbox,p=msandbox --database=test --table=t1 --sync-to-master --execute --verbose 2>&1`; + +like( + $output, + qr/The server specified as a master has no connected slaves/, + 'Error printed for the wrong master' +) or diag($output); + +$slave1_dbh->do('STOP SLAVE'); +$slave1_dbh->do("CHANGE MASTER TO MASTER_PORT=12345, MASTER_LOG_POS=$ss->{exec_master_log_pos}"); +$slave1_dbh->do('START SLAVE'); +# ############################################################################# +# Done. +# ############################################################################# +$sb->wipe_clean($master_dbh); +ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +exit;