ansible/packaging/gem
Andy Kluger 8f43db3167 Fix for Issue #2470 - gem version string processing
This fix assumes that no sane gem version has spaces in it, so when one like that is encountered, it will get truncated at the first space.
2013-10-02 17:55:30 -04:00

215 lines
6.6 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2013, Johan Wiren <johan.wiren.se@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
DOCUMENTATION = '''
---
module: gem
short_description: Manage Ruby gems
description:
- Manage installation and uninstallation of Ruby gems.
version_added: "1.1"
options:
name:
description:
- The name of the gem to be managed.
required: true
state:
description:
- The desired state of the gem. C(latest) ensures that the latest version is installed.
required: true
choices: [present, absent, latest]
gem_source:
description:
- The path to a local gem used as installation source.
required: false
include_dependencies:
description:
- Wheter to include dependencies or not.
required: false
choices: [ "yes", "no" ]
default: "yes"
repository:
description:
- The repository from which the gem will be installed
required: false
aliases: [source]
user_install:
description:
- Install gem in user's local gems cache or for all users
required: false
default: "yes"
version_added: "1.3"
version:
description:
- Version of the gem to be installed/removed.
required: false
author: Johan Wiren
'''
EXAMPLES = '''
# Installs version 1.0 of vagrant.
- gem: name=vagrant version=1.0 state=present
# Installs latest available version of rake.
- gem: name=rake state=latest
# Installs rake version 1.0 from a local gem on disk.
- gem: name=rake gem_source=/path/to/gems/rake-1.0.gem state=present
'''
import re
def get_rubygems_version(module):
cmd = [module.get_bin_path('gem', True), '--version']
(rc, out, err) = module.run_command(cmd, check_rc=True)
match = re.match(r'^(\d+)\.(\d+)\.(\d+)', out)
if not match:
return None
return tuple(int(x) for x in match.groups())
def get_installed_versions(module, remote=False):
cmd = [ module.get_bin_path('gem', True) ]
cmd.append('query')
if remote:
cmd.append('--remote')
if module.params['repository']:
cmd.extend([ '--source', module.params['repository'] ])
cmd.append('-n')
cmd.append('^%s$' % module.params['name'])
(rc, out, err) = module.run_command(cmd, check_rc=True)
installed_versions = []
for line in out.splitlines():
match = re.match(r"\S+\s+\((.+)\)", line)
if match:
versions = match.group(1)
for version in versions.split(', '):
installed_versions.append(version.split()[0])
return installed_versions
def exists(module):
if module.params['state'] == 'latest':
remoteversions = get_installed_versions(module, remote=True)
if remoteversions:
module.params['version'] = remoteversions[0]
installed_versions = get_installed_versions(module)
if module.params['version']:
if module.params['version'] in installed_versions:
return True
else:
if installed_versions:
return True
return False
def uninstall(module):
if module.check_mode:
return
cmd = [ module.get_bin_path('gem', True) ]
cmd.append('uninstall')
if module.params['version']:
cmd.extend([ '--version', module.params['version'] ])
else:
cmd.append('--all')
cmd.append(module.params['name'])
module.run_command(cmd, check_rc=True)
def install(module):
if module.check_mode:
return
ver = get_rubygems_version(module)
if ver:
major = ver[0]
else:
major = None
cmd = [ module.get_bin_path('gem', True) ]
cmd.append('install')
if module.params['version']:
cmd.extend([ '--version', module.params['version'] ])
if module.params['repository']:
cmd.extend([ '--source', module.params['repository'] ])
if not module.params['include_dependencies']:
cmd.append('--ignore-dependencies')
else:
if major and major < 2:
cmd.append('--include-dependencies')
if module.params['user_install']:
cmd.append('--user-install')
else:
cmd.append('--no-user-install')
cmd.append('--no-rdoc')
cmd.append('--no-ri')
cmd.append(module.params['gem_source'])
module.run_command(cmd, check_rc=True)
def main():
module = AnsibleModule(
argument_spec = dict(
gem_source = dict(required=False, type='str'),
include_dependencies = dict(required=False, default=True, type='bool'),
name = dict(required=True, type='str'),
repository = dict(required=False, aliases=['source'], type='str'),
state = dict(required=False, choices=['present','absent','latest'], type='str'),
user_install = dict(required=False, default=True, type='bool'),
version = dict(required=False, type='str'),
),
supports_check_mode = True,
mutually_exclusive = [ ['gem_source','repository'], ['gem_source','version'] ],
)
if module.params['version'] and module.params['state'] == 'latest':
module.fail_json(msg="Cannot specify version when state=latest")
if module.params['gem_source'] and module.params['state'] == 'latest':
module.fail_json(msg="Cannot maintain state=latest when installing from local source")
if not module.params['gem_source']:
module.params['gem_source'] = module.params['name']
changed = False
if module.params['state'] in [ 'present', 'latest']:
if not exists(module):
install(module)
changed = True
elif module.params['state'] == 'absent':
if exists(module):
uninstall(module)
changed = True
result = {}
result['name'] = module.params['name']
result['state'] = module.params['state']
if module.params['version']:
result['version'] = module.params['version']
result['changed'] = changed
module.exit_json(**result)
# include magic from lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
main()