@ -32,11 +32,25 @@ description:
author : " Kevin Brebanov (@kbrebanov) "
author : " Kevin Brebanov (@kbrebanov) "
version_added : " 2.0 "
version_added : " 2.0 "
options :
options :
available :
description :
- During upgrade , reset versioned world dependencies and change logic to prefer replacing or downgrading packages ( instead of holding them )
if the currently installed package is no longer available from any repository .
required : false
default : no
choices : [ " yes " , " no " ]
version_added : " 2.4 "
name :
name :
description :
description :
- A package name , like C ( foo ) , or mutliple packages , like C ( foo , bar ) .
- A package name , like C ( foo ) , or mutliple packages , like C ( foo , bar ) .
required : false
required : false
default : null
default : null
repository :
description :
- A package repository or multiple repositories
required : false
default : null
version_added : " 2.4 "
state :
state :
description :
description :
- Indicates the desired package ( s ) state .
- Indicates the desired package ( s ) state .
@ -109,23 +123,54 @@ EXAMPLES = '''
- apk :
- apk :
upgrade : yes
upgrade : yes
# Upgrade / replace / downgrade / uninstall all installed packages to the latest versions available
- apk :
available : yes
upgrade : yes
# Update repositories as a separate step
# Update repositories as a separate step
- apk :
- apk :
update_cache : yes
update_cache : yes
# Install package from a specific repository
- apk :
name : foo
state : latest
update_cache : yes
repository : http : / / dl - 3. alpinelinux . org / alpine / edge / main
'''
'''
RETURN = '''
packages :
description : a list of packages that have been changed
returned : when packages have changed
type : list
sample : [ ' package ' , ' other-package ' ]
'''
import re
import re
# Import module snippets.
# Import module snippets.
from ansible . module_utils . basic import AnsibleModule
from ansible . module_utils . basic import AnsibleModule
def update_package_db ( module ) :
def parse_for_packages ( stdout ) :
packages = [ ]
data = stdout . split ( ' \n ' )
regex = re . compile ( ' ^ \ ( \ d+/ \ d+ \ ) \ s+ \ S+ \ s+( \ S+) ' )
for l in data :
p = regex . search ( l )
if p :
packages . append ( p . group ( 1 ) )
return packages
def update_package_db ( module , exit ) :
cmd = " %s update " % ( APK_PATH )
cmd = " %s update " % ( APK_PATH )
rc , stdout , stderr = module . run_command ( cmd , check_rc = False )
rc , stdout , stderr = module . run_command ( cmd , check_rc = False )
if rc == 0 :
if rc != 0 :
return True
module . fail_json ( msg = " could not update package db " , stdout = stdout , stderr = stderr )
elif exit :
module . exit_json ( changed = True , msg = ' updated repository indexes ' , stdout = stdout , stderr = stderr )
else :
else :
module . fail_json ( msg = " could not update package db " )
return True
def query_package ( module , name ) :
def query_package ( module , name ) :
cmd = " %s -v info --installed %s " % ( APK_PATH , name )
cmd = " %s -v info --installed %s " % ( APK_PATH , name )
@ -161,17 +206,20 @@ def get_dependencies(module, name):
else :
else :
return [ ]
return [ ]
def upgrade_packages ( module ):
def upgrade_packages ( module , available ):
if module . check_mode :
if module . check_mode :
cmd = " %s upgrade --simulate " % ( APK_PATH )
cmd = " %s upgrade --simulate " % ( APK_PATH )
else :
else :
cmd = " %s upgrade " % ( APK_PATH )
cmd = " %s upgrade " % ( APK_PATH )
if available :
cmd = " %s --available " % cmd
rc , stdout , stderr = module . run_command ( cmd , check_rc = False )
rc , stdout , stderr = module . run_command ( cmd , check_rc = False )
packagelist = parse_for_packages ( stdout )
if rc != 0 :
if rc != 0 :
module . fail_json ( msg = " failed to upgrade packages " )
module . fail_json ( msg = " failed to upgrade packages " , stdout = stdout , stderr = stderr , packages = packagelist )
if re . search ( r ' ^OK ' , stdout ) :
if re . search ( r ' ^OK ' , stdout ) :
module . exit_json ( changed = False , msg = " packages already upgraded " )
module . exit_json ( changed = False , msg = " packages already upgraded " , stdout = stdout , stderr = stderr , packages = packagelist )
module . exit_json ( changed = True , msg = " upgraded packages " )
module . exit_json ( changed = True , msg = " upgraded packages " , stdout = stdout , stderr = stderr , packages = packagelist )
def install_packages ( module , names , state ) :
def install_packages ( module , names , state ) :
upgrade = False
upgrade = False
@ -206,9 +254,10 @@ def install_packages(module, names, state):
else :
else :
cmd = " %s add %s " % ( APK_PATH , packages )
cmd = " %s add %s " % ( APK_PATH , packages )
rc , stdout , stderr = module . run_command ( cmd , check_rc = False )
rc , stdout , stderr = module . run_command ( cmd , check_rc = False )
packagelist = parse_for_packages ( stdout )
if rc != 0 :
if rc != 0 :
module . fail_json ( msg = " failed to install %s " % ( packages ) )
module . fail_json ( msg = " failed to install %s " % ( packages ) , stdout = stdout , stderr = stderr , packages = packagelist )
module . exit_json ( changed = True , msg = " installed %s package(s) " % ( packages ) )
module . exit_json ( changed = True , msg = " installed %s package(s) " % ( packages ) , stdout = stdout , stderr = stderr , packages = packagelist )
def remove_packages ( module , names ) :
def remove_packages ( module , names ) :
installed = [ ]
installed = [ ]
@ -223,9 +272,10 @@ def remove_packages(module, names):
else :
else :
cmd = " %s del --purge %s " % ( APK_PATH , names )
cmd = " %s del --purge %s " % ( APK_PATH , names )
rc , stdout , stderr = module . run_command ( cmd , check_rc = False )
rc , stdout , stderr = module . run_command ( cmd , check_rc = False )
packagelist = parse_for_packages ( stdout )
if rc != 0 :
if rc != 0 :
module . fail_json ( msg = " failed to remove %s package(s) " % ( names ) )
module . fail_json ( msg = " failed to remove %s package(s) " % ( names ) , stdout = stdout , stderr = stderr , packages = packagelist )
module . exit_json ( changed = True , msg = " removed %s package(s) " % ( names ) )
module . exit_json ( changed = True , msg = " removed %s package(s) " % ( names ) , stdout = stdout , stderr = stderr , packages = packagelist )
# ==========================================
# ==========================================
# Main control flow.
# Main control flow.
@ -235,8 +285,10 @@ def main():
argument_spec = dict (
argument_spec = dict (
state = dict ( default = ' present ' , choices = [ ' present ' , ' installed ' , ' absent ' , ' removed ' , ' latest ' ] ) ,
state = dict ( default = ' present ' , choices = [ ' present ' , ' installed ' , ' absent ' , ' removed ' , ' latest ' ] ) ,
name = dict ( type = ' list ' ) ,
name = dict ( type = ' list ' ) ,
repository = dict ( type = ' list ' ) ,
update_cache = dict ( default = ' no ' , type = ' bool ' ) ,
update_cache = dict ( default = ' no ' , type = ' bool ' ) ,
upgrade = dict ( default = ' no ' , type = ' bool ' ) ,
upgrade = dict ( default = ' no ' , type = ' bool ' ) ,
available = dict ( default = ' no ' , type = ' bool ' ) ,
) ,
) ,
required_one_of = [ [ ' name ' , ' update_cache ' , ' upgrade ' ] ] ,
required_one_of = [ [ ' name ' , ' update_cache ' , ' upgrade ' ] ] ,
mutually_exclusive = [ [ ' name ' , ' upgrade ' ] ] ,
mutually_exclusive = [ [ ' name ' , ' upgrade ' ] ] ,
@ -251,6 +303,11 @@ def main():
p = module . params
p = module . params
# add repositories to the APK_PATH
if p [ ' repository ' ] :
for r in p [ ' repository ' ] :
APK_PATH = " %s --repository %s " % ( APK_PATH , r )
# normalize the state parameter
# normalize the state parameter
if p [ ' state ' ] in [ ' present ' , ' installed ' ] :
if p [ ' state ' ] in [ ' present ' , ' installed ' ] :
p [ ' state ' ] = ' present '
p [ ' state ' ] = ' present '
@ -258,12 +315,10 @@ def main():
p [ ' state ' ] = ' absent '
p [ ' state ' ] = ' absent '
if p [ ' update_cache ' ] :
if p [ ' update_cache ' ] :
update_package_db ( module )
update_package_db ( module , not p [ ' name ' ] and not p [ ' upgrade ' ] )
if not p [ ' name ' ] :
module . exit_json ( changed = True , msg = ' updated repository indexes ' )
if p [ ' upgrade ' ] :
if p [ ' upgrade ' ] :
upgrade_packages ( module )
upgrade_packages ( module , p [ ' available ' ] )
if p [ ' state ' ] in [ ' present ' , ' latest ' ] :
if p [ ' state ' ] in [ ' present ' , ' latest ' ] :
install_packages ( module , p [ ' name ' ] , p [ ' state ' ] )
install_packages ( module , p [ ' name ' ] , p [ ' state ' ] )