Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #34195 - add apt package manager for debian #576

Merged
merged 16 commits into from
Jun 1, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions definitions/scenarios/packages.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ def compose
else
add_steps_with_context(
Procedures::Packages::UpdateAllConfirmation,
Procedures::Packages::InstallerConfirmation,
Procedures::Packages::UnlockVersions
Procedures::Packages::InstallerConfirmation
)
add_step_with_context(Procedures::Packages::UnlockVersions)
add_step_with_context(Procedures::Packages::Update,
:force => true, :warn_on_errors => true)
add_step_with_context(Procedures::Installer::Upgrade)
Expand Down
29 changes: 22 additions & 7 deletions lib/foreman_maintain/cli/packages_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,27 @@ class PackagesCommand < Base
subcommand 'lock', 'Prevent packages from automatic update' do
interactive_option(['assumeyes'])
def execute
run_scenarios_and_exit(Scenarios::Packages::Lock.new)
run_scenario_or_rescue do
run_scenarios_and_exit(Scenarios::Packages::Lock.new)
end
end
end

subcommand 'unlock', 'Enable packages for automatic update' do
interactive_option(['assumeyes'])
def execute
run_scenarios_and_exit(Scenarios::Packages::Unlock.new)
run_scenario_or_rescue do
run_scenarios_and_exit(Scenarios::Packages::Unlock.new)
end
end
end

subcommand 'status', 'Check if packages are protected against update' do
interactive_option(['assumeyes'])
def execute
run_scenarios_and_exit(Scenarios::Packages::Status.new)
run_scenario_or_rescue do
run_scenarios_and_exit(Scenarios::Packages::Status.new)
end
end
end

Expand Down Expand Up @@ -60,12 +66,21 @@ def execute
subcommand 'is-locked', 'Check if update of packages is allowed' do
interactive_option(['assumeyes'])
def execute
locked = ForemanMaintain.package_manager.versions_locked?
puts "Packages are#{locked ? '' : ' not'} locked"
exit_code = locked ? 0 : 1
exit exit_code
run_scenario_or_rescue do
locked = ForemanMaintain.package_manager.versions_locked?
puts "Packages are#{locked ? '' : ' not'} locked"
exit_code = locked ? 0 : 1
exit exit_code
end
end
end

def run_scenario_or_rescue
yield
rescue NotImplementedError
upadhyeammit marked this conversation as resolved.
Show resolved Hide resolved
puts 'Command is not implemented for Debian based operating systems!'
upadhyeammit marked this conversation as resolved.
Show resolved Hide resolved
exit 0
end
end
end
end
8 changes: 6 additions & 2 deletions lib/foreman_maintain/concerns/system_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,12 @@ def packages_action(action, packages, options = {})
end

def package_version(name)
# space for extension to support non-rpm distributions
pkg = package_manager.find_installed_package(name, '%{VERSION}')
ver = if el?
'%{VERSION}'
elsif debian?
'${VERSION}'
end
pkg = package_manager.find_installed_package(name, ver)
version(pkg) unless pkg.nil?
end

Expand Down
8 changes: 5 additions & 3 deletions lib/foreman_maintain/package_manager.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
require 'foreman_maintain/package_manager/base'
require 'foreman_maintain/package_manager/yum'
require 'foreman_maintain/package_manager/dnf'
require 'foreman_maintain/package_manager/apt'

