@ -56,6 +56,14 @@ options:
choices : [ " yes " , " no " ]
version_added : " 1.3 "
force :
description :
- Force remove package , without any checks .
required : false
default : " no "
choices : [ " yes " , " no " ]
version_added : " 2.0 "
update_cache :
description :
- Whether or not to refresh the master package lists . This can be
@ -63,6 +71,14 @@ options:
required : false
default : " no "
choices : [ " yes " , " no " ]
upgrade :
description :
- Whether or not to upgrade whole system
required : false
default : " no "
choices : [ " yes " , " no " ]
version_added : " 2.0 "
'''
EXAMPLES = '''
@ -80,6 +96,12 @@ EXAMPLES = '''
# Run the equivalent of "pacman -Sy" as a separate step
- pacman : update_cache = yes
# Run the equivalent of "pacman -Su" as a separate step
- pacman : upgrade = yes
# Run the equivalent of "pacman -Rdd", force remove package baz
- pacman : name = baz state = absent force = yes
'''
import json
@ -88,8 +110,6 @@ import os
import re
import sys
PACMAN_PATH = " /usr/bin/pacman "
def get_version ( pacman_output ) :
""" Take pacman -Qi or pacman -Si output and get the Version """
lines = pacman_output . split ( ' \n ' )
@ -98,10 +118,10 @@ def get_version(pacman_output):
return line . split ( ' : ' ) [ 1 ] . strip ( )
return None
def query_package ( module , name, state = " present " ) :
def query_package ( module , pacman_path, name, state = " present " ) :
""" Query the package status in both the local system and the repository. Returns a boolean to indicate if the package is installed, and a second boolean to indicate if the package is up-to-date. """
if state == " present " :
lcmd = " pacman -Qi %s " % ( name )
lcmd = " %s -Qi %s " % ( pacman_path , name )
lrc , lstdout , lstderr = module . run_command ( lcmd , check_rc = False )
if lrc != 0 :
# package is not installed locally
@ -110,7 +130,7 @@ def query_package(module, name, state="present"):
# get the version installed locally (if any)
lversion = get_version ( lstdout )
rcmd = " pacman -Si %s " % ( name )
rcmd = " %s -Si %s " % ( pacman_path , name )
rrc , rstdout , rstderr = module . run_command ( rcmd , check_rc = False )
# get the version in the repository
rversion = get_version ( rstdout )
@ -123,8 +143,8 @@ def query_package(module, name, state="present"):
return False , False
def update_package_db ( module ):
cmd = " pacman -Sy"
def update_package_db ( module , pacman_path ):
cmd = " %s -Sy" % ( pacman_path )
rc , stdout , stderr = module . run_command ( cmd , check_rc = False )
if rc == 0 :
@ -132,22 +152,41 @@ def update_package_db(module):
else :
module . fail_json ( msg = " could not update package db " )
def upgrade ( module , pacman_path ) :
cmdupgrade = " %s -Suq --noconfirm " % ( pacman_path )
cmdneedrefresh = " %s -Qqu " % ( pacman_path )
rc , stdout , stderr = module . run_command ( cmdneedrefresh , check_rc = False )
if rc == 0 :
rc , stdout , stderr = module . run_command ( cmdupgrade , check_rc = False )
if rc == 0 :
module . exit_json ( changed = True , msg = ' System upgraded ' )
else :
module . fail_json ( msg = " could not upgrade " )
else :
module . exit_json ( changed = False , msg = ' Nothing to upgrade ' )
def remove_packages ( module , packages ) :
def remove_packages ( module , pac man_path, pac kages) :
if module . params [ " recurse " ] :
args = " Rs "
else :
args = " R "
def remove_packages ( module , pacman_path , packages ) :
if module . params [ " force " ] :
args = " Rdd "
else :
args = " R "
remove_c = 0
# Using a for loop incase of error, we can report the package that failed
for package in packages :
# Query the package first, to see if we even need to remove
installed , updated = query_package ( module , package )
installed , updated = query_package ( module , pac man_path, pac kage)
if not installed :
continue
cmd = " pacman -%s %s --noconfirm " % ( args , package )
cmd = " %s -%s %s --noconfirm " % ( pacman_path , args , package )
rc , stdout , stderr = module . run_command ( cmd , check_rc = False )
if rc != 0 :
@ -162,12 +201,12 @@ def remove_packages(module, packages):
module . exit_json ( changed = False , msg = " package(s) already absent " )
def install_packages ( module , state, packages , package_files ) :
def install_packages ( module , pacman_path, state, packages , package_files ) :
install_c = 0
for i , package in enumerate ( packages ) :
# if the package is installed and state == present or state == latest and is up-to-date then skip
installed , updated = query_package ( module , pac kage)
installed , updated = query_package ( module , pac man_path, pac kage)
if installed and ( state == ' present ' or ( state == ' latest ' and updated ) ) :
continue
@ -176,7 +215,7 @@ def install_packages(module, state, packages, package_files):
else :
params = ' -S %s ' % package
cmd = " pacman %s --noconfirm " % ( params )
cmd = " %s %s --noconfirm " % ( pacman_path , params )
rc , stdout , stderr = module . run_command ( cmd , check_rc = False )
if rc != 0 :
@ -190,10 +229,10 @@ def install_packages(module, state, packages, package_files):
module . exit_json ( changed = False , msg = " package(s) already installed " )
def check_packages ( module , pac kages, state ) :
def check_packages ( module , pac man_path, pac kages, state ) :
would_be_changed = [ ]
for package in packages :
installed , updated = query_package ( module , pac kage)
installed , updated = query_package ( module , pac man_path, pac kage)
if ( ( state in [ " present " , " latest " ] and not installed ) or
( state == " absent " and installed ) or
( state == " latest " and not updated ) ) :
@ -213,12 +252,16 @@ def main():
name = dict ( aliases = [ ' pkg ' ] ) ,
state = dict ( default = ' present ' , choices = [ ' present ' , ' installed ' , " latest " , ' absent ' , ' removed ' ] ) ,
recurse = dict ( default = ' no ' , choices = BOOLEANS , type = ' bool ' ) ,
force = dict ( default = ' no ' , choices = BOOLEANS , type = ' bool ' ) ,
upgrade = dict ( default = ' no ' , choices = BOOLEANS , type = ' bool ' ) ,
update_cache = dict ( default = ' no ' , aliases = [ ' update-cache ' ] , choices = BOOLEANS , type = ' bool ' ) ) ,
required_one_of = [ [ ' name ' , ' update_cache ' ] ] ,
required_one_of = [ [ ' name ' , ' update_cache ' , ' upgrade ' ]] ,
supports_check_mode = True )
if not os . path . exists ( PACMAN_PATH ) :
module . fail_json ( msg = " cannot find pacman, looking for %s " % ( PACMAN_PATH ) )
pacman_path = module . get_bin_path ( ' pacman ' , True )
if not os . path . exists ( pacman_path ) :
module . fail_json ( msg = " cannot find pacman, in path %s " % ( pacman_path ) )
p = module . params
@ -229,13 +272,16 @@ def main():
p [ ' state ' ] = ' absent '
if p [ " update_cache " ] and not module . check_mode :
update_package_db ( module )
update_package_db ( module , pacman_path )
if not p [ ' name ' ] :
module . exit_json ( changed = True , msg = ' updated the package master lists ' )
if p [ ' update_cache ' ] and module . check_mode and not p [ ' name ' ] :
module . exit_json ( changed = True , msg = ' Would have updated the package cache ' )
if p [ ' upgrade ' ] :
upgrade ( module , pacman_path )
if p [ ' name ' ] :
pkgs = p [ ' name ' ] . split ( ' , ' )
@ -250,14 +296,15 @@ def main():
pkg_files . append ( None )
if module . check_mode :
check_packages ( module , p kgs, p [ ' state ' ] )
check_packages ( module , p acman_path, p kgs, p [ ' state ' ] )
if p [ ' state ' ] in [ ' present ' , ' latest ' ] :
install_packages ( module , p [ ' state ' ] , pkgs , pkg_files )
install_packages ( module , p acman_path, p [ ' state ' ] , pkgs , pkg_files )
elif p [ ' state ' ] == ' absent ' :
remove_packages ( module , p kgs)
remove_packages ( module , p acman_path, p kgs)
# import module snippets
from ansible . module_utils . basic import *
if __name__ == " __main__ " :
main ( )