mirror of https://github.com/ansible/ansible.git
Introduce module layman
parent
ff8eb5f454
commit
88b7dc344c
@ -0,0 +1,236 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2014, Jakub Jirutka <jakub@jirutka.cz>
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
import shutil
|
||||
from os import path
|
||||
from urllib2 import Request, urlopen, URLError
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: layman
|
||||
author: Jakub Jirutka <jakub@jirutka.cz>
|
||||
version_added: "1.4.5"
|
||||
short_description: Manage Gentoo overlays
|
||||
description:
|
||||
- Uses Layman to manage an additional repositories for the Portage package manager on Gentoo Linux.
|
||||
Please note that Layman must be installed on a managed node prior using this module.
|
||||
options:
|
||||
name:
|
||||
description:
|
||||
- The overlay id to install, synchronize, or uninstall.
|
||||
Use 'ALL' to sync all of the installed overlays (can be used only when C(state=updated)).
|
||||
required: true
|
||||
list_url:
|
||||
description:
|
||||
- An URL of the alternative overlays list that defines the overlay to install.
|
||||
This list will be fetched and saved under C(${overlay_defs})/${name}.xml), where
|
||||
C(overlay_defs) is readed from the Layman's configuration.
|
||||
required: false
|
||||
state:
|
||||
description:
|
||||
- Whether to install (C(present)), sync (C(updated)), or uninstall (C(absent)) the overlay.
|
||||
required: false
|
||||
default: present
|
||||
choices: [present, absent, updated]
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Install the overlay 'mozilla' which is on the central overlays list.
|
||||
- layman: name=mozilla
|
||||
|
||||
# Install the overlay 'cvut' from the specified alternative list.
|
||||
- layman: name=cvut list_url=http://raw.github.com/cvut/gentoo-overlay/master/overlay.xml
|
||||
|
||||
# Update (sync) the overlay 'cvut', or install if not installed yet.
|
||||
- layman: name=cvut list_url=http://raw.github.com/cvut/gentoo-overlay/master/overlay.xml state=updated
|
||||
|
||||
# Update (sync) all of the installed overlays.
|
||||
- layman: name=ALL state=updated
|
||||
|
||||
# Uninstall the overlay 'cvut'.
|
||||
- layman: name=cvut state=absent
|
||||
'''
|
||||
|
||||
USERAGENT = 'ansible-httpget'
|
||||
|
||||
try:
|
||||
from layman.api import LaymanAPI
|
||||
from layman.config import BareConfig
|
||||
HAS_LAYMAN_API = True
|
||||
except ImportError:
|
||||
HAS_LAYMAN_API = False
|
||||
|
||||
|
||||
class ModuleError(Exception): pass
|
||||
|
||||
|
||||
def init_layman(config=None):
|
||||
'''Returns the initialized ``LaymanAPI``.
|
||||
|
||||
:param config: the layman's configuration to use (optional)
|
||||
'''
|
||||
if config is None: config = BareConfig(read_configfile=True, quietness=1)
|
||||
return LaymanAPI(config)
|
||||
|
||||
|
||||
def download_url(url, dest):
|
||||
'''
|
||||
:param url: the URL to download
|
||||
:param dest: the absolute path of where to save the downloaded content to;
|
||||
it must be writable and not a directory
|
||||
|
||||
:raises ModuleError
|
||||
'''
|
||||
request = Request(url)
|
||||
request.add_header('User-agent', USERAGENT)
|
||||
|
||||
try:
|
||||
response = urlopen(request)
|
||||
except URLError, e:
|
||||
raise ModuleError("Failed to get %s: %s" % (url, str(e)))
|
||||
|
||||
try:
|
||||
with open(dest, 'w') as f:
|
||||
shutil.copyfileobj(response, f)
|
||||
except IOError, e:
|
||||
raise ModuleError("Failed to write: %s" % str(e))
|
||||
|
||||
|
||||
def install_overlay(name, list_url=None):
|
||||
'''Installs the overlay repository. If not on the central overlays list,
|
||||
then :list_url of an alternative list must be provided. The list will be
|
||||
fetched and saved under ``%(overlay_defs)/%(name.xml)`` (location of the
|
||||
``overlay_defs`` is read from the Layman's configuration).
|
||||
|
||||
:param name: the overlay id
|
||||
:param list_url: the URL of the remote repositories list to look for the overlay
|
||||
definition (optional, default: None)
|
||||
|
||||
:returns: True if the overlay was installed, or False if already exists
|
||||
(i.e. nothing has changed)
|
||||
:raises ModuleError
|
||||
'''
|
||||
# read Layman configuration
|
||||
layman_conf = BareConfig(read_configfile=True)
|
||||
layman = init_layman(layman_conf)
|
||||
|
||||
if layman.is_installed(name):
|
||||
return False
|
||||
|
||||
if not layman.is_repo(name):
|
||||
if not list_url: raise ModuleError("Overlay '%s' is not on the list of known " \
|
||||
"overlays and URL of the remote list was not provided." % name)
|
||||
|
||||
overlay_defs = layman_conf.get_option('overlay_defs')
|
||||
dest = path.join(overlay_defs, name + '.xml')
|
||||
|
||||
download_url(list_url, dest)
|
||||
|
||||
# reload config
|
||||
layman = init_layman()
|
||||
|
||||
if not layman.add_repos(name): raise ModuleError(layman.get_errors())
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def uninstall_overlay(name):
|
||||
'''Uninstalls the given overlay repository from the system.
|
||||
|
||||
:param name: the overlay id to uninstall
|
||||
|
||||
:returns: True if the overlay was uninstalled, or False if doesn't exist
|
||||
(i.e. nothing has changed)
|
||||
:raises ModuleError
|
||||
'''
|
||||
layman = init_layman()
|
||||
|
||||
if not layman.is_installed(name):
|
||||
return False
|
||||
|
||||
layman.delete_repos(name)
|
||||
if layman.get_errors(): raise ModuleError(layman.get_errors())
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def sync_overlay(name):
|
||||
'''Synchronizes the specified overlay repository.
|
||||
|
||||
:param name: the overlay repository id to sync
|
||||
:raises ModuleError
|
||||
'''
|
||||
layman = init_layman()
|
||||
|
||||
if not layman.sync(name):
|
||||
messages = [ str(item[1]) for item in layman.sync_results[2] ]
|
||||
raise ModuleError(messages)
|
||||
|
||||
|
||||
def sync_overlays():
|
||||
'''Synchronize all of the installed overlays.
|
||||
|
||||
:raises ModuleError
|
||||
'''
|
||||
layman = init_layman()
|
||||
|
||||
for name in layman.get_installed():
|
||||
sync_overlay(name)
|
||||
|
||||
|
||||
def main():
|
||||
# define module
|
||||
module = AnsibleModule(
|
||||
argument_spec = {
|
||||
'name': { 'required': True },
|
||||
'list_url': { 'aliases': ['url'] },
|
||||
'state': { 'default': "present", 'choices': ['present', 'absent', 'updated'] },
|
||||
}
|
||||
)
|
||||
|
||||
if not HAS_LAYMAN_API:
|
||||
module.fail_json(msg='Layman is not installed')
|
||||
|
||||
state, name, url = (module.params[key] for key in ['state', 'name', 'list_url'])
|
||||
|
||||
changed = False
|
||||
try:
|
||||
if state == 'present':
|
||||
changed = install_overlay(name, url)
|
||||
|
||||
elif state == 'updated':
|
||||
if name == 'ALL':
|
||||
sync_overlays()
|
||||
elif install_overlay(name, url):
|
||||
changed = True
|
||||
else:
|
||||
sync_overlay(name)
|
||||
else:
|
||||
changed = uninstall_overlay(name)
|
||||
|
||||
except ModuleError, e:
|
||||
module.fail_json(msg=e.message)
|
||||
else:
|
||||
module.exit_json(changed=changed, name=name)
|
||||
|
||||
|
||||
# import module snippets
|
||||
from ansible.module_utils.basic import *
|
||||
main()
|
Loading…
Reference in New Issue