#!/usr/bin/python # -*- coding: utf-8 -*- """ Ansible module to manage symbolic link alternatives. (c) 2014, Gabe Mulley 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 . """ DOCUMENTATION = ''' --- module: alternatives short_description: Manages symbolic links description: - Manages symbolic links using the 'update-alternatives' tool provided on debian-like systems. - Useful when multiple programs are installed but provide similar functionality (e.g. different editors). version_added: "1.5" options: name: description: - The generic name of the link. required: true path: description: - The path to the real executable that the link should point to. required: true link: description: - The path to the symbolic link that should point to the real executable. required: false requirements: [ update-alternatives ] ''' EXAMPLES = ''' - name: correct java version selected alternatives: name=java path=/usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java - name: alternatives link created alternatives: name=hadoop-conf link=/etc/hadoop/conf path=/etc/hadoop/conf.ansible ''' UPDATE_ALTERNATIVES = '/usr/sbin/update-alternatives' DEFAULT_LINK_PRIORITY = 50 def main(): module = AnsibleModule( argument_spec = dict( name = dict(required=True), path = dict(required=True), link = dict(required=False), ) ) params = module.params name = params['name'] path = params['path'] link = params['link'] current_path = None all_alternatives = [] (rc, query_output, query_error) = module.run_command( [UPDATE_ALTERNATIVES, '--query', name] ) # Gather the current setting and all alternatives from the query output. # Query output should look something like this: # Name: java # Link: /usr/bin/java # Slaves: # java.1.gz /usr/share/man/man1/java.1.gz # Status: manual # Best: /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java # Value: /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java # Alternative: /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java # Priority: 1061 # Slaves: # java.1.gz /usr/lib/jvm/java-6-openjdk-amd64/jre/man/man1/java.1.gz # Alternative: /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java # Priority: 1071 # Slaves: # java.1.gz /usr/lib/jvm/java-7-openjdk-amd64/jre/man/man1/java.1.gz if rc == 0: for line in query_output.splitlines(): split_line = line.split(':') if len(split_line) == 2: key = split_line[0] value = split_line[1].strip() if key == 'Value': current_path = value elif key == 'Alternative': all_alternatives.append(value) if current_path != path: try: # install the requested path if necessary if path not in all_alternatives: module.run_command( [UPDATE_ALTERNATIVES, '--install', link, name, path, str(DEFAULT_LINK_PRIORITY)], check_rc=True ) # select the requested path module.run_command( [UPDATE_ALTERNATIVES, '--set', name, path], check_rc=True ) module.exit_json(changed=True) except subprocess.CalledProcessError as cpe: module.fail_json(msg=str(dir(cpe))) else: module.exit_json(changed=False) # import module snippets from ansible.module_utils.basic import * main()