Skip to content

Commit

Permalink
RE-34: Move up the recording of the active remote MySQL profile
Browse files Browse the repository at this point in the history
Fixes an issue where it was not recorded when the `try` block actually
succeeded. I also golfed things down a bit where I could.
Notably, the unit test I had to modify died along the critical path
until I added a Test::MockFile invocation RE
/var/cpanel/elevate-mysql-profile.
I am pretty sure that this along with my manual testing should
ensure this functions properly going forward.

Changelog: Fix minor bug in original RE-34 fix where it would not always
  record the active profile.
  • Loading branch information
troglodyne committed Jul 31, 2024
1 parent 5ef8705 commit 44a5193
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 70 deletions.
55 changes: 25 additions & 30 deletions elevate-cpanel
Original file line number Diff line number Diff line change
Expand Up @@ -5470,65 +5470,60 @@ EOS
}

sub post_leapp ($self) {
return unless -e MYSQL_PROFILE_FILE;

if ( -e MYSQL_PROFILE_FILE ) {
my $original_profile = File::Slurper::read_text(MYSQL_PROFILE_FILE) // 'localhost';
INFO(qq{Reactivating "$original_profile" MySQL profile});
my $original_profile = File::Slurper::read_text(MYSQL_PROFILE_FILE) // 'localhost';
INFO(qq{Reactivating "$original_profile" MySQL profile});

my $output = $self->ssystem_capture_output( '/usr/local/cpanel/scripts/manage_mysql_profiles', '--activate', "$original_profile" );
my $stdout = join qq{\n}, @{ $output->{'stdout'} };

unless ( $stdout =~ m{MySQL profile activation done} ) {
die <<~"EOS";
Unable to reactivate the original remote MySQL profile "$original_profile":
my $output = $self->ssystem_capture_output( '/usr/local/cpanel/scripts/manage_mysql_profiles', '--activate', "$original_profile" );
my $stdout = join qq{\n}, @{ $output->{'stdout'} };

$stdout
unless ( $stdout =~ m{MySQL profile activation done} ) {
die <<~"EOS";
Unable to reactivate the original remote MySQL profile "$original_profile":
Please resolve the reported problems then run this script again with:
$stdout
/scripts/elevate-cpanel --continue
Please resolve the reported problems then run this script again with:
EOS
}
/scripts/elevate-cpanel --continue
unlink MYSQL_PROFILE_FILE;
EOS
}

unlink MYSQL_PROFILE_FILE or WARN( "Could not delete " . MYSQL_PROFILE_FILE . ": $!" );

return;
}

sub _ensure_localhost_mysql_profile_is_active ( $self, $should_create_localhost_profile ) {

if ( Cpanel::MysqlUtils::MyCnf::Basic::is_local_mysql() ) {
return;
}
return if Cpanel::MysqlUtils::MyCnf::Basic::is_local_mysql();

my $profile_manager = Cpanel::MysqlUtils::RemoteMySQL::ProfileManager->new();

my $profile = $profile_manager->get_active_profile('dont_die') || 'localhost';
if ($should_create_localhost_profile) {
INFO( "Saving the currently active MySQL Profile ($profile) to " . MYSQL_PROFILE_FILE );
File::Slurper::write_text( MYSQL_PROFILE_FILE, $profile );
}

try {
$profile_manager->validate_profile('localhost');
$self->_activate_localhost_profile($profile_manager);
}

catch {
if ($should_create_localhost_profile) {
INFO("Attempting to create new localhost MySQL profile...");
$self->_create_new_localhost_profile($profile_manager);
$self->_ensure_localhost_mysql_profile_is_active(0);
}
else {
die "Unable to generate/enable localhost MySQL profile: $_\n";
}
die "Unable to generate/enable localhost MySQL profile: $_\n" unless $should_create_localhost_profile;
INFO("Attempting to create new localhost MySQL profile...");
$self->_create_new_localhost_profile($profile_manager);
$self->_ensure_localhost_mysql_profile_is_active(0);
};

return;
}

sub _create_new_localhost_profile ( $self, $profile_manager ) {

my $active_profile = $profile_manager->get_active_profile('dont_die');
File::Slurper::write_text( MYSQL_PROFILE_FILE, $active_profile );

my $password = Cpanel::PasswdStrength::Generate::generate_password( 16, no_othersymbols => 1 );

try {
Expand Down
62 changes: 30 additions & 32 deletions lib/Elevate/Components/DatabaseUpgrade.pm
Original file line number Diff line number Diff line change
Expand Up @@ -36,52 +36,57 @@ sub pre_leapp ($self) {
# We don't auto-upgrade the database if provided by cloudlinux
return if Elevate::Database::is_database_provided_by_cloudlinux();

$self->_ensure_localhost_mysql_profile_is_active(1);

# If the database version is supported on the new OS version, then no need to upgrade
return if Elevate::Database::is_database_version_supported( Elevate::Database::get_local_database_version() );

$self->_ensure_localhost_mysql_profile_is_active(1);

Elevate::Database::upgrade_database_server();

return;
}

sub post_leapp ($self) {
return unless -e MYSQL_PROFILE_FILE;

if ( -e MYSQL_PROFILE_FILE ) {
my $original_profile = File::Slurper::read_text(MYSQL_PROFILE_FILE) // 'localhost';
INFO(qq{Reactivating "$original_profile" MySQL profile});

my $output = $self->ssystem_capture_output( '/usr/local/cpanel/scripts/manage_mysql_profiles', '--activate', "$original_profile" );
my $stdout = join qq{\n}, @{ $output->{'stdout'} };
my $original_profile = File::Slurper::read_text(MYSQL_PROFILE_FILE) // 'localhost';
INFO(qq{Reactivating "$original_profile" MySQL profile});

unless ( $stdout =~ m{MySQL profile activation done} ) {
die <<~"EOS";
Unable to reactivate the original remote MySQL profile "$original_profile":
my $output = $self->ssystem_capture_output( '/usr/local/cpanel/scripts/manage_mysql_profiles', '--activate', "$original_profile" );
my $stdout = join qq{\n}, @{ $output->{'stdout'} };

$stdout
unless ( $stdout =~ m{MySQL profile activation done} ) {
die <<~"EOS";
Unable to reactivate the original remote MySQL profile "$original_profile":
Please resolve the reported problems then run this script again with:
$stdout
/scripts/elevate-cpanel --continue
Please resolve the reported problems then run this script again with:
EOS
}
/scripts/elevate-cpanel --continue
unlink MYSQL_PROFILE_FILE;
EOS
}

unlink MYSQL_PROFILE_FILE or WARN( "Could not delete " . MYSQL_PROFILE_FILE . ": $!" );

return;
}

sub _ensure_localhost_mysql_profile_is_active ( $self, $should_create_localhost_profile ) {

if ( Cpanel::MysqlUtils::MyCnf::Basic::is_local_mysql() ) {
return;
}
return if Cpanel::MysqlUtils::MyCnf::Basic::is_local_mysql();

my $profile_manager = Cpanel::MysqlUtils::RemoteMySQL::ProfileManager->new();

# Immediately record the currently active profile, as othrewise you can
# miss it in the try/catch below. Default to localhost, because if there's
# no answer, something's probably wrong in a way we don't *want* to touch.
my $profile = $profile_manager->get_active_profile('dont_die') || 'localhost';
if ($should_create_localhost_profile) {
INFO( "Saving the currently active MySQL Profile ($profile) to " . MYSQL_PROFILE_FILE );
File::Slurper::write_text( MYSQL_PROFILE_FILE, $profile );
}

# Validate that the current “localhost” profile exists, and contains valid settings.
try {
$profile_manager->validate_profile('localhost');
Expand All @@ -90,24 +95,17 @@ sub _ensure_localhost_mysql_profile_is_active ( $self, $should_create_localhost_

# Otherwise attempt to recreate it, overwriting the existing profile.
catch {
if ($should_create_localhost_profile) {
INFO("Attempting to create new localhost MySQL profile...");
$self->_create_new_localhost_profile($profile_manager);
$self->_ensure_localhost_mysql_profile_is_active(0);
}
else {
die "Unable to generate/enable localhost MySQL profile: $_\n";
}
die "Unable to generate/enable localhost MySQL profile: $_\n" unless $should_create_localhost_profile;
INFO("Attempting to create new localhost MySQL profile...");
$self->_create_new_localhost_profile($profile_manager);
$self->_ensure_localhost_mysql_profile_is_active(0);
};

return;
}

sub _create_new_localhost_profile ( $self, $profile_manager ) {

my $active_profile = $profile_manager->get_active_profile('dont_die');
File::Slurper::write_text( MYSQL_PROFILE_FILE, $active_profile );

my $password = Cpanel::PasswdStrength::Generate::generate_password( 16, no_othersymbols => 1 );

try {
Expand Down
38 changes: 30 additions & 8 deletions t/components-DatabaseUpgrade.t
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#!/usr/local/cpanel/3rdparty/bin/perl
package test::cpev::components;

# Copyright 2024 WebPros International, LLC
# All rights reserved.
# copyright@cpanel.net http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited.

package test::cpev::components;
use cPstrict;

use FindBin;

Expand All @@ -20,11 +21,6 @@ use Test::MockFile qw/strict/;
use lib $FindBin::Bin . "/lib";
use Test::Elevate;

use cPstrict;

use strict;
use warnings;

use constant PROFILE_FILE => Elevate::Components::DatabaseUpgrade::MYSQL_PROFILE_FILE;

my $db_upgrade = bless {}, 'Elevate::Components::DatabaseUpgrade';
Expand Down Expand Up @@ -117,7 +113,8 @@ my $db_upgrade = bless {}, 'Elevate::Components::DatabaseUpgrade';
{
note('Checking _ensure_localhost_mysql_profile_is_active');

my $mock_mysqlutils = Test::MockModule->new('Cpanel::MysqlUtils::MyCnf::Basic');
my $saved_db_file_mock = Test::MockFile->file('/var/cpanel/elevate-mysql-profile');
my $mock_mysqlutils = Test::MockModule->new('Cpanel::MysqlUtils::MyCnf::Basic');
$mock_mysqlutils->redefine( 'is_local_mysql', 1 );

my $instantiated_pm = 0;
Expand All @@ -128,7 +125,30 @@ my $db_upgrade = bless {}, 'Elevate::Components::DatabaseUpgrade';
is $instantiated_pm, 0, 'ProfileManager instance not created when is_local_mysql returns true';

$mock_mysqlutils->redefine( 'is_local_mysql', 0 );
$mock_pm->redefine( 'validate_profile', sub { die 'foo' } );
$mock_pm->redefine(
'validate_profile', sub { die 'foo' },
'read_profiles',
sub {
return {
'localhost' => {
'mysql_port' => '3306',
'mysql_pass' => 'hunter2',
'mysql_host' => 'localhost',
'mysql_user' => 'azurediamond',
'setup_via' => 'Auto-Migrated active profile',
'active' => 0,
},
'remote' => {
'mysql_port' => '69420',
'mysql_pass' => 'NHTSA_R00lz',
'mysql_host' => 'test.test',
'mysql_user' => 'crash_test_dummy',
'setup_via' => "The People's Quality Front",
'active' => 1
},
};
},
);

like(
dies { $db_upgrade->_ensure_localhost_mysql_profile_is_active(0) },
Expand All @@ -146,10 +166,12 @@ my $db_upgrade = bless {}, 'Elevate::Components::DatabaseUpgrade';
'Died as expected when _activate_localhost_profile fails and should_create_localhost_profile is false'
);

$mock_pm->redefine( 'validate_profile', sub { die "whugg" } );
my $created_new_localhost_profile = 0;
$mock_db_upgrade->redefine( '_create_new_localhost_profile', sub { $created_new_localhost_profile = 1 } );
eval { $db_upgrade->_ensure_localhost_mysql_profile_is_active(1) };
is $created_new_localhost_profile, 1, '_create_new_localhost_profile() was called when existing profile failed to validate/activate';
message_seen( 'INFO', qr{Saving the currently active MySQL Profile \(remote\) to /var/cpanel/elevate-mysql-profile} );
message_seen( 'INFO', qr/Attempting to create new localhost MySQL profile/ );

clear_messages_seen();
Expand Down

0 comments on commit 44a5193

Please sign in to comment.