@ -3,6 +3,7 @@
# Copyright (c) 2013 Shaun Zinck <shaun.zinck at gmail.com>
# Copyright (c) 2013 Shaun Zinck <shaun.zinck at gmail.com>
# Copyright (c) 2015 Lawrence Leonard Gilbert <larry@L2G.to>
# Copyright (c) 2015 Lawrence Leonard Gilbert <larry@L2G.to>
# Copyright (c) 2016 Jasper Lievisse Adriaanse <j at jasper.la>
#
#
# Written by Shaun Zinck
# Written by Shaun Zinck
# Based on pacman module written by Afterburn <http://github.com/afterburn>
# Based on pacman module written by Afterburn <http://github.com/afterburn>
@ -33,6 +34,7 @@ version_added: "1.0"
author :
author :
- " Larry Gilbert (L2G) "
- " Larry Gilbert (L2G) "
- " Shaun Zinck (@szinck) "
- " Shaun Zinck (@szinck) "
- " Jasper Lievisse Adriaanse (@jasperla) "
notes :
notes :
- " Known bug with pkgin < 0.8.0: if a package is removed and another
- " Known bug with pkgin < 0.8.0: if a package is removed and another
package depends on it , the other package will be silently removed as
package depends on it , the other package will be silently removed as
@ -57,6 +59,34 @@ options:
default : no
default : no
choices : [ " yes " , " no " ]
choices : [ " yes " , " no " ]
version_added : " 2.1 "
version_added : " 2.1 "
upgrade :
description :
- Upgrade main packages to their newer versions
required : false
default : no
choices : [ " yes " , " no " ]
version_added : " 2.1 "
full_upgrade :
description :
- Upgrade all packages to their newer versions
required : false
default : no
choices : [ " yes " , " no " ]
version_added : " 2.1 "
clean :
description :
- Clean packages cache
required : false
default : no
choices : [ " yes " , " no " ]
version_added : " 2.1 "
force :
description :
- Force package reinstall
required : false
default : no
choices : [ " yes " , " no " ]
version_added : " 2.1 "
'''
'''
EXAMPLES = '''
EXAMPLES = '''
@ -74,12 +104,24 @@ EXAMPLES = '''
# Update repositories as a separate step
# Update repositories as a separate step
- pkgin : update_cache = yes
- pkgin : update_cache = yes
# Upgrade main packages (equivalent to C(pkgin upgrade))
- pkgin : upgrade = yes
# Upgrade all packages (equivalent to C(pkgin full-upgrade))
- pkgin : full_upgrade = yes
# Force-upgrade all packages (equivalent to C(pkgin -F full-upgrade))
- pkgin : full_upgrade = yes force = yes
# clean packages cache (equivalent to C(pkgin clean))
- pkgin : clean = yes
'''
'''
import re
import re
def query_package ( module , pkgin_path , name ) :
def query_package ( module , name) :
""" Search for the package by name.
""" Search for the package by name.
Possible return values :
Possible return values :
@ -89,7 +131,7 @@ def query_package(module, pkgin_path, name):
"""
"""
# test whether '-p' (parsable) flag is supported.
# test whether '-p' (parsable) flag is supported.
rc , out , err = module . run_command ( " %s -p -v " % pkgin_path )
rc , out , err = module . run_command ( " %s -p -v " % PKGIN_PATH )
if rc == 0 :
if rc == 0 :
pflag = ' -p '
pflag = ' -p '
@ -100,7 +142,7 @@ def query_package(module, pkgin_path, name):
# Use "pkgin search" to find the package. The regular expression will
# Use "pkgin search" to find the package. The regular expression will
# only match on the complete name.
# only match on the complete name.
rc , out , err = module . run_command ( " %s %s search \" ^ %s $ \" " % ( pkgin_path , pflag , name ) )
rc , out , err = module . run_command ( " %s %s search \" ^ %s $ \" " % ( PKGIN_PATH , pflag , name ) )
# rc will not be 0 unless the search was a success
# rc will not be 0 unless the search was a success
if rc == 0 :
if rc == 0 :
@ -162,37 +204,43 @@ def format_action_message(module, action, count):
return message + " s "
return message + " s "
def format_pkgin_command ( module , pkgin_path, command, package = None ) :
def format_pkgin_command ( module , command, package = None ) :
# Not all commands take a package argument, so cover this up by passing
# Not all commands take a package argument, so cover this up by passing
# an empty string. Some commands (e.g. 'update') will ignore extra
# an empty string. Some commands (e.g. 'update') will ignore extra
# arguments, however this behaviour cannot be relied on for others.
# arguments, however this behaviour cannot be relied on for others.
if package is None :
if package is None :
package = " "
package = " "
vars = { " pkgin " : pkgin_path ,
if module . params [ " force " ] :
force = " -F "
else :
force = " "
vars = { " pkgin " : PKGIN_PATH ,
" command " : command ,
" command " : command ,
" package " : package }
" package " : package ,
" force " : force }
if module . check_mode :
if module . check_mode :
return " %(pkgin)s -n %(command)s %(package)s " % vars
return " %(pkgin)s -n %(command)s %(package)s " % vars
else :
else :
return " %(pkgin)s -y %( command)s %(package)s " % vars
return " %(pkgin)s -y %( force)s %( command)s %(package)s " % vars
def remove_packages ( module , p kgin_path, p ackages) :
def remove_packages ( module , p ackages) :
remove_c = 0
remove_c = 0
# Using a for loop incase of error, we can report the package that failed
# Using a for loop incase of error, we can report the package that failed
for package in packages :
for package in packages :
# Query the package first, to see if we even need to remove
# Query the package first, to see if we even need to remove
if not query_package ( module , p kgin_path, p ackage) :
if not query_package ( module , p ackage) :
continue
continue
rc , out , err = module . run_command (
rc , out , err = module . run_command (
format_pkgin_command ( module , pkgin_path , " remove " , package ) )
format_pkgin_command ( module , " remove " , package ) )
if not module . check_mode and query_package ( module , p kgin_path, p ackage) :
if not module . check_mode and query_package ( module , p ackage) :
module . fail_json ( msg = " failed to remove %s : %s " % ( package , out ) )
module . fail_json ( msg = " failed to remove %s : %s " % ( package , out ) )
remove_c + = 1
remove_c + = 1
@ -203,18 +251,18 @@ def remove_packages(module, pkgin_path, packages):
module . exit_json ( changed = False , msg = " package(s) already absent " )
module . exit_json ( changed = False , msg = " package(s) already absent " )
def install_packages ( module , p kgin_path, p ackages) :
def install_packages ( module , p ackages) :
install_c = 0
install_c = 0
for package in packages :
for package in packages :
if query_package ( module , p kgin_path, p ackage) :
if query_package ( module , p ackage) :
continue
continue
rc , out , err = module . run_command (
rc , out , err = module . run_command (
format_pkgin_command ( module , pkgin_path , " install " , package ) )
format_pkgin_command ( module , " install " , package ) )
if not module . check_mode and not query_package ( module , p kgin_path, p ackage) :
if not module . check_mode and not query_package ( module , p ackage) :
module . fail_json ( msg = " failed to install %s : %s " % ( package , out ) )
module . fail_json ( msg = " failed to install %s : %s " % ( package , out ) )
install_c + = 1
install_c + = 1
@ -224,41 +272,97 @@ def install_packages(module, pkgin_path, packages):
module . exit_json ( changed = False , msg = " package(s) already present " )
module . exit_json ( changed = False , msg = " package(s) already present " )
def update_package_db ( module , pkgin_path ):
def update_package_db ( module ):
rc , out , err = module . run_command (
rc , out , err = module . run_command (
format_pkgin_command ( module , pkgin_path , " update " ) )
format_pkgin_command ( module , " update " ) )
if rc == 0 :
if rc == 0 :
return True
if re . search ( ' database for.*is up-to-date \n $ ' , out ) :
return False , " datebase is up-to-date "
else :
return True , " updated repository database "
else :
else :
module . fail_json ( msg = " could not update package db " )
module . fail_json ( msg = " could not update package db " )
def do_upgrade_packages ( module , full = False ) :
if full :
cmd = " full-upgrade "
else :
cmd = " upgrade "
rc , out , err = module . run_command (
format_pkgin_command ( module , cmd ) )
if rc == 0 :
if re . search ( ' ^nothing to do. \n $ ' , out ) :
module . exit_json ( changed = False , msg = " nothing left to upgrade " )
else :
module . fail_json ( msg = " could not %s packages " % cmd )
def upgrade_packages ( module ) :
do_upgrade_packages ( module )
def full_upgrade_packages ( module ) :
do_upgrade_packages ( module , True )
def clean_cache ( module ) :
rc , out , err = module . run_command (
format_pkgin_command ( module , " clean " ) )
if rc == 0 :
# There's no indication if 'clean' actually removed anything,
# so assume it did.
module . exit_json ( changed = True , msg = " cleaned caches " )
else :
module . fail_json ( msg = " could not clean package cache " )
def main ( ) :
def main ( ) :
module = AnsibleModule (
module = AnsibleModule (
argument_spec = dict (
argument_spec = dict (
state = dict ( default = " present " , choices = [ " present " , " absent " ] ) ,
state = dict ( default = " present " , choices = [ " present " , " absent " ] ) ,
name = dict ( aliases = [ " pkg " ] , type = ' list ' ) ,
name = dict ( aliases = [ " pkg " ] , type = ' list ' ) ,
update_cache = dict ( default = ' no ' , type = ' bool ' ) ) ,
update_cache = dict ( default = ' no ' , type = ' bool ' ) ,
required_one_of = [ [ ' name ' , ' update_cache ' ] ] ,
upgrade = dict ( default = ' no ' , type = ' bool ' ) ,
full_upgrade = dict ( default = ' no ' , type = ' bool ' ) ,
clean = dict ( default = ' no ' , type = ' bool ' ) ,
force = dict ( default = ' no ' , type = ' bool ' ) ) ,
required_one_of = [ [ ' name ' , ' update_cache ' , ' upgrade ' , ' full_upgrade ' , ' clean ' ] ] ,
supports_check_mode = True )
supports_check_mode = True )
pkgin_path = module . get_bin_path ( ' pkgin ' , True , [ ' /opt/local/bin ' ] )
global PKGIN_PATH
PKGIN_PATH = module . get_bin_path ( ' pkgin ' , True , [ ' /opt/local/bin ' ] )
p = module . params
module. run_command_environ_update = dict ( LANG = ' C ' , LC_ALL = ' C ' , LC_MESSAGES = ' C ' , LC_CTYPE = ' C ' )
pkgs = p [ " name " ]
p = module . params
if p [ " update_cache " ] :
if p [ " update_cache " ] :
update_package_db ( module , pkgin_path )
c , msg = update_package_db ( module )
if not ( p [ ' name ' ] or p [ " upgrade " ] or p [ " full_upgrade " ] ) :
module . exit_json ( changed = c , msg = msg )
if p [ " upgrade " ] :
upgrade_packages ( module )
if not p [ ' name ' ] :
if not p [ ' name ' ] :
module . exit_json ( changed = True , msg = ' updated repository database ' )
module . exit_json ( changed = True , msg = ' upgraded packages ' )
if p [ " full_upgrade " ] :
full_upgrade_packages ( module )
if not p [ ' name ' ] :
module . exit_json ( changed = True , msg = ' upgraded all packages ' )
if p [ " clean " ] :
clean_cache ( module )
if not p [ ' name ' ] :
module . exit_json ( changed = True , msg = ' cleaned caches ' )
pkgs = p [ " name " ]
if p [ " state " ] == " present " :
if p [ " state " ] == " present " :
install_packages ( module , pkgin_path , pkgs )
install_packages ( module , pkg s)
elif p [ " state " ] == " absent " :
elif p [ " state " ] == " absent " :
remove_packages ( module , pkgin_path , pkgs )
remove_packages ( module , pkg s)
# import module snippets
# import module snippets
from ansible . module_utils . basic import *
from ansible . module_utils . basic import *