From 7ecdae6ef66e4ed3b3bfbd951a90675a3bf0a932 Mon Sep 17 00:00:00 2001 From: Yoann La Cancellera <43131790+ylacancellera@users.noreply.github.com> Date: Thu, 23 Feb 2023 14:00:44 +0100 Subject: [PATCH] PT-2102_pt-mysql-summary should support include in config files (#601) * PT-2102 pt-mysql-summary should support include* in config file includedir directories are now printed in the order of which they appear in root my.cnf * PT-2102 pt-mysql-summary should support include* in config file !include was not supported. Changed 'for' to 'while' to properly test for '!includedir' and '!include'. Supports extra spaces between files and !include. * PT-2102 pt-mysql-summary should support include* in config file Updates modules, added test case for !include and !includedir Changed find_my_cnf function to make it try every regexes and only returned when it find one * Update pt-mysql-summary Identation fix as suggested by review * Update collect_mysql_info.sh Identation as suggested by review * PT-2102 pt-mysql-summary should support include* in config file Fix formatting after review --------- Co-authored-by: Sveta Smirnova --- bin/pt-mysql-summary | 31 +++++++- lib/bash/collect_mysql_info.sh | 13 ++- lib/bash/report_mysql_info.sh | 19 +++++ t/pt-mysql-summary/pt-2102.t | 96 +++++++++++++++++++++++ t/pt-mysql-summary/samples/my.cnf-002.txt | 43 ++++++++++ 5 files changed, 195 insertions(+), 7 deletions(-) create mode 100644 t/pt-mysql-summary/pt-2102.t create mode 100644 t/pt-mysql-summary/samples/my.cnf-002.txt diff --git a/bin/pt-mysql-summary b/bin/pt-mysql-summary index f6587cd9..77c6a640 100755 --- a/bin/pt-mysql-summary +++ b/bin/pt-mysql-summary @@ -878,11 +878,17 @@ find_my_cnf_file() { if [ "$port" ]; then cnf_file="$(grep --max-count 1 "/mysqld.*--port=$port" "$file" \ | awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }')" - else - cnf_file="$(grep --max-count 1 '/mysqld' "$file" \ - | awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }')" + + if [ -n "$cnf_file" ]; then + echo "$cnf_file" + return + fi fi + cnf_file="$(grep --max-count 1 '/mysqld' "$file" \ + | awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }')" + + if [ -z "$cnf_file" ]; then if [ -e "/etc/my.cnf" ]; then cnf_file="/etc/my.cnf" @@ -1419,6 +1425,25 @@ pretty_print_cnf_file () { } }' "$file" + while read line; do + echo $line | grep -q '!include' + if [ $? -eq 0 ]; then + clause=$(echo -n $line | tr -s ' ' | cut -d ' ' -f 1) + include=$(echo -n $line | tr -s ' ' | cut -d ' ' -f 2) + + if [ "x$include" != "x" -a -d "${include}" -a "x$clause" = 'x!includedir' ]; then + for subfile in $(find -L "$include" -type f -maxdepth 1 -name *.cnf ); do + echo "# $subfile" + pretty_print_cnf_file $subfile + done + elif [ -f "$include" -a "$clause" = '!include' ]; then + echo "# $include" + pretty_print_cnf_file $include + fi + fi + + done < "$file" + } diff --git a/lib/bash/collect_mysql_info.sh b/lib/bash/collect_mysql_info.sh index dc6d6e2a..86fba56b 100644 --- a/lib/bash/collect_mysql_info.sh +++ b/lib/bash/collect_mysql_info.sh @@ -64,12 +64,17 @@ find_my_cnf_file() { # Find the cnf file for the specific port. cnf_file="$(grep --max-count 1 "/mysqld.*--port=$port" "$file" \ | awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }')" - else - # Find the cnf file for the first mysqld instance. - cnf_file="$(grep --max-count 1 '/mysqld' "$file" \ - | awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }')" + + if [ -n "$cnf_file" ]; then + echo "$cnf_file" + return + fi fi + cnf_file="$(grep --max-count 1 '/mysqld' "$file" \ + | awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }')" + + if [ -z "$cnf_file" ]; then # Cannot autodetect config file, try common locations. if [ -e "/etc/my.cnf" ]; then diff --git a/lib/bash/report_mysql_info.sh b/lib/bash/report_mysql_info.sh index 7efae9db..428dc269 100644 --- a/lib/bash/report_mysql_info.sh +++ b/lib/bash/report_mysql_info.sh @@ -387,6 +387,25 @@ pretty_print_cnf_file () { } }' "$file" + while read line; do + echo $line | grep -q '!include' + if [ $? -eq 0 ]; then + clause=$(echo -n $line | tr -s ' ' | cut -d ' ' -f 1) + include=$(echo -n $line | tr -s ' ' | cut -d ' ' -f 2) + + if [ "x$include" != "x" -a -d "${include}" -a "x$clause" = 'x!includedir' ]; then + for subfile in $(find -L "$include" -type f -maxdepth 1 -name *.cnf ); do + echo "# $subfile" + pretty_print_cnf_file $subfile + done + elif [ -f "$include" -a "$clause" = '!include' ]; then + echo "# $include" + pretty_print_cnf_file $include + fi + fi + + done < "$file" + } diff --git a/t/pt-mysql-summary/pt-2102.t b/t/pt-mysql-summary/pt-2102.t new file mode 100644 index 00000000..2f0ef80d --- /dev/null +++ b/t/pt-mysql-summary/pt-2102.t @@ -0,0 +1,96 @@ +#!/usr/bin/env perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use PerconaTest; +use Sandbox; +use DSNParser; +require VersionParser; +use Test::More; +use File::Temp qw( tempdir ); + +local $ENV{PTDEBUG} = ""; + +my $dp = new DSNParser(opts=>$dsn_opts); +my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); +my $master_dbh = $sb->get_dbh_for('master'); +my $has_keyring_plugin; + +if ( !$master_dbh ) { + plan skip_all => 'Cannot connect to sandbox master'; +} +else { + plan tests => 3; +} + +my $db_flavor = VersionParser->new($master_dbh)->flavor(); +if ( $db_flavor =~ m/Percona Server/ ) { + my $rows = $master_dbh->selectall_hashref("SHOW PLUGINS", "name"); + while (my ($key, $values) = each %$rows) { + if ($key =~ m/^keyring_/) { + $has_keyring_plugin=1; + last; + } + } +} + +# mysqldump from earlier versions doesn't seem to work with 5.6, +# so use the actual mysqldump from each MySQL bin which should +# always be compatible with itself. +# We need LC_NUMERIC=POSIX, so test does not fail in environment +# which use , insead of . for numbers. +my $env = qq\CMD_MYSQLDUMP="$ENV{PERCONA_TOOLKIT_SANDBOX}/bin/mysqldump" LC_NUMERIC=POSIX\; + +# +# --save-samples +# + +my $dir = tempdir( "percona-testXXXXXXXX", CLEANUP => 1 ); + +my $output; +my $cnf = '/tmp/12345/my.sandbox.cnf'; +diag(`cp $cnf $cnf.bak`); +my $cmd = "$trunk/bin/pt-mysql-summary --sleep 1 -- --defaults-file=$cnf"; + +diag(`echo "[mysqld]" > /tmp/12345/my.sandbox.2.cnf`); +diag(`echo "wait_timeout=12345" >> /tmp/12345/my.sandbox.2.cnf`); +diag(`echo "!include /tmp/12345/my.sandbox.2.cnf" >> $cnf`); + +$output = `$cmd`; + +like( + $output, + qr/wait_timeout\s+=\s+12345/s, + "!include works" +); + +diag(`cp $cnf.bak $cnf`); + +diag(`mkdir -p /tmp/12345/my.sandbox.3`); +diag(`echo "[mysqld]" > /tmp/12345/my.sandbox.3/my.sandbox.cnf`); +diag(`echo "wait_timeout=23456" >> /tmp/12345/my.sandbox.3/my.sandbox.cnf`); +diag(`echo "!includedir /tmp/12345/my.sandbox.3" >> $cnf`); + +$output = `$cmd`; + +like( + $output, + qr/wait_timeout\s+=\s+23456/s, + "!includedir works" +); + +diag(`cp $cnf.bak $cnf`); + +# ############################################################################# +# Done. +# ############################################################################# +$sb->wipe_clean($master_dbh); +ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +exit; diff --git a/t/pt-mysql-summary/samples/my.cnf-002.txt b/t/pt-mysql-summary/samples/my.cnf-002.txt new file mode 100644 index 00000000..fce27b5d --- /dev/null +++ b/t/pt-mysql-summary/samples/my.cnf-002.txt @@ -0,0 +1,43 @@ +[mysqld] +####datadir=/var/lib/mysql +datadir=/mnt/data/mysql +####socket=/var/lib/mysql/mysql.sock +socket=/mnt/data/mysql/mysql.sock +# Default to using old password format for compatibility with mysql 3.x +# clients (those using the mysqlclient10 compatibility package). +old_passwords=1 + +ssl-key = /opt/mysql.pdns/.cert/server-key.pem +ssl-cert = /opt/mysql.pdns/.cert/server-cert.pem +ssl-ca = /opt/mysql.pdns/.cert/ca-cert.pem + +innodb_buffer_pool_size = 16M +innodb_flush_method = O_DIRECT +## THIS SETTING REQUIRE SPECIAL SHUTDOWN PROCEDURE AND MOVING LOGFILE. DO NOT SET UNLESS YOU UNDERSTAND WHAT YOU ARE DOING! +innodb_log_file_size = 64M +innodb_log_buffer_size = 1M +innodb_flush_log_at_trx_commit = 2 +innodb_file_per_table = 1 + +ssl = 1 + +server-id = 1 +log-bin=sl1-bin + +wsrep_provider_options = "gcache.size=64M;base_host=10.1.2.102; base_port=4567; cert.log_conflicts=no;etc=etc;" + +[mysql.server] +user=mysql +####basedir=/var/lib +basedir=/mnt/data + +[mysqld_safe] +log-error=/var/log/mysqld.log +pid-file=/var/run/mysqld/mysqld.pid + +[mysql] + + +[xtrabackup] +target-dir=/data/backup +