bootstrap-vz/bootstrapvz/plugins/ansible/tasks.py
Anders Ingemann 99bc43bbe9
ansible: Add task that removes the $HOME/.ansible directory on guest
If ansible_ssh_user is set through extra_vars, ansible will
create a .ansible directory in the home dir of that user.
However, it will be owned by root, which is not what ansible
will be expecting when it is provision through SSH at a later date.
2018-07-19 16:52:32 +02:00

99 lines
3.7 KiB
Python

from bootstrapvz.base import Task
from bootstrapvz.common.tasks import host
from bootstrapvz.common import phases
from bootstrapvz.common.tools import rel_path
from bootstrapvz.common.tools import log_check_call
import os
import json
class AddRequiredCommands(Task):
description = 'Adding commands required for provisioning with ansible'
phase = phases.validation
successors = [host.CheckExternalCommands]
@classmethod
def run(cls, info):
info.host_dependencies['ansible'] = 'ansible'
class CheckPlaybookPath(Task):
description = 'Checking whether the playbook path exist'
phase = phases.validation
@classmethod
def run(cls, info):
from bootstrapvz.common.exceptions import TaskError
playbook = rel_path(info.manifest.path, info.manifest.plugins['ansible']['playbook'])
if not os.path.exists(playbook):
msg = 'The playbook file {playbook} does not exist.'.format(playbook=playbook)
raise TaskError(msg)
if not os.path.isfile(playbook):
msg = 'The playbook path {playbook} does not point to a file.'.format(playbook=playbook)
raise TaskError(msg)
class AddPackages(Task):
description = 'Making sure python is installed'
phase = phases.preparation
@classmethod
def run(cls, info):
info.packages.add('python')
class RunAnsiblePlaybook(Task):
description = 'Running ansible playbook'
phase = phases.user_modification
@classmethod
def run(cls, info):
# Extract playbook and directory
playbook = rel_path(info.manifest.path, info.manifest.plugins['ansible']['playbook'])
# build the inventory file
inventory = os.path.join(info.root, 'tmp/bootstrap-inventory')
with open(inventory, 'w') as handle:
conn = '{} ansible_connection=chroot'.format(info.root)
content = ""
if 'groups' in info.manifest.plugins['ansible']:
for group in info.manifest.plugins['ansible']['groups']:
content += '[{}]\n{}\n'.format(group, conn)
else:
content = conn
handle.write(content)
# build the ansible command
cmd = ['ansible-playbook', '-i', inventory, playbook]
if 'extra_vars' in info.manifest.plugins['ansible']:
cmd.extend(['--extra-vars', json.dumps(info.manifest.plugins['ansible']['extra_vars'])])
if 'tags' in info.manifest.plugins['ansible']:
cmd.extend(['--tags', ','.join(info.manifest.plugins['ansible']['tags'])])
if 'skip_tags' in info.manifest.plugins['ansible']:
cmd.extend(['--skip-tags', ','.join(info.manifest.plugins['ansible']['skip_tags'])])
if 'opt_flags' in info.manifest.plugins['ansible']:
# Should probably do proper validation on these, but I don't think it should be used very often.
cmd.extend(info.manifest.plugins['ansible']['opt_flags'])
# Run and remove the inventory file
log_check_call(cmd)
os.remove(inventory)
class RemoveAnsibleSSHUserDir(Task):
description = 'Removing .ansible directory'
phase = phases.user_modification
predecessors = [RunAnsiblePlaybook]
@classmethod
def run(cls, info):
ssh_user = info.manifest.plugins['ansible']['extra_vars']['ansible_ssh_user']
# os.path.expanduser does not work in a chroot,
# so we use sh instead
[ssh_user_home] = log_check_call(['chroot', info.root, 'sh', '-c', 'echo ~' + ssh_user])
from shutil import rmtree
# [1:] to remove the leading slash from e.g. /home/ansible
ansible_dir_path = os.path.join(info.root, ssh_user_home[1:], '.ansible')
rmtree(ansible_dir_path)