Skip to content
Snippets Groups Projects
Commit 5dad5fb4 authored by Vladimír Štill's avatar Vladimír Štill
Browse files

ansible: A new GHC-installer role

parent f82c78fe
No related branches found
No related tags found
No related merge requests found
#!/usr/bin/python
# based on
# https://github.com/ansible-collections/community.general/blob/main/plugins/modules/system/alternatives.py
import os
import re
import subprocess
from ansible.module_utils.basic import AnsibleModule
def main():
fields = {
"name": {"required": True, "type": "str"},
"path": {"required": True, "type": "path"},
"link": {"type": "path"},
"priority": {"type": "int", "default": 50},
"state": {"default": "set", "choices": ["present", "set", "auto"], "type": "str"},
"slaves": {"type": "list", "default": []}
}
module = AnsibleModule(argument_spec=fields, supports_check_mode=True)
params = module.params
name = params['name']
path = params['path']
link = params['link']
priority = params['priority']
state = params["state"]
slaves = params['slaves']
UPDATE_ALTERNATIVES = module.get_bin_path('update-alternatives', True)
current_path = None
all_alternatives = []
# Run `update-alternatives --display <name>` to find existing alternatives
(rc, display_output, dummy) = module.run_command(
['env', 'LC_ALL=C', UPDATE_ALTERNATIVES, '--display', name]
)
if rc == 0:
# Alternatives already exist for this link group
# Parse the output to determine the current path of the symlink and
# available alternatives
current_path_regex = re.compile(r'^\s*link currently points to (.*)$',
re.MULTILINE)
alternative_regex = re.compile(r'^(\/.*)\s-\s(?:family\s\S+\s)?priority', re.MULTILINE)
match = current_path_regex.search(display_output)
if match:
current_path = match.group(1)
all_alternatives = alternative_regex.findall(display_output)
if not link:
# Read the current symlink target from `update-alternatives --query`
# in case we need to install the new alternative before setting it.
#
# This is only compatible on Debian-based systems, as the other
# alternatives don't have --query available
rc, query_output, dummy = module.run_command(
['env', 'LC_ALL=C', UPDATE_ALTERNATIVES, '--query', name]
)
if rc == 0:
for line in query_output.splitlines():
if line.startswith('Link:'):
link = line.split()[1]
break
if current_path != path or len(slaves): # TODO: properly check changed status in presence of slaves
if module.check_mode:
module.exit_json(changed=True, current_path=current_path, slaves=slaves)
try:
# install the requested path if necessary
if path not in all_alternatives or len(slaves):
if not os.path.exists(path):
module.fail_json(msg="Specified path %s does not exist" % path)
if not link:
module.fail_json(msg="Needed to install the alternative, but unable to do so as we are missing the link")
cmd_slaves = []
SLAVE_KEYS = ["link", "name", "path"]
for slave in slaves:
for key in SLAVE_KEYS:
if key not in slave:
module.fail_json(msg="Key %s missing from slave list, required keys are: %s"
% (key, ", ".join(SLAVE_KEYS)))
cmd_slaves.extend(["--slave", slave["link"], slave["name"], slave["path"]])
module.run_command(
[UPDATE_ALTERNATIVES, '--install', link, name, path, str(priority)] + cmd_slaves,
check_rc=True
)
if state == "set":
# select the requested path
module.run_command(
[UPDATE_ALTERNATIVES, '--set', name, path],
check_rc=True
)
elif state == "auto":
# set the path to auto mode
module.run_command(
[UPDATE_ALTERNATIVES, '--auto', name],
check_rc=True
)
module.exit_json(changed=True, slaves=slaves)
except subprocess.CalledProcessError as cpe:
module.fail_json(msg=str(dir(cpe)))
else:
module.exit_json(changed=False, slaves=slaves)
if __name__ == '__main__':
main()
---
- name: Does GHC exist?
stat:
path: "/opt/ghc/{{version.ghc}}/bin/ghci-{{version.ghc}}"
register: ghc
- name: Does Cabal exist?
stat:
path: "/opt/cabal/{{version.cabal}}/bin/cabal"
when: version.cabal is defined
register: cabal
- name: GHC Dir
file:
state: directory
path: "/opt/ghc/{{version.ghc}}"
- name: Cabal Dir
file:
state: directory
path: "/opt/cabal/{{version.cabal}}/bin"
when: version.cabal is defined
- name: Build GHC & cabal if it does not exist
block:
- name: Build GHC under the builder user
block:
- name: "Download GHC"
unarchive:
src: 'https://downloads.haskell.org/~ghc/{{version.ghc}}/ghc-{{version.ghc}}-x86_64-deb9-linux.tar.xz'
dest: "/home/builder/ghc/"
remote_src: True
- name: Build GHC
shell:
chdir: '/home/builder/ghc/ghc-{{version.ghc}}'
cmd: "./configure --prefix=/opt/ghc/{{version.ghc}}/"
become_user: builder
become: true
- name: Install GHC
shell:
chdir: '/home/builder/ghc/ghc-{{version.ghc}}'
cmd: make install -j8
when: not ghc.stat.exists
- name: Add cabal
unarchive:
src: "https://downloads.haskell.org/~cabal/cabal-install-{{version.cabal}}/cabal-install-{{version.cabal}}-x86_64-linux-deb10.tar.xz"
dest: "/opt/cabal/{{version.cabal}}/bin/"
remote_src: true
when: version.cabal is defined and not cabal.stat.exists
- name: Setup opt-GHC alteranative
deb_alternatives:
name: "opt-ghc{{item}}"
link: "/opt/ghc/bin/ghc{{item}}"
path: "/opt/ghc/{{version.ghc}}/bin/ghc"
priority: "{{version_idx + 100}}"
state: present
slaves:
- link: "/opt/ghc/bin/ghci{{item}}"
name: "opt-ghci{{item}}"
path: "/opt/ghc/{{version.ghc}}/bin/ghci"
- link: "/opt/ghc/bin/runghc{{item}}"
name: "opt-runghc{{item}}"
path: "/opt/ghc/{{version.ghc}}/bin/runghc"
- link: "/opt/ghc/bin/ghc-pkg{{item}}"
name: "opt-ghc-pkg{{item}}"
path: "/opt/ghc/{{version.ghc}}/bin/ghc-pkg"
- link: "/opt/ghc/bin/haddock{{item}}"
name: "opt-haddock{{item}}"
path: "/opt/ghc/{{version.ghc}}/bin/haddock"
loop:
- ""
- "-{{version.ghc}}"
- name: Setup GHC alternative
deb_alternatives:
name: "ghc{{item}}"
link: "/usr/bin/ghc{{item}}"
path: "/etc/alternatives/opt-ghc{{item}}"
priority: 100
state: present
slaves:
- link: "/usr/bin/ghci{{item}}"
name: "ghci{{item}}"
path: "/etc/alternatives/opt-ghci{{item}}"
- link: "/usr/bin/runghc{{item}}"
name: "runghc{{item}}"
path: "/etc/alternatives/opt-runghc{{item}}"
- link: "/usr/bin/ghc-pkg{{item}}"
name: "ghc-pkg{{item}}"
path: "/etc/alternatives/opt-ghc-pkg{{item}}"
- link: "/usr/bin/haddock{{item}}"
name: "haddock{{item}}"
path: "/etc/alternatives/opt-haddock{{item}}"
loop:
- ""
- "-{{version.ghc}}"
- name: Setup opt-cabal alternative
deb_alternatives:
name: "opt-cabal{{item}}"
link: "/opt/ghc/bin/cabal{{item}}"
path: "/opt/cabal/{{version.cabal}}/bin/cabal"
priority: "{{version_idx + 100}}"
state: present
loop:
- ""
- "-{{version.cabal}}"
when: version.cabal is defined
- name: Setup cabal alternative
deb_alternatives:
name: "cabal{{item}}"
link: "/usr/bin/cabal{{item}}"
path: "/etc/alternatives/opt-cabal{{item}}"
priority: 100
state: present
loop:
- ""
- "-{{version.cabal}}"
when: version.cabal is defined
---
- name: Builder user
user:
name: builder
create_home: true
shell: /bin/bash
system: true
- name: GHC source dir
file:
state: directory
owner: "builder"
path: "/home/builder/ghc"
- include_tasks: install.yml
loop: "{{versions}}"
loop_control:
loop_var: version
index_var: version_idx
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment