This uses standard APT syntax, e.g.:
ansible webservers -m apt -a "pkg=nginx=1.1.19-1 state=installed"
... | ... |
@@ -63,16 +63,27 @@ def run_apt(command): |
63 | 63 |
rc = cmd.returncode |
64 | 64 |
return rc, out, err |
65 | 65 |
|
66 |
-def package_status(pkgspec, cache): |
|
66 |
+def package_split(pkgspec): |
|
67 |
+ parts = pkgspec.split('=') |
|
68 |
+ if len(parts) > 1: |
|
69 |
+ return parts[0], parts[1] |
|
70 |
+ else: |
|
71 |
+ return parts[0], None |
|
72 |
+ |
|
73 |
+def package_status(pkgname, version, cache): |
|
67 | 74 |
try: |
68 |
- pkg = cache[pkgspec] |
|
69 |
- except: |
|
70 |
- fail_json(msg="No package matching '%s' is available" % pkgspec) |
|
71 |
- return (pkg.is_installed, pkg.is_upgradable) |
|
75 |
+ pkg = cache[pkgname] |
|
76 |
+ except KeyError: |
|
77 |
+ fail_json(msg="No package matching '%s' is available" % pkgname) |
|
78 |
+ if version: |
|
79 |
+ return pkg.is_installed and pkg.installed.version == version, False |
|
80 |
+ else: |
|
81 |
+ return pkg.is_installed, pkg.is_upgradable |
|
72 | 82 |
|
73 | 83 |
def install(pkgspec, cache, upgrade=False): |
74 |
- (installed, upgradable) = package_status(pkgspec, cache) |
|
75 |
- if (not installed) or (upgrade and upgradable): |
|
84 |
+ name, version = package_split(pkgspec) |
|
85 |
+ installed, upgradable = package_status(name, version, cache) |
|
86 |
+ if not installed or (upgrade and upgradable): |
|
76 | 87 |
cmd = "%s -q -y install '%s'" % (APT, pkgspec) |
77 | 88 |
rc, out, err = run_apt(cmd) |
78 | 89 |
if rc: |
... | ... |
@@ -82,15 +93,16 @@ def install(pkgspec, cache, upgrade=False): |
82 | 82 |
return False |
83 | 83 |
|
84 | 84 |
def remove(pkgspec, cache, purge=False): |
85 |
- (installed, upgradable) = package_status(pkgspec, cache) |
|
85 |
+ name, version = package_split(pkgspec) |
|
86 |
+ installed, upgradable = package_status(name, version, cache) |
|
86 | 87 |
if not installed: |
87 | 88 |
return False |
88 | 89 |
else: |
89 | 90 |
purge = '--purge' if purge else '' |
90 |
- cmd = "%s -q -y %s remove '%s'" % (APT, purge, pkgspec) |
|
91 |
+ cmd = "%s -q -y %s remove '%s'" % (APT, purge, name) |
|
91 | 92 |
rc, out, err = run_apt(cmd) |
92 | 93 |
if rc: |
93 |
- fail_json(msg="'apt-get remove %s' failed: %s" % (pkgspec, err)) |
|
94 |
+ fail_json(msg="'apt-get remove %s' failed: %s" % (name, err)) |
|
94 | 95 |
return True |
95 | 96 |
|
96 | 97 |
|
... | ... |
@@ -109,7 +121,7 @@ if not len(items): |
109 | 109 |
|
110 | 110 |
params = {} |
111 | 111 |
for x in items: |
112 |
- (k, v) = x.split("=") |
|
112 |
+ (k, v) = x.split("=", 1) |
|
113 | 113 |
params[k] = v |
114 | 114 |
|
115 | 115 |
state = params.get('state','installed') |
... | ... |
@@ -137,7 +149,12 @@ if update_cache == 'yes': |
137 | 137 |
if package == None: |
138 | 138 |
exit_json(changed=False) |
139 | 139 |
|
140 |
+if package.count('=') > 1: |
|
141 |
+ fail_json(msg='invalid package spec') |
|
142 |
+ |
|
140 | 143 |
if state == 'latest': |
144 |
+ if '=' in package: |
|
145 |
+ fail_json(msg='version number inconsistent with state=latest') |
|
141 | 146 |
changed = install(package, cache, upgrade=True) |
142 | 147 |
elif state == 'installed': |
143 | 148 |
changed = install(package, cache) |