Compare commits

...

15 Commits

Author SHA1 Message Date
Carlos Salguero
aca7e6a83e PT-1528 Ingore UTF8 warning 2020-12-16 15:18:23 -03:00
Carlos Salguero
15ffa974eb PT-1528 [WIP] Proposed solution 2020-11-22 18:58:00 -03:00
Carlos Salguero
ff6b05b381 PT-1891 Fixed mongodb-summary connection with ssl (#469)
* PT-1891 Fixed mongodb-summary connection with ssl

- Added SSL connection options
- Fixed old tests
- Replaced gofmt by gofumpt in Makefile
- There are no ssl test for mongodb-summary because the current sandbox
doesnt support it

* PT-1891 Ran gofumports

* PMM-1891 Fixes for CR

* PT-1891 Decreased minimum TLS reqs for compatibility
2020-11-02 17:13:29 -03:00
Carlos Salguero
e731cf4d83 PT-1881 Updated changelog 2020-10-27 19:17:02 -03:00
Nayuta Yanagisawa
442a099268 PT-1881: Fix missing argument error of pt-upgrade (#461)
* Fix missing argument error of pt-upgrade

* Use print rather than printf
2020-10-27 19:15:21 -03:00
Jaroslav Musil
fc4e86928b [PMM-6756] Added go 1.15.x. (#468) 2020-10-19 15:22:08 +02:00
Carlos Salguero
03bd58e3a3 Updated changelog 2020-10-13 08:26:34 -03:00
Carlos Salguero
d7a7a1c7a5 PT-169 Handle drop-swap errors in pt-online-schema-change (#467)
* PT-169 Fixed drop-swap error handling

* PT-169 Fixed drop_swap error handling
2020-10-12 15:36:45 -03:00
Carlos Salguero
1090f017a1 Updated changelog 2020-09-30 11:06:15 -03:00
Carlos Salguero
a8ea8dfe56 PT-1892 Fixed sshd process recognition (#465) 2020-09-30 11:04:34 -03:00
Carlos Salguero
0aac7b4cfc PMM-6494 Topology labels (#463)
* PMM-6494 Topology labels

Added common functions needed for topology lables in mongo exporter and
pt-mongodb-summary

* PMM-5723 Fix reviewdog.

Co-authored-by: Nurlan Moldomurov <nurlan.moldomurov@percona.com>
2020-09-08 19:48:09 +03:00
Alexey Palazhchenko
d7ece0aecc Add go.mod (#464)
* Add go.mod

* Update github.com/shirou/gopsutil

* Use released version of dep

* Disable modules in CI for now

* PMM-5723 Fix reviewdog.

Co-authored-by: Nurlan Moldomurov <nurlan.moldomurov@percona.com>
2020-09-08 17:20:19 +03:00
PaulJacobs-percona
ff8b0aff84 Update release_notes.rst
Don't expose email
2020-08-17 10:03:26 +03:00
Paul Jacobs
db7dee46b6 3.2.1 RNs 2020-08-17 10:01:02 +03:00
PaulJacobs-percona
ecaaf4cc42 Merge pull request #460 from percona/release-3.2.1
3.2.1 release branch
2020-08-17 09:39:11 +03:00
55 changed files with 1834 additions and 273 deletions

View File

@@ -1,6 +1,7 @@
language: go
go:
- 1.15.x
- 1.14.x
- tip
@@ -9,6 +10,7 @@ services:
env:
global:
- GO111MODULE: "off" # TODO test with "on" too
- DOCKER_COMPOSE_VERSION: 1.8.0
- TEST_MONGODB_FLAVOR: mongo
- TEST_PSMDB_VERSION: 4.0
@@ -35,7 +37,7 @@ env:
- TEST_MONGODB_S3_SECONDARY1_PORT: 17022
- TEST_MONGODB_S3_SECONDARY2_PORT: 17023
# REVIEWDOG_GITHUB_API_TOKEN
- secure: "px8XYeNEAFTSTb1hYZuEOxqOXUxvp3EoU+KCtPck/KNozkoS95eBd9klgr3Os4wPKloLdMhrr0VE98lukogUxA/NmnYnos01kegjWgwwM6fkob8JxaN5KK4oUFF1wmirBlrjGlw8vUErPwINmrK4BywKpDbw6Yip6FzxdlWESHI="
secure: "iba+2pzxc/zfMxnYki9qM9pCZs1uTEoqfPTaG9qtVr8cMutDzCJvMftn0bb6gSUrglt2mjSNhV65HX7mZl0qh8p/6a46QpzFiwZmaTH+E1tGQf97Z55tx3tHgrcoFI8LGPEHpTQehcI7V0VVo69aBhz+8lNNScOuJwt8ulyuVwE="
matrix:
include:
@@ -61,8 +63,9 @@ before_install:
- docker-compose --version
install:
- go get -u github.com/golang/dep/cmd/dep
# install reviewdog and golangci-lin
- curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
# install reviewdog and golangci-lint
- curl https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh| sh -s
- curl https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s latest

View File

@@ -1,5 +1,9 @@
Changelog for Percona Toolkit
* Fixed bug PT-169 : pt-online-schema-change FKs error handling.
* Fixed bug PT-1892: pt-summary says sshd not running
* Fixed bug PT-1881: pt-upgrade fails when query including format strings and SQL errors is given (Thanks Nayuta Yanagisawa)
* Fixed bug PT-1859: pt-pg-summary fails for Postgres12 (Thanks Sergey Kuzmichev)
* Improvement PT-1853: Added --no-check-foreing-keys to pt-osc
* Improvement PT-1851: Backslashes missing from documentation

45
Gopkg.lock generated
View File

@@ -202,7 +202,15 @@
version = "v1.0.0"
[[projects]]
digest = "1:55dcddb2ba6ab25098ee6b96f176f39305f1fde7ea3d138e7e10bb64a5bf45be"
digest = "1:9d1d58facb0409ecf634fec680d83b6f57f4e619458f7b7b5e4dda1665fd89ec"
name = "github.com/prometheus/common"
packages = ["log"]
pruneopts = ""
revision = "f39dfa2b000545b3a763b844012958c275a62266"
version = "v0.13.0"
[[projects]]
digest = "1:9d35a914be9b807050704f377becb1f864ee46b000f590566a8b9fb871d6c571"
name = "github.com/shirou/gopsutil"
packages = [
"cpu",
@@ -212,16 +220,8 @@
"process",
]
pruneopts = ""
revision = "e4ec7b275ada47ca32799106c2dba142d96aaf93"
version = "v2.19.8"
[[projects]]
branch = "master"
digest = "1:99c6a6dab47067c9b898e8c8b13d130c6ab4ffbcc4b7cc6236c2cd0b1e344f5b"
name = "github.com/shirou/w32"
packages = ["."]
pruneopts = ""
revision = "bb4de0191aa41b5507caa14b0650cdbddcd9280b"
revision = "9aa2bee419e8b592ecf9f46018f3f1f6a5474c10"
version = "v2.20.8"
[[projects]]
digest = "1:1a405cddcf3368445051fb70ab465ae99da56ad7be8d8ca7fc52159d1c2d873c"
@@ -324,6 +324,8 @@
packages = [
"unix",
"windows",
"windows/registry",
"windows/svc/eventlog",
]
pruneopts = ""
revision = "749cb33beabd9aa6d3178e3de05bcc914f70b2bf"
@@ -343,6 +345,25 @@
revision = "342b2e1fbaa52c93f31447ad2c6abc048c63e475"
version = "v0.3.2"
[[projects]]
digest = "1:15d017551627c8bb091bde628215b2861bed128855343fdd570c62d08871f6e1"
name = "gopkg.in/alecthomas/kingpin.v2"
packages = ["."]
pruneopts = ""
revision = "947dcec5ba9c011838740e680966fd7087a71d0d"
version = "v2.2.6"
[[projects]]
branch = "v2"
digest = "1:e56755c5336ff37d20befca76df29097085c85ea1fe58af746e3df6b815decfa"
name = "gopkg.in/mgo.v2"
packages = [
"bson",
"internal/json",
]
pruneopts = ""
revision = "a6b53ec6cb22a3699387a57a161566f9402ee85b"
[[projects]]
branch = "v3"
digest = "1:2e9c4d6def1d36dcd17730e00c06b49a2e97ea5e1e639bcd24fa60fa43e33ad6"
@@ -368,6 +389,7 @@
"github.com/pborman/getopt",
"github.com/percona/go-mysql/query",
"github.com/pkg/errors",
"github.com/prometheus/common/log",
"github.com/shirou/gopsutil/process",
"github.com/sirupsen/logrus",
"github.com/stretchr/testify/assert",
@@ -377,6 +399,7 @@
"go.mongodb.org/mongo-driver/mongo",
"go.mongodb.org/mongo-driver/mongo/options",
"golang.org/x/crypto/ssh/terminal",
"gopkg.in/mgo.v2/bson",
]
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -24,4 +24,4 @@
[[constraint]]
name = "github.com/shirou/gopsutil"
version = "2.17.11"
version = "2.20.8"

View File

@@ -8387,6 +8387,7 @@ package pt_online_schema_change;
use strict;
use warnings FATAL => 'all';
use utf8;
use English qw(-no_match_vars);
use Percona::Toolkit;
@@ -8474,7 +8475,7 @@ sub main {
@drop_trigger_sqls = ();
@triggers_not_dropped = ();
$dont_interrupt_now = 0;
%ignore_code = (1592 => 1, 1062 => 1);
%ignore_code = (1592 => 1, 1062 => 1, 1300 => 1);
my %stats = (
INSERT => 0,
@@ -8788,6 +8789,7 @@ sub main {
my $flow_ctl_pr; # Progress for FlowControlWaiter
my $sys_load; # MySQLStatusWaiter object
my $sys_load_pr; # Progress for MySQLStatusWaiter object
my $process_error; # Used if drop_swap fails
if ( $o->get('execute') ) {
# #####################################################################
@@ -9414,6 +9416,9 @@ sub main {
. "cause MySQL error 1146 (42S02): \"Table $new_tbl->{name} "
. " doesn't exist\".\n";
}
elsif ($process_error) {
print "Not dropping new table because FKs processing has failed.\n";
}
else {
print ts("Dropping new table...\n");
print $sql, "\n" if $o->get('print');
@@ -10208,8 +10213,9 @@ sub main {
}
};
if ( $EVAL_ERROR ) {
# TODO: improve error message and handling.
_die("Error updating foreign key constraints: $EVAL_ERROR", ERROR_UPDATING_FKS);
#$oktorun = 0;
$process_error = "Error updating foreign key constraints: $EVAL_ERROR";
_die($process_error, ERROR_UPDATING_FKS);
}
# --plugin hook
@@ -10273,6 +10279,7 @@ sub main {
# ########################################################################
# Done.
# ########################################################################
$orig_tbl->{success} = 1; # flag for cleanup tasks
$cleanup = undef; # exec cleanup tasks

View File

@@ -1278,7 +1278,7 @@ top_processes () { local PTFUNCNAME=top_processes;
notable_processes_info () { local PTFUNCNAME=notable_processes_info;
local format="%5s %+2d %s\n"
local sshd_pid=$(ps -eo pid,args | awk '$2 ~ /\/usr\/sbin\/sshd/ { print $1; exit }')
local sshd_pid=$(ps -eo pid,args | awk '$0 ~ /\/usr\/sbin\/sshd/ { print $1; exit }')
echo " PID OOM COMMAND"

View File

@@ -6159,7 +6159,7 @@ sub _print_failures {
foreach my $failure ( @$failures ) {
print "\n-- $failno.\n";
if ( ($failure->[1] || '') eq ($failure->[2] || '') ) {
printf "\nOn both hosts:\n\n" . ($failure->[1] || '') . "\n";
print "\nOn both hosts:\n\n" . ($failure->[1] || '') . "\n";
}
else {
printf "\n%s\n\nvs.\n\n%s\n",

View File

@@ -1,6 +1,28 @@
Percona Toolkit
***************
v3.2.1 released 2020-08-13
==========================
Improvements:
* :jirabug:`PT-1836`: Review and consider lintian reported issues (Thanks to user midget for reporting this issue)
Bugs Fixed:
* :jirabug:`PT-1853`: Added --no-check-foreign-keys to pt-osc
* :jirabug:`PT-1869`: pt-osc dynamically update slave list on check slaves (Thanks to user mateus.dubiela for reporting this issue)
* :jirabug:`PT-1829`: pt-heartbeat doesn't reconnect for check-read-only
* :jirabug:`PT-1822`: pt-mongodb-summary fails on standalone mongodb instances
* :jirabug:`PT-1851`: Backslashes missing from documentation (Thanks to user billkarwin for reporting this issue)
* :jirabug:`PT-1518`: pt-table-checksum gives error CRC32 never needs BIT_XOR optimization (Thanks to user soumya_s_das (AT homedepot DOT com) for reporting this issue)
* :jirabug:`PT-1859`: pt-pg-summary fails for Postgres12
v3.2.0 released 2020-04-23
==========================

28
docs/rn.3-2-1.txt Normal file
View File

@@ -0,0 +1,28 @@
.. _PT-3.2.1:
================================================================================
*Percona Toolkit* 3.2.1
================================================================================
:Date: August 13, 2020
:Installation: `Installing Percona Toolkit <https://www.percona.com/doc/percona-toolkit/LATEST/installation.html>`_
Improvements
================================================================================
* :jirabug:`PT-1836`: Review and consider lintian reported issues (Thanks to user midget for reporting this issue)
Bugs Fixed
================================================================================
* :jirabug:`PT-1853`: Added --no-check-foreign-keys to pt-osc
* :jirabug:`PT-1869`: pt-osc dynamically update slave list on check slaves (Thanks to user mateus.dubiela for reporting this issue)
* :jirabug:`PT-1829`: pt-heartbeat doesn't reconnect for check-read-only
* :jirabug:`PT-1822`: pt-mongodb-summary fails on standalone mongodb instances
* :jirabug:`PT-1851`: Backslashes missing from documentation (Thanks to user billkarwin for reporting this issue)
* :jirabug:`PT-1518`: pt-table-checksum gives error CRC32 never needs BIT_XOR optimization (Thanks to user soumya_s_das@homedepot.com for reporting this issue)
* :jirabug:`PT-1859`: pt-pg-summary fails for Postgres12

40
go.mod Normal file
View File

@@ -0,0 +1,40 @@
module github.com/percona/percona-toolkit
go 1.14
require (
github.com/Masterminds/semver v1.4.2
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
github.com/alecthomas/kingpin v2.2.6+incompatible
github.com/go-ini/ini v1.46.0
github.com/go-ole/go-ole v1.2.4 // indirect
github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129
github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf // indirect
github.com/google/go-cmp v0.5.2 // indirect
github.com/google/uuid v1.1.1
github.com/hashicorp/go-version v1.2.1-0.20190424083514-192140e6f3e6
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c
github.com/klauspost/compress v1.10.10 // indirect
github.com/lib/pq v1.2.0
github.com/mattn/go-shellwords v1.0.6
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe
github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3
github.com/percona/go-mysql v0.0.0-20190903141930-197f4ad8db8d
github.com/pkg/errors v0.9.1
github.com/prometheus/common v0.13.0
github.com/shirou/gopsutil v2.20.8+incompatible
github.com/sirupsen/logrus v1.6.0
github.com/stretchr/testify v1.6.1
github.com/xdg/stringprep v1.0.1-0.20180714160509-73f8eece6fdc // indirect
go.mongodb.org/mongo-driver v1.3.4
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 // indirect
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect
golang.org/x/text v0.3.3 // indirect
golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/ini.v1 v1.61.0 // indirect
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
mvdan.cc/gofumpt v0.0.0-20200927160801-5bfeb2e70dd6 // indirect
)

539
go.sum Normal file
View File

@@ -0,0 +1,539 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/alecthomas/kingpin v2.2.6+incompatible h1:5svnBTFgJjZvGKyYBtMB0+m5wvrbUHiqye8wRJMlnYI=
github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-ini/ini v1.46.0 h1:hDJFfs/9f75875scvqLkhNB5Jz5/DybKEOZ5MLF+ng4=
github.com/go-ini/ini v1.46.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129 h1:tT8iWCYw4uOem71yYA3htfH+LNopJvcqZQshm56G5L4=
github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf h1:gFVkHXmVAhEbxZVDln5V9GKrLaluNoFHDbrZwAWZgws=
github.com/golang/snappy v0.0.2-0.20190904063534-ff6b7dc882cf/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.1-0.20190424083514-192140e6f3e6 h1:rL76JewpeImeqMtpkAHVZkHrXWt6B5sGSj6sAsL0VnI=
github.com/hashicorp/go-version v1.2.1-0.20190424083514-192140e6f3e6/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0=
github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I=
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-shellwords v1.0.6 h1:9Jok5pILi5S1MnDirGVTufYGtksUs/V2BWUP3ZkeUUI=
github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3 h1:YtFkrqsMEj7YqpIhRteVxJxCeC3jJBieuLr0d4C4rSA=
github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
github.com/percona/go-mysql v0.0.0-20190903141930-197f4ad8db8d h1:ZkztfR4jYDnkFQtZfwMVm9z7wkK/WiCXRQ7l1CB1/1M=
github.com/percona/go-mysql v0.0.0-20190903141930-197f4ad8db8d/go.mod h1:/SGLf9OMxlnK6jq4mkFiImBcJXXk5jwD+lDrwDaGXcw=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.13.0 h1:vJlpe9wPgDRM1Z+7Wj3zUUjY1nr6/1jNKyl7llliccg=
github.com/prometheus/common v0.13.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shirou/gopsutil v2.20.8+incompatible h1:8c7Atn0FAUZJo+f4wYbN0iVpdWniCQk7IYwGtgdh1mY=
github.com/shirou/gopsutil v2.20.8+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/xdg/stringprep v1.0.1-0.20180714160509-73f8eece6fdc h1:vIp1tjhVogU0yBy7w96P027ewvNPeH6gzuNcoc+NReU=
github.com/xdg/stringprep v1.0.1-0.20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.mongodb.org/mongo-driver v1.3.4 h1:zs/dKNwX0gYUtzwrN9lLiR15hCO0nDwQj5xXx+vjCdE=
go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200731060945-b5fad4ed8dd6 h1:qKpj8TpV+LEhel7H/fR788J+KvhWZ3o3V6N2fU/iuLU=
golang.org/x/tools v0.0.0-20200731060945-b5fad4ed8dd6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6 h1:rbvTkL9AkFts1cgI78+gG6Yu1pwaqX6hjSJAatB78E4=
golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/ini.v1 v1.61.0 h1:LBCdW4FmFYL4s/vDZD1RQYX7oAR6IjujCYgMdbHBR10=
gopkg.in/ini.v1 v1.61.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
mvdan.cc/gofumpt v0.0.0-20200927160801-5bfeb2e70dd6 h1:z+/YqapuV7VZPvBb3GYmuEJbA88M3PFUxaHilHYVCpQ=
mvdan.cc/gofumpt v0.0.0-20200927160801-5bfeb2e70dd6/go.mod h1:bzrjFmaD6+xqohD3KYP0H2FEuxknnBmyyOxdhLdaIws=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=

View File

@@ -405,7 +405,7 @@ sub _print_failures {
foreach my $failure ( @$failures ) {
print "\n-- $failno.\n";
if ( ($failure->[1] || '') eq ($failure->[2] || '') ) {
printf "\nOn both hosts:\n\n" . ($failure->[1] || '') . "\n";
print "\nOn both hosts:\n\n" . ($failure->[1] || '') . "\n";
}
else {
printf "\n%s\n\nvs.\n\n%s\n",

View File

@@ -138,8 +138,8 @@ test: ## Run tests
@./runtests.sh
format: ## Format source code.
gofmt -w -s $(FILES)
goimports -local github.com/percona/pmm-managed -l -w $(FILES)
gofumpt -w -s $(FILES)
gofumports -local github.com/percona/pmm-managed -l -w $(FILES)
vet: ## Run vet on Go code
@echo ">> vetting code"

View File

@@ -1,11 +1,16 @@
package testutils
import (
"context"
"net"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
const (
@@ -143,30 +148,70 @@ func BaseDir() string {
}
basedir = strings.TrimSpace(string(out))
return basedir
}
// GetMongoDBAddr returns the address of an instance by replicaset name and instance type like
// (rs1, primary) or (rs1, secondary1)
// (rs1, primary) or (rs1, secondary1).
func GetMongoDBAddr(rs, name string) string {
if _, ok := hosts[rs]; !ok {
return ""
}
replset := hosts[rs]
if host, ok := replset[name]; ok {
return host
}
return ""
}
// GetMongoDBReplsetAddrs return the addresses of all instances for a replicaset name
// GetMongoDBReplsetAddrs return the addresses of all instances for a replicaset name.
func GetMongoDBReplsetAddrs(rs string) []string {
addrs := []string{}
if _, ok := hosts[rs]; !ok {
return addrs
}
for _, host := range hosts[rs] {
addrs = append(addrs, host)
}
return addrs
}
// TestClient returns a new MongoDB connection to the specified server port.
func TestClient(ctx context.Context, port string) (*mongo.Client, error) {
if port == "" {
port = MongoDBShard1PrimaryPort
}
hostname := "127.0.0.1"
direct := true
to := time.Second
co := &options.ClientOptions{
ConnectTimeout: &to,
Hosts: []string{net.JoinHostPort(hostname, port)},
Direct: &direct,
Auth: &options.Credential{
Username: MongoDBUser,
Password: MongoDBPassword,
PasswordSet: true,
},
}
client, err := mongo.Connect(ctx, co)
if err != nil {
return nil, err
}
err = client.Ping(ctx, nil)
if err != nil {
return nil, err
}
return client, nil
}

View File

@@ -75,10 +75,8 @@ func DefaultConfigFiles(toolName string) ([]string, error) {
}
func DefaultConfig(toolname string) *Config {
files, _ := DefaultConfigFiles(toolname)
return NewConfig(files...)
}
func NewConfig(files ...string) *Config {
@@ -94,7 +92,6 @@ func NewConfig(files ...string) *Config {
}
func read(filename string, opts map[string]interface{}) error {
f, err := os.Open(filename)
if err != nil {
return err

View File

@@ -11,7 +11,6 @@ import (
)
func TestReadConfig(t *testing.T) {
rootPath, err := tutil.RootPath()
if err != nil {
t.Errorf("cannot get root path: %s", err)
@@ -69,7 +68,6 @@ func TestReadConfig(t *testing.T) {
}
func TestOverrideConfig(t *testing.T) {
rootPath, err := tutil.RootPath()
if err != nil {
t.Errorf("cannot get root path: %s", err)
@@ -131,7 +129,6 @@ func TestOverrideConfig(t *testing.T) {
}
func TestDefaultFiles(t *testing.T) {
user, _ := user.Current()
toolname := "pt-testing"
@@ -150,5 +147,4 @@ func TestDefaultFiles(t *testing.T) {
if !reflect.DeepEqual(got, want) {
t.Errorf("got %#v\nwant: %#v\n", got, want)
}
}

View File

@@ -5,8 +5,8 @@ import (
"regexp"
"time"
"github.com/percona/percona-toolkit/src/go/pt-pg-summary/models"
"github.com/hashicorp/go-version"
"github.com/percona/percona-toolkit/src/go/pt-pg-summary/models"
"github.com/pkg/errors"
"github.com/shirou/gopsutil/process"
"github.com/sirupsen/logrus"

View File

@@ -108,17 +108,15 @@ func LoadBson(filename string, destination interface{}) error {
}
func WriteJson(filename string, data interface{}) error {
buf, err := json.MarshalIndent(data, "", " ")
if err != nil {
return err
}
err = ioutil.WriteFile(filename, buf, 0777)
err = ioutil.WriteFile(filename, buf, 0o777)
if err != nil {
return err
}
return nil
}
func ShouldUpdateSamples() bool {

View File

@@ -12,7 +12,6 @@ import (
)
func TestCheckUpdates(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, _ := ioutil.ReadAll(r.Body)
m := strings.Split(string(body), ";")
@@ -39,11 +38,9 @@ func TestCheckUpdates(t *testing.T) {
if msg == "" {
t.Error("got empty response")
}
}
func TestEmptyResponse(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "")
}))
@@ -57,5 +54,4 @@ func TestEmptyResponse(t *testing.T) {
if msg != "" {
t.Error("response should return error due to empty body")
}
}

View File

@@ -11,10 +11,8 @@ import (
"go.mongodb.org/mongo-driver/mongo"
)
var (
// DocsBufferSize is the buffer size to store documents from the MongoDB profiler
DocsBufferSize = 100
)
var DocsBufferSize = 100
// Profiler interface
type Profiler interface {

View File

@@ -34,9 +34,11 @@ type OpLogs []OplogInfo
func (s OpLogs) Len() int {
return len(s)
}
func (s OpLogs) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s OpLogs) Less(i, j int) bool {
return s[i].TimeDiffHours < s[j].TimeDiffHours
}

View File

@@ -0,0 +1,30 @@
package proto
import "time"
type ProcInfo struct {
CreateTime time.Time
Path string
UserName string
Error error
}
type GetHostInfo struct {
Hostname string
HostOsType string
HostSystemCPUArch string
HostDatabases int
HostCollections int
DBPath string
ProcPath string
ProcUserName string
ProcCreateTime time.Time
ProcProcessCount int
// Server Status
ProcessName string
ReplicasetName string
Version string
NodeType string
}

View File

@@ -4,8 +4,11 @@ import (
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ReplicaSetConfigTags map[string]string
type GetLastErrorModes map[string]*ReplicaSetConfigTags
type (
ReplicaSetConfigTags map[string]string
GetLastErrorModes map[string]*ReplicaSetConfigTags
)
// https://docs.mongodb.com/v3.2/reference/command/getLastError/#dbcmd.getLastError
type GetLastErrorDefaults struct {

View File

@@ -1,6 +1,9 @@
package proto
import "go.mongodb.org/mongo-driver/bson/primitive"
import (
"go.mongodb.org/mongo-driver/bson/primitive"
"gopkg.in/mgo.v2/bson"
)
const (
REPLICA_SET_MEMBER_STARTUP = iota
@@ -48,3 +51,83 @@ type ReplicaSetStatus struct {
Ok float64 `bson:"ok"` //
Set string `bson:"set"` // Replica set name
}
type Member struct {
Host string `bson:"host"`
Votes int32 `bson:"votes"`
ID int32 `bson:"_id"`
SlaveDelay int64 `bson:"slaveDelay"`
Priority float64 `bson:"priority"`
BuildIndexes bool `bson:"buildIndexes"`
ArbiterOnly bool `bson:"arbiterOnly"`
Hidden bool `bson:"hidden"`
Tags bson.M `bson:"tags"`
}
type RSConfig struct {
ID string `bson:"_id"`
ConfigServer bool `bson:"configsvr"`
WriteConcernMajorityJournalDefault bool `bson:"writeConcernMajorityJournalDefault"`
Version int32 `bson:"version"`
ProtocolVersion int64 `bson:"protocolVersion"`
Settings RSSettings `bson:"settings"`
Members []Member `bson:"members"`
}
type LastErrorDefaults struct {
W int32 `bson:"w"`
WTimeout int32 `bson:"wtimeout"`
}
type RSSettings struct {
HeartbeatTimeoutSecs int32 `bson:"heartbeatTimeoutSecs"`
ElectionTimeoutMillis int32 `bson:"electionTimeoutMillis"`
CatchUpTimeoutMillis int32 `bson:"catchUpTimeoutMillis"`
GetLastErrorModes bson.M `bson:"getLastErrorModes"`
ChainingAllowed bool `bson:"chainingAllowed"`
HeartbeatIntervalMillis int32 `bson:"heartbeatIntervalMillis"`
CatchUpTakeoverDelayMillis int32 `bson:"catchUpTakeoverDelayMillis"`
GetLastErrorDefaults LastErrorDefaults `bson:"getLastErrorDefaults"`
ReplicaSetID primitive.ObjectID `bson:"replicaSetId"`
}
type Signature struct {
Hash primitive.Binary `bson:"hash"`
KeyID int64 `bson:"keyId"`
}
type ClusterTime struct {
ClusterTime primitive.Timestamp `bson:"clusterTime"`
Signature Signature `bson:"signature"`
}
type ReplicasetConfig struct {
Config RSConfig `bson:"config"`
OK float64 `bson:"ok"`
LastCommittedOpTime primitive.Timestamp `bson:"lastCommittedOpTime"`
ClusterTime ClusterTime `bson:"$clusterTime"`
OperationTime primitive.Timestamp `bson:"operationTime"`
}
type ConfigVersion struct {
ID int32 `bson:"_id"`
MinCompatibleVersion int32 `bson:"minCompatibleVersion"`
CurrentVersion int32 `bson:"currentVersion"`
ClusterID primitive.ObjectID `bson:"clusterId"`
}
type ShardIdentity struct {
ID string `bson:"_id"`
ShardName string `bson:"shardName"`
ClusterID primitive.ObjectID `bson:"clusterId"`
ConfigsvrConnectionString string `bson:"configsvrConnectionString"`
}
// MyState is a subset of getDiagnosticData result used to tag metrics in the MongoDB exporter
type MyState struct {
Data struct {
ReplicasetGetStatus struct {
MyState int `bson:"myState"`
} `bson:"replSetGetStatus"`
} `bson:"data"`
}

View File

@@ -2,23 +2,39 @@ package util
import (
"context"
"fmt"
"sort"
"strings"
"time"
"github.com/percona/percona-toolkit/src/go/mongolib/proto"
"github.com/pkg/errors"
"github.com/prometheus/common/log"
"github.com/shirou/gopsutil/process"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"gopkg.in/mgo.v2/bson"
)
const (
TypeIsDBGrid = "isdbgrid"
TypeMongos = "mongos"
TypeMongod = "mongod"
TypeShardServer = "shardsvr"
milliToSeconds = 1000
shardingNotEnabledErrorCode = 203
ErrNotYetInitialized = int32(94)
ErrNoReplicationEnabled = int32(76)
)
var (
CannotGetQueryError = errors.New("cannot get query field from the profile document (it is not a map)")
ShardingNotEnabledError = errors.New("sharding not enabled")
ErrCannotGetProcess = fmt.Errorf("cannot get process")
ErrCannotGetClusterID = fmt.Errorf("cannot get cluster ID")
)
func GetReplicasetMembers(ctx context.Context, clientOptions *options.ClientOptions) ([]proto.Members, error) {
@@ -26,6 +42,7 @@ func GetReplicasetMembers(ctx context.Context, clientOptions *options.ClientOpti
if err != nil {
return nil, errors.Wrap(err, "cannot get a new client for GetReplicasetMembers")
}
if err := client.Connect(ctx); err != nil {
return nil, errors.Wrap(err, "cannot connect to MongoDB")
}
@@ -34,6 +51,7 @@ func GetReplicasetMembers(ctx context.Context, clientOptions *options.ClientOpti
if err != nil {
return nil, err
}
if err := client.Disconnect(ctx); err != nil {
return nil, errors.Wrapf(err, "cannot disconnect from %v", clientOptions.Hosts)
}
@@ -54,7 +72,10 @@ func GetReplicasetMembers(ctx context.Context, clientOptions *options.ClientOpti
cmdOpts := proto.CommandLineOptions{}
// Not always we can get this info. For examples, we cannot get this for hidden hosts so
// if there is an error, just ignore it
res := client.Database("admin").RunCommand(ctx, primitive.D{{"getCmdLineOpts", 1}, {"recordStats", 1}})
res := client.Database("admin").RunCommand(ctx, primitive.D{
{Key: "getCmdLineOpts", Value: 1},
{Key: "recordStats", Value: 1},
})
if res.Err() == nil {
if err := res.Decode(&cmdOpts); err != nil {
return nil, errors.Wrapf(err, "cannot decode getCmdLineOpts response for host %s", hostname)
@@ -62,6 +83,7 @@ func GetReplicasetMembers(ctx context.Context, clientOptions *options.ClientOpti
}
rss := proto.ReplicaSetStatus{}
res = client.Database("admin").RunCommand(ctx, primitive.M{"replSetGetStatus": 1})
if res.Err() != nil {
m := proto.Members{
@@ -73,26 +95,34 @@ func GetReplicasetMembers(ctx context.Context, clientOptions *options.ClientOpti
m.ID = serverStatus.Pid
m.StorageEngine = serverStatus.StorageEngine
}
membersMap[m.Name] = m
continue // If a host is a mongos we cannot get info but is not a real error
}
if err := res.Decode(&rss); err != nil {
return nil, errors.Wrap(err, "cannot decode replSetGetStatus response")
}
for _, m := range rss.Members {
if _, ok := membersMap[m.Name]; ok {
continue // already exists
}
m.Set = rss.Set
if serverStatus, err := GetServerStatus(ctx, client); err == nil {
m.ID = serverStatus.Pid
m.StorageEngine = serverStatus.StorageEngine
if cmdOpts.Parsed.Sharding.ClusterRole != "" {
m.StateStr = cmdOpts.Parsed.Sharding.ClusterRole + "/" + m.StateStr
}
m.StateStr = strings.ToUpper(m.StateStr)
}
membersMap[m.Name] = m
}
@@ -104,30 +134,36 @@ func GetReplicasetMembers(ctx context.Context, clientOptions *options.ClientOpti
}
sort.Slice(members, func(i, j int) bool { return members[i].Name < members[j].Name })
return members, nil
}
func GetHostnames(ctx context.Context, client *mongo.Client) ([]string, error) {
// Probably we are connected to an individual member of a replica set
rss := proto.ReplicaSetStatus{}
res := client.Database("admin").RunCommand(ctx, primitive.M{"replSetGetStatus": 1})
if res.Err() == nil {
if err := res.Decode(&rss); err != nil {
return nil, errors.Wrap(err, "cannot decode replSetGetStatus response for GetHostnames")
}
return buildHostsListFromReplStatus(rss), nil
}
// Try getShardMap first. If we are connected to a mongos it will return
// all hosts, including config hosts
var shardsMap proto.ShardsMap
smRes := client.Database("admin").RunCommand(ctx, primitive.M{"getShardMap": 1})
if smRes.Err() != nil {
if e, ok := smRes.Err().(mongo.CommandError); ok && e.Code == shardingNotEnabledErrorCode {
return nil, ShardingNotEnabledError // standalone instance
}
return nil, errors.Wrap(smRes.Err(), "cannot getShardMap for GetHostnames")
}
if err := smRes.Decode(&shardsMap); err != nil {
return nil, errors.Wrap(err, "cannot decode getShardMap result for GetHostnames")
}
@@ -145,7 +181,6 @@ func GetHostnames(ctx context.Context, client *mongo.Client) ([]string, error) {
return nil, nil // standalone instance
}
func buildHostsListFromReplStatus(replStatus proto.ReplicaSetStatus) []string {
/*
"members" : [
{
@@ -163,17 +198,17 @@ func buildHostsListFromReplStatus(replStatus proto.ReplicaSetStatus) []string {
"self" : true
},
*/
func buildHostsListFromReplStatus(replStatus proto.ReplicaSetStatus) []string {
hostnames := []string{}
for _, member := range replStatus.Members {
hostnames = append(hostnames, member.Name)
}
sort.Strings(hostnames) // to make testing easier
return hostnames
}
func buildHostsListFromShardMap(shardsMap proto.ShardsMap) []string {
/* Example
mongos> db.getSiblingDB('admin').runCommand('getShardMap')
{
@@ -184,9 +219,9 @@ func buildHostsListFromShardMap(shardsMap proto.ShardsMap) []string {
"r1/localhost:17001,localhost:17002,localhost:17003" : "r1/localhost:17001,localhost:17002,localhost:17003",
},
"ok" : 1
}
}.
*/
func buildHostsListFromShardMap(shardsMap proto.ShardsMap) []string {
hostnames := []string{}
hm := make(map[string]bool)
@@ -197,10 +232,11 @@ func buildHostsListFromShardMap(shardsMap proto.ShardsMap) []string {
for _, val := range shardsMap.Map {
m := strings.Split(val, "/")
hostsStr := ""
switch len(m) {
case 1:
hostsStr = m[0] // there is no / in the hosts list
case 2:
case 2: //nolint
hostsStr = m[1] // there is a / in the string. Remove the prefix until the / and keep the rest
}
// since there is no Sets in Go, build a map where the value is the map key
@@ -209,33 +245,39 @@ func buildHostsListFromShardMap(shardsMap proto.ShardsMap) []string {
hm[host] = false
}
}
for host := range hm {
hostnames = append(hostnames, host)
}
}
sort.Strings(hostnames)
return hostnames
}
// GetShardedHosts is like GetHostnames but it uses listShards instead of getShardMap
// so it won't include config servers in the returned list
// so it won't include config servers in the returned list.
func GetShardedHosts(ctx context.Context, client *mongo.Client) ([]string, error) {
shardsInfo := &proto.ShardsInfo{}
res := client.Database("admin").RunCommand(ctx, primitive.M{"listShards": 1})
if res.Err() != nil {
return nil, errors.Wrap(res.Err(), "cannot list shards")
}
if err := res.Decode(&shardsInfo); err != nil {
return nil, errors.Wrap(err, "cannot decode listShards response")
}
hostnames := []string{}
for _, shardInfo := range shardsInfo.Shards {
m := strings.Split(shardInfo.Host, "/")
h := strings.Split(m[1], ",")
hostnames = append(hostnames, h[0])
}
return hostnames, nil
}
@@ -248,6 +290,7 @@ func GetServerStatus(ctx context.Context, client *mongo.Client) (proto.ServerSta
{Key: "recordStats", Value: 1},
}
res := client.Database("admin").RunCommand(ctx, query)
if res.Err() != nil {
return ss, errors.Wrap(res.Err(), "GetHostInfo.serverStatus")
}
@@ -265,14 +308,17 @@ func GetQueryField(doc proto.SystemProfile) (primitive.M, error) {
// however MongoDB 3.0 doesn't have that field
// so we need to detect protocol by looking at actual data.
query := doc.Query
if len(doc.Command) > 0 {
if len(doc.Command) > 0 { //nolint
query = doc.Command
if doc.Op == "update" || doc.Op == "remove" {
if squery, ok := query.Map()["q"]; ok {
// just an extra check to ensure this type assertion won't fail
if ssquery, ok := squery.(primitive.M); ok {
return ssquery, nil
}
return nil, CannotGetQueryError
}
}
@@ -309,6 +355,7 @@ func GetQueryField(doc proto.SystemProfile) (primitive.M, error) {
if ssquery, ok := squery.(primitive.M); ok {
return ssquery, nil
}
return nil, CannotGetQueryError
}
@@ -317,6 +364,7 @@ func GetQueryField(doc proto.SystemProfile) (primitive.M, error) {
if ssquery, ok := squery.(primitive.M); ok {
return ssquery, nil
}
return nil, CannotGetQueryError
}
@@ -333,5 +381,173 @@ func GetQueryField(doc proto.SystemProfile) (primitive.M, error) {
func GetClientForHost(co *options.ClientOptions, newHost string) (*mongo.Client, error) {
newOptions := options.MergeClientOptions(co, &options.ClientOptions{Hosts: []string{newHost}})
newOptions.SetDirect(true)
return mongo.NewClient(newOptions)
}
func GetHostInfo(ctx context.Context, client *mongo.Client) (*proto.GetHostInfo, error) {
hi := proto.HostInfo{}
if err := client.Database("admin").RunCommand(ctx, primitive.M{"hostInfo": 1}).Decode(&hi); err != nil {
log.Debugf("run('hostInfo') error: %s", err)
return nil, errors.Wrap(err, "GetHostInfo.hostInfo")
}
cmdOpts := proto.CommandLineOptions{}
query := primitive.D{{Key: "getCmdLineOpts", Value: 1}, {Key: "recordStats", 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}}
if err := client.Database("admin").RunCommand(ctx, query).Decode(&ss); err != nil {
return nil, errors.Wrap(err, "GetHostInfo.serverStatus")
}
pi := proto.ProcInfo{}
if err := fillProcInfo(int32(ss.Pid), &pi); err != nil {
pi.Error = err
}
nodeType, _ := getNodeType(ctx, client)
procCount, _ := countMongodProcesses()
i := &proto.GetHostInfo{
Hostname: hi.System.Hostname,
HostOsType: hi.Os.Type,
HostSystemCPUArch: hi.System.CpuArch,
DBPath: "", // Sets default. It will be overridden later if necessary
ProcessName: ss.Process,
ProcProcessCount: procCount,
Version: ss.Version,
NodeType: nodeType,
ProcPath: pi.Path,
ProcUserName: pi.UserName,
ProcCreateTime: pi.CreateTime,
}
if ss.Repl != nil {
i.ReplicasetName = ss.Repl.SetName
}
if cmdOpts.Parsed.Storage.DbPath != "" {
i.DBPath = cmdOpts.Parsed.Storage.DbPath
}
return i, nil
}
func ClusterID(ctx context.Context, client *mongo.Client) (string, error) {
var cv proto.ConfigVersion
if err := client.Database("config").Collection("version").FindOne(ctx, bson.M{}).Decode(&cv); err == nil {
return cv.ClusterID.Hex(), nil
}
var si proto.ShardIdentity
filter := bson.M{"_id": "shardIdentity"}
if err := client.Database("admin").Collection("system.version").FindOne(ctx, filter).Decode(&si); err == nil {
return si.ClusterID.Hex(), nil
}
rc, err := ReplicasetConfig(ctx, client)
if err != nil {
if e, ok := err.(mongo.CommandError); ok && IsReplicationNotEnabledError(e) {
return "", nil
}
return "", err
}
return rc.Config.Settings.ReplicaSetID.Hex(), nil
}
func IsReplicationNotEnabledError(err mongo.CommandError) bool {
return err.Code == ErrNotYetInitialized || err.Code == ErrNoReplicationEnabled
}
func MyState(ctx context.Context, client *mongo.Client) (int, error) {
var ms proto.MyState
if err := client.Database("admin").RunCommand(ctx, bson.M{"getDiagnosticData": 1}).Decode(&ms); err != nil {
return 0, err
}
return ms.Data.ReplicasetGetStatus.MyState, nil
}
func ReplicasetConfig(ctx context.Context, client *mongo.Client) (*proto.ReplicasetConfig, error) {
var rs proto.ReplicasetConfig
if err := client.Database("admin").RunCommand(ctx, bson.M{"replSetGetConfig": 1}).Decode(&rs); err != nil {
return nil, err
}
return &rs, nil
}
func fillProcInfo(pid int32, procInfo *proto.ProcInfo) error {
proc, err := process.NewProcess(pid)
if err != nil {
return errors.Wrapf(ErrCannotGetProcess, "%s", err)
}
ct, err := proc.CreateTime()
if err != nil {
return err
}
procInfo.CreateTime = time.Unix(ct/milliToSeconds, 0)
if procInfo.Path, err = proc.Exe(); err != nil {
return err
}
if procInfo.UserName, err = proc.Username(); err != nil {
return err
}
return nil
}
func getNodeType(ctx context.Context, client *mongo.Client) (string, error) {
md := proto.MasterDoc{}
if err := client.Database("admin").RunCommand(ctx, primitive.M{"isMaster": 1}).Decode(&md); err != nil {
return "", err
}
if md.SetName != nil || md.Hosts != nil {
return TypeShardServer, nil
} else if md.Msg == TypeIsDBGrid {
// isdbgrid is always the msg value when calling isMaster on a mongos
// see http://docs.mongodb.org/manual/core/sharded-cluster-query-router/
return TypeMongos, nil
}
return TypeMongod, nil
}
func countMongodProcesses() (int, error) {
pids, err := process.Pids()
if err != nil {
return 0, err
}
count := 0
for _, pid := range pids {
p, err := process.NewProcess(pid)
if err != nil {
continue
}
if name, _ := p.Name(); name == TypeMongod || name == TypeMongos {
count++
}
}
return count, nil
}

View File

@@ -8,6 +8,7 @@ import (
"time"
tu "github.com/percona/percona-toolkit/src/go/internal/testutils"
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
@@ -21,33 +22,57 @@ func TestGetHostnames(t *testing.T) {
}{
{
name: "from_mongos",
uri: fmt.Sprintf("mongodb://%s:%s@%s:%s", tu.MongoDBUser, tu.MongoDBPassword, tu.MongoDBHost, tu.MongoDBMongosPort),
uri: fmt.Sprintf("mongodb://%s:%s@%s:%s",
tu.MongoDBUser,
tu.MongoDBPassword,
tu.MongoDBHost,
tu.MongoDBMongosPort,
),
want: []string{"127.0.0.1:17001", "127.0.0.1:17002", "127.0.0.1:17004", "127.0.0.1:17005", "127.0.0.1:17007"},
wantError: false,
},
{
name: "from_mongod",
uri: fmt.Sprintf("mongodb://%s:%s@%s:%s", tu.MongoDBUser, tu.MongoDBPassword, tu.MongoDBHost, tu.MongoDBShard1PrimaryPort),
uri: fmt.Sprintf("mongodb://%s:%s@%s:%s",
tu.MongoDBUser,
tu.MongoDBPassword,
tu.MongoDBHost,
tu.MongoDBShard1PrimaryPort,
),
want: []string{"127.0.0.1:17001", "127.0.0.1:17002", "127.0.0.1:17003"},
wantError: false,
},
{
name: "from_non_sharded",
uri: fmt.Sprintf("mongodb://%s:%s@%s:%s", tu.MongoDBUser, tu.MongoDBPassword, tu.MongoDBHost, tu.MongoDBShard3PrimaryPort),
uri: fmt.Sprintf("mongodb://%s:%s@%s:%s",
tu.MongoDBUser,
tu.MongoDBPassword,
tu.MongoDBHost,
tu.MongoDBShard3PrimaryPort,
),
want: []string{"127.0.0.1:17021", "127.0.0.1:17022", "127.0.0.1:17023"},
wantError: false,
},
{
name: "from_standalone",
uri: fmt.Sprintf("mongodb://%s:%s@%s:%s", tu.MongoDBUser, tu.MongoDBPassword, tu.MongoDBHost, tu.MongoDBStandalonePort),
uri: fmt.Sprintf("mongodb://%s:%s@%s:%s",
tu.MongoDBUser,
tu.MongoDBPassword,
tu.MongoDBHost,
tu.MongoDBStandalonePort,
),
want: nil,
wantError: true,
},
}
for _, test := range testCases {
uri := test.uri
want := test.want
wantError := test.wantError
t.Run(test.name, func(t *testing.T) {
client, err := mongo.NewClient(options.Client().ApplyURI(test.uri))
client, err := mongo.NewClient(options.Client().ApplyURI(uri))
if err != nil {
t.Fatalf("cannot get a new MongoDB client: %s", err)
}
@@ -59,12 +84,12 @@ func TestGetHostnames(t *testing.T) {
}
hostnames, err := GetHostnames(ctx, client)
if err != nil && !test.wantError {
if err != nil && !wantError {
t.Errorf("Expecting error=nil, got: %v", err)
}
if !reflect.DeepEqual(hostnames, test.want) {
t.Errorf("Invalid hostnames. Got: %+v, want %+v", hostnames, test.want)
if !reflect.DeepEqual(hostnames, want) {
t.Errorf("Invalid hostnames. Got: %+v, want %+v", hostnames, want)
}
})
}
@@ -194,3 +219,139 @@ func TestGetShardedHosts(t *testing.T) {
})
}
}
func TestReplicasetConfig(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
tcs := []struct {
port string
wantID string
wantConfigServer bool
wantError error
}{
{
port: tu.MongoDBStandalonePort,
wantID: "",
wantConfigServer: false,
wantError: mongo.CommandError{
Code: 76,
Message: "not running with --replSet",
Labels: []string(nil),
Name: "NoReplicationEnabled",
},
},
{
port: tu.MongoDBMongosPort,
wantID: "",
wantConfigServer: false,
wantError: mongo.CommandError{
Code: 59,
Message: "no such cmd: replSetGetConfig",
Labels: []string(nil),
Name: "CommandNotFound",
},
},
{
port: tu.MongoDBShard1PrimaryPort,
wantID: "rs1",
wantConfigServer: false,
},
{
port: tu.MongoDBConfigsvr1Port,
wantID: "csReplSet",
wantConfigServer: true,
},
}
for _, tc := range tcs {
client, err := tu.TestClient(ctx, tc.port)
assert.NoError(t, err)
rs, err := ReplicasetConfig(ctx, client)
assert.Equal(t, tc.wantError, err, fmt.Sprintf("%v", tc.port))
if tc.wantError != nil {
continue
}
assert.Equal(t, tc.wantID, rs.Config.ID)
assert.Equal(t, tc.wantConfigServer, rs.Config.ConfigServer)
assert.NotEmpty(t, rs.Config.Settings.ReplicaSetID.Hex())
}
}
func TestClusterID(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
tcs := []struct {
port string
emptyID bool
}{
{
port: tu.MongoDBMongosPort,
emptyID: false,
},
{
port: tu.MongoDBShard1PrimaryPort,
emptyID: false,
},
{
port: tu.MongoDBShard1Secondary1Port,
emptyID: false,
},
{
port: tu.MongoDBConfigsvr1Port,
emptyID: false,
},
{
port: tu.MongoDBStandalonePort,
emptyID: true,
},
}
for _, tc := range tcs {
client, err := tu.TestClient(ctx, tc.port)
assert.NoError(t, err)
cid, err := ClusterID(ctx, client)
assert.NoError(t, err, fmt.Sprintf("port: %v", tc.port))
assert.Equal(t, cid == "", tc.emptyID)
}
}
func TestMyState(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
tcs := []struct {
port string
want int
}{
{
port: tu.MongoDBShard1PrimaryPort,
want: 1,
},
{
port: tu.MongoDBShard1Secondary1Port,
want: 2,
},
{
port: tu.MongoDBMongosPort,
want: 0,
},
{
port: tu.MongoDBStandalonePort,
want: 0,
},
}
for _, tc := range tcs {
client, err := tu.TestClient(ctx, tc.port)
assert.NoError(t, err)
state, err := MyState(ctx, client)
assert.NoError(t, err)
assert.Equal(t, tc.want, state, fmt.Sprintf("port: %v", tc.port))
}
}

View File

@@ -70,7 +70,6 @@ type report struct {
}
func main() {
opts, err := getOptions()
if err != nil {
log.Errorf("error processing command line arguments: %s", err)
@@ -193,7 +192,6 @@ func main() {
}
fmt.Println(string(out))
}
func formatResults(rep report, outputFormat string) ([]byte, error) {
@@ -368,7 +366,6 @@ func getHeaders(opts *cliOptions) []string {
}
func getQueryTemplate() string {
t := `
# Query {{.Rank}}: {{printf "% 0.2f" .QPS}} QPS, ID {{.ID}}
# Ratio {{Format .Ratio 7.2}} (docs scanned/returned)
@@ -522,7 +519,6 @@ func sortQueries(queries []stats.QueryStats, orderby []string) []stats.QueryStat
OrderedBy(sortFuncs...).Sort(queries)
return queries
}
func isProfilerEnabled(ctx context.Context, clientOptions *options.ClientOptions) (bool, error) {

View File

@@ -3,11 +3,16 @@ package main
import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"html/template"
"io/ioutil"
"net"
"os"
"os/user"
"path/filepath"
"strings"
"time"
@@ -39,18 +44,23 @@ const (
DefaultOutputFormat = "text"
typeMongos = "mongos"
// Exit Codes
// Exit Codes.
cannotFormatResults = 1
cannotParseCommandLineParameters = 2
cannotGetHostInfo = 3
cannotGetReplicasetMembers = 4
cannotGetClientOptions = 4
cannotConnectToMongoDB = 5
)
//nolint:gochecknoglobals
var (
Build string = "2020-04-23" // nolint
GoVersion string = "1.14.1" // nolint
Build string = "2020-04-23"
GoVersion string = "1.14.1"
Version string = "3.2.0"
Commit string
defaultConnectionTimeout = 3 * time.Second
directConnection = true
)
type TimedStats struct {
@@ -69,6 +79,7 @@ type opCounters struct {
Command TimedStats
SampleRate time.Duration
}
type hostInfo struct {
Hostname string
HostOsType string
@@ -164,14 +175,11 @@ func main() {
opts, err := parseFlags()
if err != nil {
log.Errorf("cannot get parameters: %s", err.Error())
os.Exit(cannotParseCommandLineParameters)
}
if opts == nil && err == nil {
return
}
if opts.Help {
getopt.Usage()
if opts == nil && err == nil {
return
}
@@ -187,6 +195,7 @@ func main() {
fmt.Printf("Version %s\n", Version)
fmt.Printf("Build: %s using %s\n", Build, GoVersion)
fmt.Printf("Commit: %s\n", Commit)
return
}
@@ -201,34 +210,46 @@ func main() {
}
ctx := context.Background()
clientOptions := getClientOptions(opts)
clientOptions, err := getClientOptions(opts)
if err != nil {
log.Error(err)
os.Exit(cannotGetClientOptions)
}
client, err := mongo.NewClient(clientOptions)
if err != nil {
log.Fatalf("Cannot get a MongoDB client: %s", err)
log.Errorf("Cannot get a MongoDB client: %s", err)
os.Exit(cannotConnectToMongoDB)
}
if err := client.Connect(ctx); err != nil {
log.Fatalf("Cannot connect to MongoDB: %s", err)
log.Errorf("Cannot connect to MongoDB: %s", err)
os.Exit(cannotConnectToMongoDB)
}
defer client.Disconnect(ctx) // nolint
hostnames, err := util.GetHostnames(ctx, client)
if err != nil && errors.Is(err, util.ShardingNotEnabledError) {
log.Errorf("Cannot get hostnames: %s", err)
}
log.Debugf("hostnames: %v", hostnames)
ci := &collectedInfo{}
ci.HostInfo, err = getHostInfo(ctx, client)
if err != nil {
message := fmt.Sprintf("Cannot get host info for %q: %s", opts.Host, err.Error())
log.Errorf(message)
os.Exit(cannotGetHostInfo)
log.Errorf("Cannot get host info for %q: %s", opts.Host, err)
os.Exit(cannotGetHostInfo) //nolint:gocritic
}
if ci.ReplicaMembers, err = util.GetReplicasetMembers(ctx, clientOptions); err != nil {
log.Warnf("[Error] cannot get replicaset members: %v\n", err)
}
log.Debugf("replicaMembers:\n%+v\n", ci.ReplicaMembers)
if opts.RunningOpsSamples > 0 && opts.RunningOpsInterval > 0 {
@@ -274,9 +295,10 @@ func main() {
out, err := formatResults(ci, opts.OutputFormat)
if err != nil {
log.Errorf("Cannot format the results: %s", err.Error())
log.Errorf("Cannot format the results: %s", err)
os.Exit(cannotFormatResults)
}
fmt.Println(string(out))
}
@@ -287,8 +309,9 @@ func formatResults(ci *collectedInfo, format string) ([]byte, error) {
case "json":
b, err := json.MarshalIndent(ci, "", " ")
if err != nil {
return nil, fmt.Errorf("[Error] Cannot convert results to json: %s", err.Error())
return nil, errors.Wrap(err, "Cannot convert results to json")
}
buf = bytes.NewBuffer(b)
default:
buf = new(bytes.Buffer)
@@ -338,6 +361,7 @@ func getHostInfo(ctx context.Context, client *mongo.Client) (*hostInfo, error) {
hi := proto.HostInfo{}
if err := client.Database("admin").RunCommand(ctx, primitive.M{"hostInfo": 1}).Decode(&hi); err != nil {
log.Debugf("run('hostInfo') error: %s", err)
return nil, errors.Wrap(err, "GetHostInfo.hostInfo")
}
@@ -393,12 +417,15 @@ func countMongodProcesses() (int, error) {
if err != nil {
return 0, err
}
count := 0
for _, pid := range pids {
p, err := process.NewProcess(pid)
if err != nil {
continue
}
if name, _ := p.Name(); name == "mongod" || name == typeMongos {
count++
}
@@ -440,6 +467,7 @@ func getClusterwideInfo(ctx context.Context, client *mongo.Client) (*clusterwide
if collStats.Sharded {
cwi.ShardedDataSize += collStats.Size
cwi.ShardedColsCount++
continue
}
@@ -464,11 +492,14 @@ func sizeAndUnit(size int64) (float64, string) {
unit := []string{"bytes", "KB", "MB", "GB", "TB"}
idx := 0
newSize := float64(size)
for newSize > 1024 {
newSize /= 1024
idx++
}
newSize = float64(int64(newSize*100)) / 100
return newSize, unit[idx]
}
@@ -486,7 +517,10 @@ func getSecuritySettings(ctx context.Context, client *mongo.Client, ver string)
}
cmdOpts := proto.CommandLineOptions{}
err = client.Database("admin").RunCommand(ctx, primitive.D{{"getCmdLineOpts", 1}, {"recordStats", 1}}).Decode(&cmdOpts)
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")
}
@@ -503,7 +537,7 @@ func getSecuritySettings(ctx context.Context, client *mongo.Client, ver string)
s.BindIP = cmdOpts.Parsed.Net.BindIP
s.Port = cmdOpts.Parsed.Net.Port
if cmdOpts.Parsed.Net.BindIP == "" {
if cmdOpts.Parsed.Net.BindIP == "" { //nolint:nestif
if prior26 {
s.WarningMsgs = append(s.WarningMsgs, "WARNING: You might be insecure. There is no IP binding")
}
@@ -586,7 +620,11 @@ func getOpCountersStats(ctx context.Context, client *mongo.Client, count int,
// count + 1 because we need 1st reading to stablish a base to measure variation
for i := 0; i < count+1; i++ {
<-ticker.C
err := client.Database("admin").RunCommand(ctx, primitive.D{{"serverStatus", 1}, {"recordStats", 1}}).Decode(&ss)
err := client.Database("admin").RunCommand(ctx, primitive.D{
{Key: "serverStatus", Value: 1},
{Key: "recordStats", Value: 1},
}).Decode(&ss)
if err != nil {
return nil, err
}
@@ -598,6 +636,7 @@ func getOpCountersStats(ctx context.Context, client *mongo.Client, count int,
prevOpCount.Insert.Total = ss.Opcounters.Insert
prevOpCount.Query.Total = ss.Opcounters.Query
prevOpCount.Update.Total = ss.Opcounters.Update
continue
}
@@ -631,57 +670,63 @@ func getOpCountersStats(ctx context.Context, client *mongo.Client, count int,
}
// Insert --------------------------------------
if delta.Opcounters.Insert > oc.Insert.Max {
switch {
case delta.Opcounters.Insert > oc.Insert.Max:
oc.Insert.Max = delta.Opcounters.Insert
}
if delta.Opcounters.Insert < oc.Insert.Min {
case delta.Opcounters.Insert < oc.Insert.Min:
oc.Insert.Min = delta.Opcounters.Insert
}
oc.Insert.Total += delta.Opcounters.Insert
// Query ---------------------------------------
if delta.Opcounters.Query > oc.Query.Max {
switch {
case delta.Opcounters.Query > oc.Query.Max:
oc.Query.Max = delta.Opcounters.Query
}
if delta.Opcounters.Query < oc.Query.Min {
case delta.Opcounters.Query < oc.Query.Min:
oc.Query.Min = delta.Opcounters.Query
}
oc.Query.Total += delta.Opcounters.Query
// Command -------------------------------------
if delta.Opcounters.Command > oc.Command.Max {
switch {
case delta.Opcounters.Command > oc.Command.Max:
oc.Command.Max = delta.Opcounters.Command
}
if delta.Opcounters.Command < oc.Command.Min {
case delta.Opcounters.Command < oc.Command.Min:
oc.Command.Min = delta.Opcounters.Command
}
oc.Command.Total += delta.Opcounters.Command
// Update --------------------------------------
if delta.Opcounters.Update > oc.Update.Max {
switch {
case delta.Opcounters.Update > oc.Update.Max:
oc.Update.Max = delta.Opcounters.Update
}
if delta.Opcounters.Update < oc.Update.Min {
case delta.Opcounters.Update < oc.Update.Min:
oc.Update.Min = delta.Opcounters.Update
}
oc.Update.Total += delta.Opcounters.Update
// Delete --------------------------------------
if delta.Opcounters.Delete > oc.Delete.Max {
switch {
case delta.Opcounters.Delete > oc.Delete.Max:
oc.Delete.Max = delta.Opcounters.Delete
}
if delta.Opcounters.Delete < oc.Delete.Min {
case delta.Opcounters.Delete < oc.Delete.Min:
oc.Delete.Min = delta.Opcounters.Delete
}
oc.Delete.Total += delta.Opcounters.Delete
// GetMore -------------------------------------
if delta.Opcounters.GetMore > oc.GetMore.Max {
switch {
case delta.Opcounters.GetMore > oc.GetMore.Max:
oc.GetMore.Max = delta.Opcounters.GetMore
}
if delta.Opcounters.GetMore < oc.GetMore.Min {
case delta.Opcounters.GetMore < oc.GetMore.Min:
oc.GetMore.Min = delta.Opcounters.GetMore
}
oc.GetMore.Total += delta.Opcounters.GetMore
prevOpCount.Insert.Total = ss.Opcounters.Insert
@@ -690,8 +735,8 @@ func getOpCountersStats(ctx context.Context, client *mongo.Client, count int,
prevOpCount.Update.Total = ss.Opcounters.Update
prevOpCount.Delete.Total = ss.Opcounters.Delete
prevOpCount.GetMore.Total = ss.Opcounters.GetMore
}
ticker.Stop()
oc.Insert.Avg = oc.Insert.Total
@@ -710,8 +755,9 @@ func getProcInfo(pid int32, templateData *procInfo) error {
// proc, err := process.NewProcess(templateData.ServerStatus.Pid)
proc, err := process.NewProcess(pid)
if err != nil {
return fmt.Errorf("cannot get process %d", pid)
return errors.New(fmt.Sprintf("cannot get process %d", pid))
}
ct, err := proc.CreateTime()
if err != nil {
return err
@@ -742,6 +788,7 @@ func GetBalancerStats(ctx context.Context, client *mongo.Client) (*proto.Balance
event := item.Id.Event
note := item.Id.Note
count := item.Count
switch event {
case "moveChunk.to", "moveChunk.from", "moveChunk.commit":
if note == "success" || note == "" {
@@ -760,7 +807,7 @@ func GetBalancerStats(ctx context.Context, client *mongo.Client) (*proto.Balance
}
func GetShardingChangelogStatus(ctx context.Context, client *mongo.Client) (*proto.ShardingChangelogStats, error) {
var qresults []proto.ShardingChangelogSummary
qresults := []proto.ShardingChangelogSummary{}
coll := client.Database("config").Collection("changelog")
match := primitive.M{"time": primitive.M{"$gt": time.Now().Add(-240 * time.Hour)}}
group := primitive.M{"_id": primitive.M{"event": "$what", "note": "$details.note"}, "count": primitive.M{"$sum": 1}}
@@ -776,6 +823,7 @@ func GetShardingChangelogStatus(ctx context.Context, client *mongo.Client) (*pro
if err := cursor.Decode(&res); err != nil {
return nil, errors.Wrap(err, "cannot decode GetShardingChangelogStatus")
}
qresults = append(qresults, res)
}
@@ -796,6 +844,7 @@ func isPrivateNetwork(ip string) (bool, error) {
if err != nil {
return false, err
}
addr := net.ParseIP(ip)
if cidrnet.Contains(addr) {
return true, nil
@@ -803,7 +852,6 @@ func isPrivateNetwork(ip string) (bool, error) {
}
return false, nil
}
func externalIP() (string, error) {
@@ -811,17 +859,21 @@ func externalIP() (string, error) {
if err != nil {
return "", err
}
for _, iface := range ifaces {
if iface.Flags&net.FlagUp == 0 {
continue // interface down
}
if iface.Flags&net.FlagLoopback != 0 {
continue // loopback interface
}
addrs, err := iface.Addrs()
if err != nil {
return "", err
}
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
@@ -830,9 +882,11 @@ func externalIP() (string, error) {
case *net.IPAddr:
ip = v.IP
}
if ip == nil || ip.IsLoopback() {
continue
}
ip = ip.To4()
if ip == nil {
continue // not an ipv4 address
@@ -840,6 +894,7 @@ func externalIP() (string, error) {
return ip.String(), nil
}
}
return "", errors.New("are you connected to the network?")
}
@@ -880,8 +935,8 @@ func parseFlags() (*cliOptions, error) {
gop.StringVarLong(&opts.SSLPEMKeyFile, "sslPEMKeyFile", 0, "SSL client PEM file used for authentication")
gop.SetParameters("host[:port]")
gop.Parse(os.Args)
if gop.NArgs() > 0 {
opts.Host = gop.Arg(0)
gop.Parse(gop.Args())
@@ -889,19 +944,25 @@ func parseFlags() (*cliOptions, error) {
if gop.IsSet("password") && opts.Password == "" {
print("Password: ")
pass, err := gopass.GetPasswd()
if err != nil {
return opts, err
}
opts.Password = string(pass)
}
if !strings.HasPrefix(opts.Host, "mongodb://") {
opts.Host = "mongodb://" + opts.Host
}
if opts.Help {
gop.PrintUsage(os.Stdout)
return nil, nil
}
if opts.OutputFormat != "json" && opts.OutputFormat != "text" {
log.Infof("Invalid output format '%s'. Using text format", opts.OutputFormat)
}
@@ -920,27 +981,93 @@ func getChunksCount(ctx context.Context, client *mongo.Client) ([]proto.ChunksBy
if err != nil {
return nil, err
}
for cursor.Next(ctx) {
res := proto.ChunksByCollection{}
if err := cursor.Decode(&res); err != nil {
return nil, errors.Wrap(err, "cannot decode chunks aggregation")
}
result = append(result, res)
}
return result, nil
}
func getClientOptions(opts *cliOptions) *options.ClientOptions {
func getClientOptions(opts *cliOptions) (*options.ClientOptions, error) {
clientOptions := options.Client().ApplyURI(opts.Host)
clientOptions.ServerSelectionTimeout = &defaultConnectionTimeout
clientOptions.Direct = &directConnection
credential := options.Credential{}
if opts.User != "" {
credential.Username = opts.User
clientOptions.SetAuth(credential)
}
if opts.Password != "" {
credential.Password = opts.Password
credential.PasswordSet = true
clientOptions.SetAuth(credential)
}
return clientOptions
if opts.SSLPEMKeyFile != "" || opts.SSLCAFile != "" {
tlsConfig, err := getTLSConfig(opts.SSLPEMKeyFile, opts.SSLCAFile)
if err != nil {
return nil, errors.Wrap(err, "cannot read SSL certificate files")
}
clientOptions.TLSConfig = tlsConfig
}
return clientOptions, nil
}
func getTLSConfig(sslPEMKeyFile, sslCAFile string) (*tls.Config, error) {
tlsConfig := &tls.Config{
MinVersion: tls.VersionTLS10,
InsecureSkipVerify: true,
}
roots := x509.NewCertPool()
if sslPEMKeyFile != "" {
crt, err := ioutil.ReadFile(filepath.Clean(expandHome(sslPEMKeyFile)))
if err != nil {
return nil, err
}
cert, err := tls.X509KeyPair(crt, crt)
if err != nil {
log.Fatal(err)
}
tlsConfig.Certificates = []tls.Certificate{cert}
}
if sslCAFile != "" {
ca, err := ioutil.ReadFile(filepath.Clean(expandHome(sslCAFile)))
if err != nil {
return nil, err
}
roots.AppendCertsFromPEM(ca)
tlsConfig.RootCAs = roots
}
return tlsConfig, nil
}
func expandHome(path string) string {
usr, _ := user.Current()
dir := usr.HomeDir
switch {
case path == "~":
path = dir
case strings.HasPrefix(path, "~/"):
path = filepath.Join(dir, path[2:])
}
return path
}

View File

@@ -99,8 +99,8 @@ func TestClusterWideInfo(t *testing.T) {
}
})
}
}
func addToCounters(ss proto.ServerStatus, increment int64) proto.ServerStatus {
ss.Opcounters.Command += increment
ss.Opcounters.Delete += increment

View File

@@ -85,7 +85,6 @@ func GetOplogInfo(ctx context.Context, hostnames []string, co *options.ClientOpt
sort.Sort(results)
return results, nil
}
func getOplogCollection(ctx context.Context, client *mongo.Client) (string, error) {

View File

@@ -31,6 +31,7 @@ type connOpts struct {
Password string
DisableSSL bool
}
type cliOptions struct {
app *kingpin.Application
connOpts connOpts
@@ -110,7 +111,6 @@ func main() {
if err := masterTmpl.ExecuteTemplate(os.Stdout, "report", info); err != nil {
log.Fatal(err)
}
}
func connect(dsn string) (*sql.DB, error) {

View File

@@ -5,8 +5,8 @@ import (
"os"
"testing"
"github.com/percona/percona-toolkit/src/go/pt-pg-summary/internal/tu"
"github.com/percona/percona-toolkit/src/go/lib/pginfo"
"github.com/percona/percona-toolkit/src/go/pt-pg-summary/internal/tu"
"github.com/sirupsen/logrus"
)
@@ -48,7 +48,6 @@ func TestConnection(t *testing.T) {
}
})
}
}
func TestNewWithLogger(t *testing.T) {
@@ -57,7 +56,7 @@ func TestNewWithLogger(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s sslmode=disable dbname=%s",
test.host, test.port, test.username, test.password, "postgres")
db, err := connect(dsn);
db, err := connect(dsn)
if err != nil {
t.Errorf("Cannot connect to the db using %q: %s", dsn, err)
}
@@ -68,18 +67,17 @@ func TestNewWithLogger(t *testing.T) {
}
}
func TestCollectGlobalInfo(t *testing.T) {
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s sslmode=disable dbname=%s",
test.host, test.port, test.username, test.password, "postgres")
db, err := connect(dsn);
db, err := connect(dsn)
if err != nil {
t.Errorf("Cannot connect to the db using %q: %s", dsn, err)
}
info, err := pginfo.NewWithLogger(db, nil, 30, logger);
info, err := pginfo.NewWithLogger(db, nil, 30, logger)
if err != nil {
t.Errorf("Cannot run NewWithLogger using %q: %s", dsn, err)
}
@@ -101,18 +99,18 @@ func TestCollectPerDatabaseInfo(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s sslmode=disable dbname=%s",
test.host, test.port, test.username, test.password, "postgres")
db, err := connect(dsn);
db, err := connect(dsn)
if err != nil {
t.Errorf("Cannot connect to the db using %q: %s", dsn, err)
}
info, err := pginfo.NewWithLogger(db, nil, 30, logger);
info, err := pginfo.NewWithLogger(db, nil, 30, logger)
if err != nil {
t.Errorf("Cannot run New using %q: %s", dsn, err)
}
for _, dbName := range info.DatabaseNames() {
dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s sslmode=disable dbname=%s",
test.host, test.port, test.username, test.password, dbName)
conn, err := connect(dsn);
conn, err := connect(dsn)
if err != nil {
t.Errorf("Cannot connect to the %s database using %q: %s", dbName, dsn, err)
}

View File

@@ -13,7 +13,7 @@ func GetAllDatabases(db XODB) ([]*AllDatabases, error) {
var err error
// sql query
var sqlstr = `SELECT datname ` +
sqlstr := `SELECT datname ` +
`FROM pg_database ` +
`WHERE datistemplate = false`

View File

@@ -24,7 +24,7 @@ func GetClusterInfos(db XODB) ([]*ClusterInfo, error) {
var err error
// sql query
var sqlstr = `SELECT usename, now() AS "Time", ` +
sqlstr := `SELECT usename, now() AS "Time", ` +
`client_addr, ` +
`client_hostname, ` +
`version() AS version, ` +

View File

@@ -20,7 +20,7 @@ func GetConnectedClients(db XODB) ([]*ConnectedClients, error) {
var err error
// sql query
var sqlstr = `SELECT usename, ` +
sqlstr := `SELECT usename, ` +
`CASE WHEN client_hostname IS NULL THEN client_addr::text ELSE client_hostname END AS client, ` +
`state, count(*) ` +
`FROM pg_stat_activity ` +

View File

@@ -14,7 +14,7 @@ func GetConnections(db XODB) ([]*Connections, error) {
var err error
// sql query
var sqlstr = `SELECT state, count(*) ` +
sqlstr := `SELECT state, count(*) ` +
`FROM pg_stat_activity ` +
`GROUP BY 1`

View File

@@ -27,7 +27,7 @@ func GetCounters(db XODB) ([]*Counters, error) {
var err error
// sql query
var sqlstr = `SELECT COALESCE(datname, '') datname, numbackends, xact_commit, xact_rollback, ` +
sqlstr := `SELECT COALESCE(datname, '') datname, numbackends, xact_commit, xact_rollback, ` +
`blks_read, blks_hit, tup_returned, tup_fetched, tup_inserted, ` +
`tup_updated, tup_deleted, conflicts, temp_files, ` +
`temp_bytes, deadlocks ` +

View File

@@ -14,7 +14,7 @@ func GetDatabases(db XODB) ([]*Databases, error) {
var err error
// sql query
var sqlstr = `SELECT datname, pg_size_pretty(pg_database_size(datname)) ` +
sqlstr := `SELECT datname, pg_size_pretty(pg_database_size(datname)) ` +
`FROM pg_stat_database ` +
`WHERE datid <> 0`

View File

@@ -22,7 +22,7 @@ func GetDatabaseWaitEvents(db XODB) ([]*DatabaseWaitEvents, error) {
var err error
// sql query
var sqlstr = `SELECT c.relname, c.relkind, d.wait_event_type, d.wait_event, b.datname, count(*) ` +
sqlstr := `SELECT c.relname, c.relkind, d.wait_event_type, d.wait_event, b.datname, count(*) ` +
`FROM pg_locks a ` +
`JOIN pg_stat_database b ON a.database=b.datid ` +
`JOIN pg_class c ON a.relation=c.oid ` +

View File

@@ -14,7 +14,7 @@ func GetPortAndDatadir(db XODB) (*PortAndDatadir, error) {
var err error
// sql query
var sqlstr = `SELECT name, ` +
sqlstr := `SELECT name, ` +
`setting ` +
`FROM pg_settings ` +
`WHERE name IN ('port','data_directory')`

View File

@@ -20,7 +20,7 @@ func GetSlaveHosts10s(db XODB) ([]*SlaveHosts10, error) {
var err error
// sql query
var sqlstr = `SELECT application_name, client_addr, state, sent_offset - (replay_offset - (sent_lsn - replay_lsn) * 255 * 16 ^ 6 ) AS byte_lag ` +
sqlstr := `SELECT application_name, client_addr, state, sent_offset - (replay_offset - (sent_lsn - replay_lsn) * 255 * 16 ^ 6 ) AS byte_lag ` +
`FROM ( SELECT application_name, client_addr, client_hostname, state, ` +
`('x' || lpad(split_part(sent_lsn::TEXT, '/', 1), 8, '0'))::bit(32)::bigint AS sent_lsn, ` +
`('x' || lpad(split_part(replay_lsn::TEXT, '/', 1), 8, '0'))::bit(32)::bigint AS replay_lsn, ` +

View File

@@ -20,7 +20,7 @@ func GetSlaveHosts96s(db XODB) ([]*SlaveHosts96, error) {
var err error
// sql query
var sqlstr = `SELECT application_name, client_addr, state, sent_offset - (replay_offset - (sent_xlog - replay_xlog) * 255 * 16 ^ 6 ) AS byte_lag ` +
sqlstr := `SELECT application_name, client_addr, state, sent_offset - (replay_offset - (sent_xlog - replay_xlog) * 255 * 16 ^ 6 ) AS byte_lag ` +
`FROM ( SELECT application_name, client_addr, client_hostname, state, ` +
`('x' || lpad(split_part(sent_location::TEXT, '/', 1), 8, '0'))::bit(32)::bigint AS sent_xlog, ` +
`('x' || lpad(split_part(replay_location::TEXT, '/', 1), 8, '0'))::bit(32)::bigint AS replay_xlog, ` +

View File

@@ -20,7 +20,7 @@ func GetTableAccesses(db XODB) ([]*TableAccess, error) {
var err error
// sql query
var sqlstr = `SELECT c.relname, c.relkind, b.datname datname, count(*) FROM pg_locks a ` +
sqlstr := `SELECT c.relname, c.relkind, b.datname datname, count(*) FROM pg_locks a ` +
`JOIN pg_stat_database b ` +
`ON a.database=b.datid ` +
`JOIN pg_class c ` +

View File

@@ -18,7 +18,7 @@ func GetTableCacheHitRatio(db XODB) (*TableCacheHitRatio, error) {
var err error
// sql query
var sqlstr = `SELECT 'cache hit rate' AS name, ` +
sqlstr := `SELECT 'cache hit rate' AS name, ` +
`CASE WHEN (sum(heap_blks_read) + sum(idx_blks_hit)) > 0 ` +
`THEN ` +
`sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) ` +

View File

@@ -15,7 +15,7 @@ func GetTablespaces(db XODB) ([]*Tablespaces, error) {
var err error
// sql query
var sqlstr = `SELECT spcname AS Name, ` +
sqlstr := `SELECT spcname AS Name, ` +
`pg_catalog.pg_get_userbyid(spcowner) AS Owner, ` +
`pg_catalog.pg_tablespace_location(oid) AS Location ` +
`FROM pg_catalog.pg_tablespace ` +

View File

@@ -50,7 +50,7 @@ func encrypt(infile, outfile string, pass [32]byte) error {
var iv [aes.BlockSize]byte
stream := cipher.NewOFB(block, iv[:])
outFile, err := os.OpenFile(outfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
outFile, err := os.OpenFile(outfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
if err != nil {
return errors.Wrapf(err, "Cannot create output file %q", outfile)
}
@@ -81,7 +81,7 @@ func decrypt(infile, outfile string, pass [32]byte) error {
var iv [aes.BlockSize]byte
stream := cipher.NewOFB(block, iv[:])
outFile, err := os.OpenFile(outfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
outFile, err := os.OpenFile(outfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
if err != nil {
return errors.Wrapf(err, "Cannot open %q for writing", outfile)
}

View File

@@ -32,11 +32,9 @@ func TestProcessCliParams(t *testing.T) {
t.Errorf("Test #%d expected error, have nil", i)
}
if !reflect.DeepEqual(opts, test.WantOpts) {
}
}
}
func TestCollect(t *testing.T) {
}

View File

@@ -6,12 +6,12 @@ cd $BASEDIR
source ${BASEDIR}/src/go/setenv.sh
for dir in $(ls -d ./src/go/pt-*)
for dir in $(ls -d ./src/go/pt-* ) ./src/go/mongolib
do
echo "Running tests at $BASEDIR/$dir"
cd $BASEDIR/$dir
go get ./...
go test -v -coverprofile=coverage.out
go test -v -coverprofile=coverage.out ./...
if [ -f coverage.out ]
then
go tool cover -func=coverage.out

View File

@@ -0,0 +1,70 @@
#!/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 threads;
use threads::shared;
use Thread::Semaphore;
use English qw(-no_match_vars);
use Test::More;
use Data::Dumper;
use PerconaTest;
use Sandbox;
use SqlModes;
use File::Temp qw/ tempdir /;
if ($sandbox_version lt '5.7') {
plan skip_all => 'This test needs MySQL 5.7+';
} else {
plan tests => 2;
}
require "$trunk/bin/pt-online-schema-change";
my $dp = new DSNParser(opts=>$dsn_opts);
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
my $dbh = $sb->get_dbh_for('master');
my $dsn = $sb->dsn_for("master");
# The sandbox servers run with lock_wait_timeout=3 and it's not dynamic
# so we need to specify --set-vars innodb_lock_wait_timeout=3 else the
# tool will die.
my @args = (qw(--set-vars innodb_lock_wait_timeout=3));
my $output;
my $exit_status;
$sb->load_file('master', "t/pt-online-schema-change/samples/pt-1528.sql");
my $rows_before = $dbh->selectall_hashref("SELECT * FROM test.brokenutf8alter", "id");
($output, $exit_status) = full_output(
sub { pt_online_schema_change::main(@args, "$dsn,D=test,t=brokenutf8alter",
'--execute', '--charset=utf8', '--chunk-size', '2', '--alter', 'engine=innodb',
),
},
stderr => 1,
);
my $rows_after = $dbh->selectall_hashref("SELECT * FROM test.brokenutf8alter", "id");
is_deeply(
$rows_before,
$rows_after,
"Should be equal",
);
# #############################################################################
# Done.
# #############################################################################
$sb->wipe_clean($dbh);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
done_testing;

View File

@@ -0,0 +1,76 @@
#!/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 threads;
use English qw(-no_match_vars);
use Test::More;
use Data::Dumper;
use PerconaTest;
use Sandbox;
use SqlModes;
use File::Temp qw/ tempdir /;
plan tests => 3;
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 $master_dsn = 'h=127.1,P=12345,u=msandbox,p=msandbox';
if ( !$master_dbh ) {
plan skip_all => 'Cannot connect to sandbox master';
}
# The sandbox servers run with lock_wait_timeout=3 and it's not dynamic
# so we need to specify --set-vars innodb_lock_wait_timeout=3 else the
# tool will die.
my @args = (qw(--set-vars innodb_lock_wait_timeout=3));
my $output;
my $exit_status;
my $sample = "t/pt-online-schema-change/samples/";
my $ERROR_UPDATING_FKS = 15; # from pt-online-schema-change line 8453
$sb->load_file('master', "$sample/pt-169.sql");
($output, $exit_status) = full_output(
sub { pt_online_schema_change::main(@args, "$master_dsn,D=test,t=users",
'--execute', '--alter', 'CHANGE COLUMN id id BIGINT UNSIGNED NOT NULL FIRST',
'--set-vars', 'foreign_key_checks=0',
'--alter-foreign-keys-method', 'drop_swap', '--no-check-alter')
},
);
is(
$exit_status,
$ERROR_UPDATING_FKS,
"--alter rename columns with uppercase names -> exit status 0",
);
# Since drop_swap has failed, the clueanup process should be skipped and the new table
# shouldn't be deleted
my $row = $master_dbh->selectrow_hashref("select count(*) AS how_many from test._users_new");
is (
$row->{how_many},
1,
"Correct number of rows",
);
$master_dbh->do("DROP DATABASE IF EXISTS test");
# #############################################################################
# Done.
# #############################################################################
$sb->wipe_clean($master_dbh);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
done_testing;

View File

@@ -0,0 +1,68 @@
-- MySQL dump 10.13 Distrib 5.7.19-17, for debian-linux-gnu (x86_64)
--
-- Host: localhost Database: test
-- ------------------------------------------------------
-- Server version 5.7.19-17-log
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
/*!50717 SELECT COUNT(*) INTO @rocksdb_has_p_s_session_variables FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'performance_schema' AND TABLE_NAME = 'session_variables' */;
/*!50717 SET @rocksdb_get_is_supported = IF (@rocksdb_has_p_s_session_variables, 'SELECT COUNT(*) INTO @rocksdb_is_supported FROM performance_schema.session_variables WHERE VARIABLE_NAME=\'rocksdb_bulk_load\'', 'SELECT 0') */;
/*!50717 PREPARE s FROM @rocksdb_get_is_supported */;
/*!50717 EXECUTE s */;
/*!50717 DEALLOCATE PREPARE s */;
/*!50717 SET @rocksdb_enable_bulk_load = IF (@rocksdb_is_supported, 'SET SESSION rocksdb_bulk_load = 1', 'SET @rocksdb_dummy_bulk_load = 0') */;
/*!50717 PREPARE s FROM @rocksdb_enable_bulk_load */;
/*!50717 EXECUTE s */;
/*!50717 DEALLOCATE PREPARE s */;
--
-- Table structure for table `brokenutf8alter`
--
DROP DATABASE IF EXISTS test;
CREATE DATABASE test;
USE test;
DROP TABLE IF EXISTS `brokenutf8alter`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `brokenutf8alter` (
`ID` binary(16) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `brokenutf8alter`
--
LOCK TABLES `brokenutf8alter` WRITE;
/*!40000 ALTER TABLE `brokenutf8alter` DISABLE KEYS */;
INSERT INTO `brokenutf8alter` VALUES ('.SG<53>:\<5C><>\<5C>B<>\0'),('.SK,:\<5C><>\<5C>B<>\0'),('.SL_:\<5C><>\<5C>B<>\0'),('.SL\<5C>:\<5C><>\<5C>B<>\0'),('.SMB:\<5C><>\<5C>B<>\0'),('.SM<53>:\<5C><>\<5C>B<>\0'),('.SM<53>:\<5C><>\<5C>B<>\0'),('.SOE:\<5C><>\<5C>B<>\0'),('.SO<53>:\<5C><>\<5C>B<>\0'),('.SP:\<5C><>\<5C>B<>\0'),('.SPZ:\<5C><>\<5C>B<>\0'),('.SP<53>:\<5C><>\<5C>B<>\0'),('.SQ:\<5C><>\<5C>B<>\0'),('.SQX:\<5C><>\<5C>B<>\0'),('.SQ<53>:\<5C><>\<5C>B<>\0'),('.SQ<53>:\<5C><>\<5C>B<>\0'),('.SRK:\<5C><>\<5C>B<>\0'),('.ST4:\<5C><>\<5C>B<>\0'),('.SU=:\<5C><>\<5C>B<>\0'),('.SU<53>:\<5C><>\<5C>B<>\0'),('.SU<53>:\<5C><>\<5C>B<>\0'),('.SVC:\<5C><>\<5C>B<>\0'),('.SV<53>:\<5C><>\<5C>B<>\0'),('.SV\<5C>:\<5C><>\<5C>B<>\0'),('.SW8:\<5C><>\<5C>B<>\0'),('.SW<53>:\<5C><>\<5C>B<>\0'),('.SX\<5C>:\<5C><>\<5C>B<>\0'),('.SY\":\<5C><>\<5C>B<>\0'),('.SYr:\<5C><>\<5C>B<>\0'),('.SY\<5C>:\<5C><>\<5C>B<>\0'),('.SZ:\<5C><>\<5C>B<>\0'),('.SZ<53>:\<5C><>\<5C>B<>\0'),('.S[):\<5C><>\<5C>B<>\0'),('.S[<5B>:\<5C><>\<5C>B<>\0'),('.S\\N:\<5C><>\<5C>B<>\0'),('.S\\\<5C>:\<5C><>\<5C>B<>\0'),('.S]>:\<5C><>\<5C>B<>\0'),('.S]<5D>:\<5C><>\<5C>B<>\0'),('.S]\<5C>:\<5C><>\<5C>B<>\0'),('.S^.:\<5C><>\<5C>B<>\0'),('.S^:\<5C><>\<5C>B<>\0'),('.S^\<5C>:\<5C><>\<5C>B<>\0'),('.S_8:\<5C><>\<5C>B<>\0'),('.S_<53>:\<5C><>\<5C>B<>\0'),('.S`W:\<5C><>\<5C>B<>\0'),('.S`<60>:\<5C><>\<5C>B<>\0'),('.Sa~:\<5C><>\<5C>B<>\0'),('.Sb:\<5C><>\<5C>B<>\0'),('.Sb<53>:\<5C><>\<5C>B<>\0'),('.Sc>:\<5C><>\<5C>B<>\0'),('.Sc\<5C>:\<5C><>\<5C>B<>\0'),('.Sd:\<5C><>\<5C>B<>\0'),('.Sdv:\<5C><>\<5C>B<>\0'),('.Sd\<5C>:\<5C><>\<5C>B<>\0'),('.Se:\<5C><>\<5C>B<>\0'),('.Seb:\<5C><>\<5C>B<>\0'),('.Se<53>:\<5C><>\<5C>B<>\0'),('.Sf:\<5C><>\<5C>B<>\0'),('.SfP:\<5C><>\<5C>B<>\0'),('.Sf<53>:\<5C><>\<5C>B<>\0'),('.Sf<53>:\<5C><>\<5C>B<>\0'),('.Sg?:\<5C><>\<5C>B<>\0'),('.Sg<53>:\<5C><>\<5C>B<>\0'),('.Sh:\<5C><>\<5C>B<>\0'),('.Sh<53>:\<5C><>\<5C>B<>\0'),('.Si7:\<5C><>\<5C>B<>\0'),('.Si\<5C>:\<5C><>\<5C>B<>\0'),('.Sji:\<5C><>\<5C>B<>\0'),('.Sk:\<5C><>\<5C>B<>\0'),('.Sk<53>:\<5C><>\<5C>B<>\0'),('.Sk\<5C>:\<5C><>\<5C>B<>\0'),('.Sl(:\<5C><>\<5C>B<>\0'),('.Sl{:\<5C><>\<5C>B<>\0'),('.Sl\<5C>:\<5C><>\<5C>B<>\0'),('.Sm\Z:\<5C><>\<5C>B<>\0'),('.Smh:\<5C><>\<5C>B<>\0'),('.Sm<53>:\<5C><>\<5C>B<>\0'),('.Sn:\<5C><>\<5C>B<>\0'),('.So:\<5C><>\<5C>B<>\0'),('.Sob:\<5C><>\<5C>B<>\0'),('.So<53>:\<5C><>\<5C>B<>\0'),('.Sp:\<5C><>\<5C>B<>\0'),('.SpQ:\<5C><>\<5C>B<>\0'),('.Sp<53>:\<5C><>\<5C>B<>\0'),('.Sp<53>:\<5C><>\<5C>B<>\0'),('.SqA:\<5C><>\<5C>B<>\0'),('.Sq<53>:\<5C><>\<5C>B<>\0'),('.Sq\<5C>:\<5C><>\<5C>B<>\0'),('.Sr+:\<5C><>\<5C>B<>\0'),('.Srv:\<5C><>\<5C>B<>\0'),('.Sr<53>:\<5C><>\<5C>B<>\0'),('.Ss:\<5C><>\<5C>B<>\0'),('.Ss_:\<5C><>\<5C>B<>\0'),('.St :\<5C><>\<5C>B<>\0'),('.St :\<5C><>\<5C>B<>\0'),('.St5:\<5C><>\<5C>B<>\0'),('.StI:\<5C><>\<5C>B<>\0'),('.St^:\<5C><>\<5C>B<>\0'),('.Str:\<5C><>\<5C>B<>\0'),('.St<53>:\<5C><>\<5C>B<>\0'),('.St<53>:\<5C><>\<5C>B<>\0');
/*!40000 ALTER TABLE `brokenutf8alter` ENABLE KEYS */;
UNLOCK TABLES;
/*!50112 SET @disable_bulk_load = IF (@is_rocksdb_supported, 'SET SESSION rocksdb_bulk_load = @old_rocksdb_bulk_load', 'SET @dummy_rocksdb_bulk_load = 0') */;
/*!50112 PREPARE s FROM @disable_bulk_load */;
/*!50112 EXECUTE s */;
/*!50112 DEALLOCATE PREPARE s */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2018-04-07 3:48:50

View File

@@ -0,0 +1,40 @@
DROP DATABASE IF EXISTS `test`;
CREATE DATABASE test;
USE test;
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL,
`username` varchar(255) NOT NULL,
`full_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci NOT NULL,
`is_verified` tinyint(1) NOT NULL DEFAULT '0',
`is_private` tinyint(1) NOT NULL DEFAULT '0',
`profile_pic_url` varchar(255) DEFAULT NULL,
`follower_count` int(11) NOT NULL DEFAULT '0',
`following_count` int(11) NOT NULL DEFAULT '0',
`media_count` int(11) NOT NULL DEFAULT '0',
`biography` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci DEFAULT NULL,
`user_active` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `username` (`username`),
KEY `follower_count` (`follower_count`),
KEY `following_count` (`following_count`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `user_comments` (
`id_user_comments` int(11) NOT NULL AUTO_INCREMENT,
`msg` varchar(255) DEFAULT NULL,
`user_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id_user_comments`),
KEY `fk1_idx` (`user_id`),
CONSTRAINT `fk1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
INSERT INTO `test`.`users` (`id`, `username`, `full_name`, `is_verified`, `is_private`, `profile_pic_url`,
`follower_count`, `following_count`, `media_count`, `biography`, `user_active`)
VALUES
(1, "zappb", "zapp brannigan", 1, 1, "https://pbs.twimg.com/profile_images/447660347273408512/NdZEGKvr.jpeg", 0, 0, 0, "", 1);
INSERT INTO `test`.`user_comments` (`id_user_comments`, `msg`, `user_id`)
VALUES
(1, "I am the man with no name. Zapp Brannigan, at your service.", 1);

View File

@@ -23,7 +23,9 @@ if ($ENV{PERCONA_SLOW_BOX}) {
plan skip_all => 'This test needs a fast machine';
} else {
plan tests => 6;
#plan skip_all => 'This test is taking too much time even in fast machines';
}
our $delay = 30;
my $tmp_file = File::Temp->new();
@@ -39,10 +41,6 @@ my $slave_dbh = $sb->get_dbh_for('slave1');
my $master_dsn = 'h=127.0.0.1,P=12345,u=msandbox,p=msandbox';
my $slave_dsn = 'h=127.0.0.1,P=12346,u=msandbox,p=msandbox';
if ( !$master_dbh ) {
plan skip_all => 'Cannot connect to sandbox master';
}
sub reset_query_cache {
my @dbhs = @_;
return if ($sandbox_version >= '8.0');
@@ -64,7 +62,7 @@ $sb->load_file('master', "t/pt-online-schema-change/samples/slave_lag.sql");
my $num_rows = 5000;
diag("Loading $num_rows into the table. This might take some time.");
diag(`util/mysql_random_data_load --host=127.0.0.1 --port=12345 --user=msandbox --password=msandbox test pt178 --bulk-size=1 --max-threads=1 $num_rows`);
diag(`util/mysql_random_data_load --host=127.0.0.1 --port=12345 --user=msandbox --password=msandbox test pt178 $num_rows`);
diag("Setting slave delay to $delay seconds");