From dca47d72ee2c0158232806233e9d40c61be2949d Mon Sep 17 00:00:00 2001 From: Tim Mullin Date: Wed, 10 Jan 2024 20:45:05 +0000 Subject: [PATCH] Refuse to run if --check has not first been run successfully --- elevate-cpanel | 51 +++++++++++++++++++++++++++++++++++++--- lib/Elevate/Blockers.pm | 49 ++++++++++++++++++++++++++++++++++++-- script/elevate-cpanel.PL | 1 + 3 files changed, 96 insertions(+), 5 deletions(-) diff --git a/elevate-cpanel b/elevate-cpanel index 2a04609c..cde23732 100755 --- a/elevate-cpanel +++ b/elevate-cpanel @@ -244,13 +244,14 @@ BEGIN { # Suppress load of all of these at earliest point. AbsoluteSymlinks }; - use constant ELEVATE_BLOCKER_FILE => '/var/cpanel/elevate-blockers'; + use constant ELEVATE_BLOCKER_FILE_EXPIRE_TIME => 6 * 60 * 60; # Six hours + use constant ELEVATE_BLOCKER_FILE => '/var/cpanel/elevate-blockers'; - our $_CHECK_MODE; # for now global so we can use the helper (move it later to the object) + our $_CHECK_MODE; # for now global so we can use the helper (move it later to the object) sub _build_blockers { [] } - sub check ( $self, %opts ) { # do_check - main entry point + sub check ( $self, %opts ) { # do_check - main entry point if ( $self->cpev->service->is_active ) { WARN("An elevation process is already in progress."); @@ -286,6 +287,49 @@ BEGIN { # Suppress load of all of these at earliest point. return $has_blockers; } + sub bail_if_check_not_run_or_blockers_found () { + + if ( !check_run_recently() ) { + FATAL("You must first run script with --check to check if your server is ready to upgrade"); + exit 1; + } + + my $blocker_ar = load_past_blockers(); + + return unless scalar @$blocker_ar; + + say "The following blockers must still be resolved:"; + foreach my $bl (@$blocker_ar) { + say ''; + say $bl->{id} . ':'; + say $bl->{msg}; + } + + FATAL("You must fix all blockers and re-run with --check before performing the upgrade."); + exit 1; + } + + sub check_run_recently () { + return 0 if ( !-f ELEVATE_BLOCKER_FILE ); + + return ( ( stat(ELEVATE_BLOCKER_FILE) )[9] + ELEVATE_BLOCKER_FILE_EXPIRE_TIME > time() ) ? 1 : 0; + } + + sub load_past_blockers ( $blocker_file = ELEVATE_BLOCKER_FILE ) { + + my $blocker_hr = eval { Cpanel::JSON::LoadFile($blocker_file) } // {}; + if ($@) { + WARN("Unable to load contents of $blocker_file: $@"); + return []; + } + if ( ref $blocker_hr ne 'HASH' || !exists $blocker_hr->{blockers} || ref $blocker_hr->{blockers} ne 'ARRAY' ) { + WARN("The blocker file $blocker_file is malformed"); + return []; + } + + return $blocker_hr->{blockers}; + } + sub _has_blockers ( $self, $check_mode = 0 ) { unless ( $< == 0 ) { @@ -5179,6 +5223,7 @@ sub monitor_upgrade ($self) { sub start ($self) { Elevate::Blockers::Distros::bail_out_on_inappropriate_distro(); + Elevate::Blockers::bail_if_check_not_run_or_blockers_found(); my $stage = get_stage(); if ( $stage != 0 ) { my $header; diff --git a/lib/Elevate/Blockers.pm b/lib/Elevate/Blockers.pm index 20511a62..84cce207 100644 --- a/lib/Elevate/Blockers.pm +++ b/lib/Elevate/Blockers.pm @@ -69,9 +69,10 @@ our @BLOCKERS = qw{ AbsoluteSymlinks }; -use constant ELEVATE_BLOCKER_FILE => '/var/cpanel/elevate-blockers'; +use constant ELEVATE_BLOCKER_FILE_EXPIRE_TIME => 6 * 60 * 60; # Six hours +use constant ELEVATE_BLOCKER_FILE => '/var/cpanel/elevate-blockers'; -our $_CHECK_MODE; # for now global so we can use the helper (move it later to the object) +our $_CHECK_MODE; # for now global so we can use the helper (move it later to the object) sub _build_blockers { [] } @@ -112,6 +113,50 @@ sub check ( $self, %opts ) { # do_check - main entry point return $has_blockers; } +sub bail_if_check_not_run_or_blockers_found () { + + if ( !check_run_recently() ) { + FATAL("You must first run script with --check to check if your server is ready to upgrade"); + exit 1; + } + + my $blocker_ar = load_past_blockers(); + + # Pass if no blockers in blocker file + return unless scalar @$blocker_ar; + + say "The following blockers must still be resolved:"; + foreach my $bl (@$blocker_ar) { + say ''; + say $bl->{id} . ':'; + say $bl->{msg}; + } + + FATAL("You must fix all blockers and re-run with --check before performing the upgrade."); + exit 1; +} + +sub check_run_recently () { + return 0 if ( !-f ELEVATE_BLOCKER_FILE ); + + return ( ( stat(ELEVATE_BLOCKER_FILE) )[9] + ELEVATE_BLOCKER_FILE_EXPIRE_TIME > time() ) ? 1 : 0; +} + +sub load_past_blockers ( $blocker_file = ELEVATE_BLOCKER_FILE ) { + + my $blocker_hr = eval { Cpanel::JSON::LoadFile($blocker_file) } // {}; + if ($@) { + WARN("Unable to load contents of $blocker_file: $@"); + return []; + } + if ( ref $blocker_hr ne 'HASH' || !exists $blocker_hr->{blockers} || ref $blocker_hr->{blockers} ne 'ARRAY' ) { + WARN("The blocker file $blocker_file is malformed"); + return []; + } + + return $blocker_hr->{blockers}; +} + sub _has_blockers ( $self, $check_mode = 0 ) { unless ( $< == 0 ) { diff --git a/script/elevate-cpanel.PL b/script/elevate-cpanel.PL index 3685985f..654c8963 100755 --- a/script/elevate-cpanel.PL +++ b/script/elevate-cpanel.PL @@ -515,6 +515,7 @@ sub monitor_upgrade ($self) { sub start ($self) { Elevate::Blockers::Distros::bail_out_on_inappropriate_distro(); + Elevate::Blockers::bail_if_check_not_run_or_blockers_found(); my $stage = get_stage(); if ( $stage != 0 ) { my $header;