Skip to content

Commit

Permalink
Fixes #37177 - Upgrade PostgreSQL to 13 on EL8
Browse files Browse the repository at this point in the history
  • Loading branch information
evgeni committed Mar 11, 2024
1 parent 72c1526 commit 3f846ff
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 1 deletion.
2 changes: 1 addition & 1 deletion config/foreman.hiera/family/RedHat-8.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
postgresql::globals::manage_dnf_module: true
postgresql::globals::version: "12"
postgresql::globals::version: "13"

redis::dnf_module_stream: "6"
redis::package_ensure: ">=6.0"
18 changes: 18 additions & 0 deletions hooks/boot/01-kafo-hook-extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ def execute!(command, do_say = true, do_log = true)
end
end

def execute_as!(user, command, do_say = true, do_log = true)
runuser_command = "runuser -l #{user} -c '#{command}'"
execute!(runuser_command, do_say, do_log)
end

def execute(command, do_say, do_log)
_stdout_stderr, status = execute_command(command, do_say, do_log)
status
Expand All @@ -139,6 +144,19 @@ def execute_command(command, do_say, do_log)
def remote_host?(hostname)
!['localhost', '127.0.0.1', `hostname`.strip].include?(hostname)
end

def el8?
facts[:os][:release][:major] == '8' && facts[:os][:family] == 'RedHat'
end

def available_space(directory = nil)
directory = '/' if directory.nil?
mountpoints = facts[:mountpoints]
until (mountpoint = mountpoints[directory.to_sym])
directory = File.dirname(directory)
end
mountpoint[:available_bytes]
end
end

Kafo::HookContext.send(:include, HookContextExtension)
66 changes: 66 additions & 0 deletions hooks/boot/06-postgresql-upgrade-extensions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
module PostgresqlUpgradeHookContextExtension
def needs_postgresql_upgrade?(new_version)
File.read('/var/lib/pgsql/data/PG_VERSION').chomp.to_i < new_version.to_i
rescue Errno::ENOENT
false
end

def os_needs_postgresql_upgrade?
el8? && needs_postgresql_upgrade?(13)
end

def postgresql_upgrade(new_version)
logger.notice("Performing upgrade of PostgreSQL to #{new_version}")

stop_services

logger.notice("Upgrading PostgreSQL packages")

execute!("dnf module switch-to postgresql:#{new_version} -y", false, true)

server_packages = ['postgresql', 'postgresql-server', 'postgresql-upgrade']
['postgresql-contrib', 'postgresql-docs'].each do |extra_package|
if execute("rpm -q #{extra_package}", false, false)
server_packages << extra_package
end
end

ensure_packages(server_packages, 'latest')

logger.notice("Migrating PostgreSQL data")

# puppetlabs-postgresql always sets data_directory in the config
# see https://github.com/puppetlabs/puppetlabs-postgresql/issues/1576
# however, one can't use postgresql-setup --upgrade if that value is set
# see https://bugzilla.redhat.com/show_bug.cgi?id=1935301
execute!("sed -i '/^data_directory/d' /var/lib/pgsql/data/postgresql.conf", false, true)

execute_as!('postgres', 'postgresql-setup --upgrade', false, true)

logger.notice("Analyzing the new PostgreSQL cluster")

start_services(['postgresql'])

execute_as!('postgres', 'vacuumdb --all --analyze-in-stages', false, true)

logger.notice("Upgrade to PostgreSQL #{new_version} completed")
end

def check_postgresql_storage
# Ensure there is at least 1x /var/lib/pgsql free disk space available on the main filesystem
current_postgres_dir = '/var/lib/pgsql/data'
new_postgres_dir = '/var/lib/pgsql'

begin
postgres_size = `du --bytes --summarize #{current_postgres_dir}`.split[0].to_i

if available_space(new_postgres_dir) < postgres_size
fail_and_exit "The PostgreSQL upgrade requires at least #{(postgres_size / 1024) / 1024} MB of storage to be available at #{new_postgres_dir}."
end
rescue StandardError
fail_and_exit 'Failed to verify available disk space'
end
end
end

