Skip to content

Commit

Permalink
Allow ansible-init to execute remote playbooks from metadata (#194)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkjpryor authored May 13, 2024
1 parent 97797ce commit 2421ce8
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 20 deletions.
105 changes: 105 additions & 0 deletions ansible/roles/linux-ansible-init/files/ansible-init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/usr/lib/ansible-init/bin/python

import json
import logging
import os
import pathlib
import subprocess

import requests


logging.basicConfig(level = logging.INFO, format = "[%(levelname)s] %(message)s")


logger = logging.getLogger(__name__)


def assemble_list(data, prefix):
"""
Assembles a list of items based on keys in data with the format "<prefix>_<idx>_<key>".
"""
list_items = {}
for key, value in data.items():
if not key.startswith(prefix):
continue
idx, item_key = key.removeprefix(prefix).split("_", maxsplit = 1)
list_items.setdefault(idx, {})[item_key] = value
return [list_items[k] for k in sorted(list_items.keys())]


def ansible_exec(cmd, *args, **kwargs):
"""
Execute an Ansible command with the appropriate environment.
"""
environ = os.environ.copy()
environ["ANSIBLE_CONFIG"] = "/etc/ansible-init/ansible.cfg"
cmd = f"/usr/lib/ansible-init/bin/ansible-{cmd}"
subprocess.run([cmd, *args], env = environ, check = True, **kwargs)


logger.info("fetching instance metadata")
METADATA_URL = "http://169.254.169.254/openstack/latest/meta_data.json"
response = requests.get(METADATA_URL)
response.raise_for_status()
user_metadata = response.json().get("meta", {})


logger.info("extracting collections and playbooks from metadata")
collections = assemble_list(user_metadata, "ansible_init_coll_")
playbooks = assemble_list(user_metadata, "ansible_init_pb_")
logger.info(f" found {len(collections)} collections")
logger.info(f" found {len(playbooks)} playbooks")


logger.info("installing collections")
ansible_exec(
"galaxy",
"collection",
"install",
"--force",
"--requirements-file",
"/dev/stdin",
input = json.dumps({ "collections": collections }).encode()
)


logger.info("executing remote playbooks for stage - pre")
for playbook in playbooks:
if playbook.get("stage", "post") == "pre":
logger.info(f" executing playbook - {playbook['name']}")
ansible_exec(
"playbook",
"--connection",
"local",
"--inventory",
"127.0.0.1,",
playbook["name"]
)


logger.info("executing playbooks from /etc/ansible-init/playbooks")
for playbook in sorted(pathlib.Path("/etc/ansible-init/playbooks").glob("*.yml")):
logger.info(f" executing playbook - {playbook}")
ansible_exec(
"playbook",
"--connection",
"local",
"--inventory",
"127.0.0.1,",
str(playbook)
)


logger.info("executing remote playbooks for stage - post")
for playbook in playbooks:
if playbook.get("stage", "post") == "post":
logger.info(f" executing playbook - {playbook['name']}")
ansible_exec(
"playbook",
"--connection",
"local",
"--inventory",
"127.0.0.1,",
playbook["name"]
)
9 changes: 0 additions & 9 deletions ansible/roles/linux-ansible-init/files/ansible-init.sh

This file was deleted.

3 changes: 3 additions & 0 deletions ansible/roles/linux-ansible-init/files/ansible.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[defaults]
home = /var/lib/ansible-init
local_tmp = /var/tmp/ansible-init
33 changes: 22 additions & 11 deletions ansible/roles/linux-ansible-init/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,40 @@
---

- name: Install pip
- name: Install python3-venv
package:
name: python3-pip
state: latest

- name: Upgrade pip
pip:
name: pip
state: latest
name: python3-venv

- name: Install Ansible
- name: Install dependencies into virtualenv
pip:
name:
- ansible
- jmespath
- requests
state: latest
virtualenv: /usr/lib/ansible-init
virtualenv_command: python3 -m venv --upgrade-deps

- name: Ensure config directories exist
file:
state: directory
path: "/etc/ansible-init/{{ item }}"
loop:
- vars
- playbooks
- includes

- name: Install Ansible config file
copy:
src: ansible.cfg
dest: /etc/ansible-init/ansible.cfg

- name: Install ansible-init script
copy:
src: ansible-init.sh
src: ansible-init.py
dest: /usr/bin/ansible-init
mode: +x

- name: Install systemd unit for ansible-init
- name: Install systemd unit file
copy:
src: ansible-init.service
dest: /etc/systemd/system/ansible-init.service
Expand Down

0 comments on commit 2421ce8

Please sign in to comment.