module ForemanMaintain
def self.package_manager
@package_manager ||= case (%w[dnf yum apt].find { |manager| !`command -v #{manager}`.empty? })
when 'dnf'
@package_manager ||= if el? && !el7?
ForemanMaintain::PackageManager::Dnf.new
upadhyeammit marked this conversation as resolved.
Show resolved Hide resolved
when 'yum'
elsif el? && el7?
ForemanMaintain::PackageManager::Yum.new
upadhyeammit marked this conversation as resolved.
Show resolved Hide resolved
elsif debian?
ForemanMaintain::PackageManager::Apt.new
else
raise 'No supported package manager was found'
end
upadhyeammit marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
63 changes: 63 additions & 0 deletions lib/foreman_maintain/package_manager/apt.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
module ForemanMaintain::PackageManager
class Apt < Base
def installed?(packages)
packages_list = [packages].flatten(1).map { |pkg| "'#{pkg}'" }.join(' ')
sys.execute?(%(dpkg-query -l #{packages_list}))
end

def install(packages, assumeyes: false)
apt_action('install', packages, :assumeyes => assumeyes)
end

def remove(packages, assumeyes: false)
apt_action('remove', packages, :assumeyes => assumeyes)
end

def update(packages = [], assumeyes: false)
action = packages.any? ? '--only-upgrade install' : 'upgrade'
apt_action(action, packages, :assumeyes => assumeyes)
end

def clean_cache(assumeyes: false)
apt_action('clean', :assumeyes => assumeyes)
end

def find_installed_package(name, queryfm = '')
dpkg_cmd = "dpkg-query --show #{name}"
unless queryfm.empty?
dpkg_cmd = "dpkg-query --showformat='#{queryfm}' --show #{name}"
end
status, result = sys.execute_with_status(dpkg_cmd)
if status == 0
result
end
end

def check_update(packages: nil, with_status: false)
apt_action('list --upgradable -a', packages, :with_status => with_status)
end

def list_installed_packages(queryfm = '${binary:Package}-${VERSION}\n')
# The queryfm should only include valid tag(s) as per `dpkg-query` man page.
# If any special formatting is required with querytag then it should be provided with tag i.e,
# querytag = "--%{VERSION}"
# The queryfm string must end with '\n'
sys.execute!("dpkg-query --showformat='#{queryfm}' -W").split("\n")
end

def apt_action(action, packages, with_status: false, assumeyes: false, valid_exit_statuses: [0])
apt_options = []
packages = [packages].flatten(1)
apt_options << '-y' if assumeyes
apt_options_s = apt_options.empty? ? '' : ' ' + apt_options.join(' ')
packages_s = packages.empty? ? '' : ' ' + packages.join(' ')
if with_status
sys.execute_with_status("apt#{apt_options_s} #{action}#{packages_s}",
:interactive => !assumeyes)
else
sys.execute!("apt#{apt_options_s} #{action}#{packages_s}",
:interactive => !assumeyes, :valid_exit_statuses => valid_exit_statuses)
upadhyeammit marked this conversation as resolved.
Show resolved Hide resolved
end
end
end
end
16 changes: 13 additions & 3 deletions test/lib/foreman_maintain_test.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

describe ForemanMaintain do
subject { ForemanMaintain }

Expand All @@ -8,17 +9,26 @@
end

it 'instantiates correct yum manager implementation' do
subject.stubs(:`).with('command -v yum').returns('/bin/yum')
subject.stubs(:el?).returns(true)
subject.stubs(:el7?).returns(true)
subject.package_manager.must_be_instance_of ForemanMaintain::PackageManager::Yum
end

it 'instantiates correct dnf manager implementation' do
subject.stubs(:`).with('command -v yum').returns('/bin/yum')
subject.stubs(:`).with('command -v dnf').returns('/bin/dnf')
subject.stubs(:el?).returns(true)
subject.stubs(:el7?).returns(false)
subject.package_manager.must_be_instance_of ForemanMaintain::PackageManager::Dnf
end

it 'instantiates correct apt manager implementation' do
subject.stubs(:el?).returns(false)
subject.stubs(:debian?).returns(true)
subject.package_manager.must_be_instance_of ForemanMaintain::PackageManager::Apt
end

it 'fail on unknown manager type' do
subject.stubs(:el?).returns(false)
subject.stubs(:debian?).returns(false)
err = proc { subject.package_manager }.must_raise Exception
err.message.must_equal 'No supported package manager was found'
end
Expand Down