Kafo::HookContext.send(:include, PostgresqlUpgradeHookContextExtension)
3 changes: 3 additions & 0 deletions hooks/pre/30-el8_upgrade_postgresql.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if local_postgresql? && os_needs_postgresql_upgrade?
postgresql_upgrade(13)
end
3 changes: 3 additions & 0 deletions hooks/pre_validations/30-el8_upgrade_postgresql.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if local_postgresql? && os_needs_postgresql_upgrade?
check_postgresql_storage
end
29 changes: 29 additions & 0 deletions spec/hook_context_extension_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -142,5 +142,34 @@
end
end
end

describe '.execute!' do
subject { context.execute!(command) }
let(:command) { 'uptime' }

before do
allow(context).to receive(:execute_command).and_return([command, true])
end

it 'executes a command' do
expect(subject).to be_nil
expect(context).to have_received(:execute_command).with(command, true, true)
end
end

describe '.execute_as!' do
subject { context.execute_as!(user, command) }
let(:command) { 'uptime' }
let(:user) { 'postgres' }

before do
allow(context).to receive(:execute!)
end

it 'executes a command' do
expect(subject).to be_nil
expect(context).to have_received(:execute!).with("runuser -l postgres -c 'uptime'", true, true)
end
end
end
end
68 changes: 68 additions & 0 deletions spec/postgresql_upgrade_hook_context_extension_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
require 'spec_helper'
require 'kafo/hook_context'

require_relative '../hooks/boot/06-postgresql-upgrade-extensions'

describe PostgresqlUpgradeHookContextExtension do
let(:kafo) { instance_double(Kafo::KafoConfigure) }
let(:logger) { instance_double(Kafo::Logger) }
let(:context) { Kafo::HookContext.new(kafo, logger) }

describe '.needs_postgresql_upgrade?' do
subject { context.needs_postgresql_upgrade?(13) }

it 'returns true for PostgreSQL 12' do
expect(File).to receive(:read).with('/var/lib/pgsql/data/PG_VERSION').and_return('12')
expect(subject).to be_truthy
end

it 'returns false for PostgreSQL 13' do
expect(File).to receive(:read).with('/var/lib/pgsql/data/PG_VERSION').and_return('13')
expect(subject).to be_falsy
end

it 'returns false when no PostgreSQL version file was found' do
expect(File).to receive(:read).with('/var/lib/pgsql/data/PG_VERSION').and_raise(Errno::ENOENT)
expect(subject).to be_falsy
end
end

describe '.postgresql_upgrade' do
subject { context.postgresql_upgrade(13) }

before do
allow(context).to receive(:logger).and_return(logger)
allow(context).to receive(:'execute!')
allow(context).to receive(:ensure_packages)
allow(context).to receive(:stop_services)
allow(context).to receive(:start_services)
allow(logger).to receive(:notice)
end

it 'logs the upgrade' do
expect(subject).to be_nil
expect(logger).to have_received(:notice).with('Performing upgrade of PostgreSQL to 13')
expect(logger).to have_received(:notice).with('Upgrade to PostgreSQL 13 completed')
end

it 'switches the dnf module' do
expect(subject).to be_nil
expect(context).to have_received(:'execute!').with('dnf module switch-to postgresql:13 -y', false, true)
end

it 'removes data_directory from postgresql.conf' do
expect(subject).to be_nil
expect(context).to have_received(:'execute!').with("sed -i '/^data_directory/d' /var/lib/pgsql/data/postgresql.conf", false, true)
end

it 'runs postgresql-setup --upgrade' do
expect(subject).to be_nil
expect(context).to have_received(:'execute!').with("runuser -l postgres -c 'postgresql-setup --upgrade'", false, true)
end

it 'runs vacuumdb --all --analyze-in-stages' do
expect(subject).to be_nil
expect(context).to have_received(:'execute!').with("runuser -l postgres -c 'vacuumdb --all --analyze-in-stages'", false, true)
end
end
end

0 comments on commit 3f846ff

Please sign in to comment.