diff --git a/debian/ngcp-system-tests.install b/debian/ngcp-system-tests.install index 4e03fd1..072ba5c 100644 --- a/debian/ngcp-system-tests.install +++ b/debian/ngcp-system-tests.install @@ -1,2 +1,4 @@ templates/* /etc/ngcp-config/templates/etc/ngcp-system-tests/ ngcp-system-tests /usr/bin/ +sbin/ngcp-mysql-compare-dbs /usr/sbin/ +helper/compare_dbs.pl /usr/share/ngcp-system-tests/ diff --git a/helper/compare_dbs.pl b/helper/compare_dbs.pl old mode 100644 new mode 100755 index 94a0a6a..d7fa4ed --- a/helper/compare_dbs.pl +++ b/helper/compare_dbs.pl @@ -8,10 +8,14 @@ use Data::Compare; use Getopt::Long; use Carp; +my $credentials_file = '/etc/mysql/sipwise_extra.cnf'; my $argv = { - result => 'result.tap', - pass_db1 => '', - pass_db2 => '', + formatter => '', + schemes => '', + pass_db1 => '', + pass_db2 => '', + user_db1 => '', + user_db2 => '', }; get_options(); @@ -128,54 +132,60 @@ __SQL__ my @objs_list = qw( tables columns indexes constraints triggers views routines ); -my $dbh1 = DBI->connect( $argv->{connect_db1}, $argv->{user_db1}, $argv->{pass_db1}, - { RaiseError => 1 } ) or - croak("Can't connect to db1: $argv->{connect_db1}, $argv->{user_db1}, $argv->{pass_db1} "); +if ($argv->{schemes} eq '') { + warn " --schemes is empty\n\n"; + print_usage(); + exit 1; +} -my $dbh2 = DBI->connect( $argv->{connect_db2}, $argv->{user_db2}, $argv->{pass_db2}, - { RaiseError => 1 } ) or - croak("Can't connect to db2: $argv->{connect_db2}, $argv->{user_db2}, $argv->{pass_db2} "); +my $dbh1 = DBI->connect( + "DBI:mysql:;host=sp1;mysql_read_default_file=$credentials_file", + $argv->{user_db1}, + $argv->{pass_db1}, + { RaiseError => 1 } ) or + croak("Can't connect to db1: DBI:mysql:;host=sp1;mysql_read_default_file=$credentials_file, $argv->{user_db1}, $argv->{pass_db1} "); -my $exit = 0; +my $dbh2 = DBI->connect( + "DBI:mysql:;host=sp2;mysql_read_default_file=$credentials_file", + $argv->{user_db2}, + $argv->{pass_db2}, + { RaiseError => 1 } ) or + croak("Can't connect to db2: DBI:mysql:;host=sp2;mysql_read_default_file=$credentials_file, $argv->{user_db2}, $argv->{pass_db2} "); -my ($sth1, $sth2); -my ($struct1, $struct2); my $res = []; -foreach my $obj ( @objs_list ) { - $struct1 = $dbh1->selectall_hashref( $queries->{$obj}, 'key_col' ); - $struct2 = $dbh2->selectall_hashref( $queries->{$obj}, 'key_col' ); +my $exit = 0; +foreach my $schema ( split( / /, $argv->{schemes} ) ) { + $dbh1->do("USE $schema"); + $dbh2->do("USE $schema"); - unless ( Compare($struct1, $struct2) ) { - $exit = 1; - print_diff($struct1, $struct2, $obj, $res); + my ($sth1, $sth2); + my ($struct1, $struct2); + foreach my $obj ( @objs_list ) { + $struct1 = $dbh1->selectall_hashref( $queries->{$obj}, 'key_col' ); + $struct2 = $dbh2->selectall_hashref( $queries->{$obj}, 'key_col' ); + + unless ( Compare($struct1, $struct2) ) { + $exit = 1; + print_diff($struct1, $struct2, $obj, $res, $schema); + } } } -my $number = scalar(@{$res}); -my $counter = 1; - -open( my $fh, '>', $argv->{result} ); -if ( $number > 0 ) { - print {$fh} "1..$number\n"; - foreach my $err ( @{$res} ) { - print {$fh} "not ok $counter $err\n"; - $counter++; - } +if ( $argv->{formatter} eq 'tap' ) { + tap_output(); } else { - print {$fh} "1..1\n"; - print {$fh} "ok 1 Schemes are equal\n"; + human_output(); } -close($fh); + exit $exit; sub get_options { GetOptions( - 'result=s' => \$argv->{'result'}, - 'connect_db1=s' => \$argv->{'connect_db1'}, + 'formatter=s' => \$argv->{'formatter'}, + 'schemes=s' => \$argv->{'schemes'}, 'user_db1=s' => \$argv->{'user_db1'}, 'pass_db1=s' => \$argv->{'pass_db1'}, - 'connect_db2=s' => \$argv->{'connect_db2'}, 'user_db2=s' => \$argv->{'user_db2'}, 'pass_db2=s' => \$argv->{'pass_db2'}, 'help|h' => sub{ print_usage(); exit(0); }, @@ -184,12 +194,14 @@ sub get_options { sub print_usage { my $usage =<<__USAGE__ - This script compares two databases by structure and prints result in TAP format. + This script compares two databases by structure and prints result. compare_db.pl [options] OPTIONS - --result TAP file with results - --connect_db1 DSN of the 1st schema + --formatter=[tap] The format of output. + Supported values: + tap - print in a TAP format. + --schemes List of schemes which should be compared. --user_db1 User of the 1st schema --pass_db1 Password of the 1st schema --connect_db2 DSN of the 2nd schema @@ -205,16 +217,16 @@ __USAGE__ } sub print_diff { - my ($obj1, $obj2, $object_name, $result) = @_; + my ($obj1, $obj2, $object_name, $result, $schema) = @_; foreach my $key ( sort( keys( %{$obj1} ) ) ) { unless ( exists($obj2->{$key}) ) { - push( @{$result}, "$object_name element: $key is missing in Schema2" ); + push( @{$result}, "Schema $schema, $object_name element: $key is missing in Schema2" ); next; } foreach my $c_name ( sort( keys( %{ $obj1->{$key} } ) ) ) { unless ( exists($obj2->{$key}->{$c_name}) ) { - push( @{$result}, "$object_name element: $key.$c_name is missing in Schema2" ); + push( @{$result}, "Schema $schema, $object_name element: $key.$c_name is missing in Schema2" ); next; } @@ -225,20 +237,21 @@ sub print_diff { $obj2->{$key}->{$c_name} = 'NULL' if ( ! defined($obj2->{$key}->{$c_name}) ); if ( $obj1->{$key}->{$c_name} ne $obj2->{$key}->{$c_name} ) { - push( @{$result}, "$object_name elements: $key.$c_name are not equal: " - . "Schema1=$obj1->{$key}->{$c_name} vs Schema2=$obj2->{$key}->{$c_name}" ); + push( @{$result}, "Schema $schema, $object_name elements: $key.$c_name are not equal:\n ---\n" + . " Schema1: $obj1->{$key}->{$c_name}\n" + . " Schema2: $obj2->{$key}->{$c_name}" ); } } } foreach my $key ( sort( keys( %{$obj2} ) ) ) { unless ( exists($obj1->{$key}) ) { - push( @{$result}, "$object_name element: $key is missing in Schema1" ); + push( @{$result}, "Schema $schema, $object_name element: $key is missing in Schema1" ); next; } foreach my $c_name ( sort( keys( %{ $obj2->{$key} } ) ) ) { unless ( exists($obj1->{$key}->{$c_name}) ) { - push( @{$result}, "$object_name element: $key.$c_name is missing in Schema1" ); + push( @{$result}, "Schema $schema, $object_name element: $key.$c_name is missing in Schema1" ); next; } } @@ -246,3 +259,32 @@ sub print_diff { return 1; } + +sub tap_output { + my $number = scalar(@{$res}); + my $counter = 1; + if ( $number > 0 ) { + print "1..$number\n"; + foreach my $err ( @{$res} ) { + print "not ok $counter $err\n"; + $counter++; + } + } + else { + print "1..1\n"; + print "ok 1 All schemes are equal\n"; + } +} + +sub human_output { + my $number = scalar(@{$res}); + if ( $number > 0 ) { + print "The following errors were found:\n\n"; + foreach my $err ( @{$res} ) { + print "$err\n"; + } + } + else { + print "All schemes $argv->{schemes} are equal\n"; + } +} diff --git a/sbin/compare_dbs b/sbin/compare_dbs deleted file mode 100644 index a71d9fc..0000000 --- a/sbin/compare_dbs +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -rm -rf results -mkdir results - -if ! [[ -r /etc/ngcp-backup-tools/db-backup.conf ]]; then - echo "Cannot read mandatory config file /etc/ngcp-backup-tools/db-backup.conf" 2>&1 - exit 1 -fi -. /etc/ngcp-backup-tools/db-backup.conf - -location="$(dirname "$0")" -version="$(cat /etc/ngcp_version)" -case "${version}" in - 2.8|3.*|mr[3-7].*|mr8.0.*) - if [[ ! -r /etc/mysql/sipwise.cnf ]]; then - echo "Cannot read mandatory config file /etc/mysql/sipwise.cnf" 2>&1 - exit 1 - fi - . /etc/mysql/sipwise.cnf - for db in "${NGCP_DB_BACKUP_FINAL_LIST[@]}"; do - "${location}/compare_dbs.pl" \ - --result="results/result_${db}.tap" \ - --connect_db1="DBI:mysql:database=${db};host=sp1" \ - --user_db1='sipwise' \ - --pass_db1="${SIPWISE_DB_PASSWORD}" \ - --connect_db2="DBI:mysql:database=${db};host=sp2" \ - --user_db2='sipwise' \ - --pass_db2="${SIPWISE_DB_PASSWORD}" \ - || true - done - ;; - *) - MYSQL_CREDENTIALS='/etc/mysql/sipwise_extra.cnf' - if [[ ! -r "${MYSQL_CREDENTIALS}" ]]; then - echo "Cannot read mandatory config file '${MYSQL_CREDENTIALS}'" 2>&1 - exit 1 - fi - for db in "${NGCP_DB_BACKUP_FINAL_LIST[@]}"; do - "${location}/compare_dbs.pl" \ - --result="results/result_${db}.tap" \ - --connect_db1="DBI:mysql:database=${db};host=sp1;mysql_read_default_file=${MYSQL_CREDENTIALS}" \ - --connect_db2="DBI:mysql:database=${db};host=sp2;mysql_read_default_file=${MYSQL_CREDENTIALS}" \ - || true - done - ;; -esac diff --git a/sbin/ngcp-mysql-compare-dbs b/sbin/ngcp-mysql-compare-dbs new file mode 100755 index 0000000..04c3fc7 --- /dev/null +++ b/sbin/ngcp-mysql-compare-dbs @@ -0,0 +1,65 @@ +#!/bin/bash + +set -euo pipefail + +usage() { + cat - <<__USAGE__ +$(basename "$0") used to compare mysql schemes between two hosts. + +Usage: $(basename "$0") [options] + +Options: + + --formatter=[tap] - Specify the output format. + Skip it to get human readable output. + + -h|--help - Show this message. + +__USAGE__ +} + +FORMATTER='' + +args=$(getopt -n "$(basename "$0")" -o h -l help,formatter: -- "$@") +eval set -- "${args}" +while true; do + case "${1}" in + --formatter) + FORMATTER="${2}" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + --) + shift + break + ;; + *) + log_error "Unknown parameter '${1}'" + exit 1 + ;; + esac +done + +DB_BACKUP_LIST='/etc/ngcp-backup-tools/db-backup.conf' +if [[ ! -r "${DB_BACKUP_LIST}" ]]; then + echo "Cannot read mandatory config file ${DB_BACKUP_LIST}" 2>&1 + exit 1 +fi + +MYSQL_CREDENTIALS='/etc/mysql/sipwise_extra.cnf' +if [[ ! -r "${MYSQL_CREDENTIALS}" ]]; then + echo "Cannot read mandatory config file '${MYSQL_CREDENTIALS}'" 2>&1 + exit 1 +fi + +. "${DB_BACKUP_LIST}" +declare -a opts +if [[ -n "${FORMATTER}" ]]; then + opts+=(--formatter="${FORMATTER}") +fi +/usr/share/ngcp-system-tests/compare_dbs.pl \ + --schemes="${NGCP_DB_BACKUP_FINAL_LIST[*]}" \ + "${opts[@]}" || true