Skip to content

Commit 9a6a787

Browse files
author
Jan Zmeskal
authored
Add vault_password_file param to PlaybookRunner (#129)
* Add vault_password_file param to PlaybookRunner * Make PlaybookRunner.run docstring clearer
1 parent da49a0f commit 9a6a787

File tree

2 files changed

+74
-4
lines changed

2 files changed

+74
-4
lines changed

rrmngmnt/playbook_runner.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def _generate_default_inventory(self):
107107
def run(
108108
self, playbook, extra_vars=None, vars_files=None, inventory=None,
109109
verbose_level=1, run_in_check_mode=False, ssh_common_args=None,
110-
upload_playbook=True
110+
upload_playbook=True, vault_password_file=None,
111111
):
112112
"""
113113
Run Ansible playbook on host
@@ -121,7 +121,8 @@ def run(
121121
vars_files (list): List of additional variable files to be included
122122
using -e@ parameter. If one variable is specified both in
123123
extra_vars and in one of the vars_files, the one in vars_files
124-
takes precedence.
124+
takes precedence. Provide local paths to vars file(s), they
125+
will be uploaded to a remote host automatically.
125126
inventory (str): Path to an inventory file (on your machine) to be
126127
used for playbook execution. If none is provided, default
127128
inventory including only localhost will be generated and used
@@ -134,8 +135,13 @@ def run(
134135
replace) the list of default options that Ansible uses when
135136
calling ssh/sftp/scp. Example: ["-o StrictHostKeyChecking=no",
136137
"-o UserKnownHostsFile=/dev/null"]
137-
upload_playbook (bool): If the playbook is going to be uploaded
138-
from the local machine (True - Default) or not (False)
138+
upload_playbook (bool): Whether the playbook is going to be
139+
automatically uploaded from the local machine to a remote host
140+
(True - Default) or not (False).
141+
vault_password_file (str): Local path to a vault password file.
142+
It will be automatically uploaded to a remote host,
143+
same as vars_files. This is required if any of the vars_files
144+
are vault-protected.
139145
140146
Returns:
141147
tuple: tuple of (rc, out, err)
@@ -158,6 +164,13 @@ def run(
158164
for f in vars_files:
159165
self.cmd.append("-e@{}".format(self._upload_file(f)))
160166

167+
if vault_password_file:
168+
self.cmd.append(
169+
"--vault-password-file={}".format(
170+
self._upload_file(vault_password_file)
171+
)
172+
)
173+
161174
self.cmd.append("-i")
162175
if inventory:
163176
self.cmd.append(self._upload_file(inventory))

tests/test_playbook_runner.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ class PlaybookRunnerBase(object):
1717
playbook_content = ''
1818
vars_file_name = 'my_vars.yml'
1919
vars_file_content = ''
20+
vault_password_file_name = 'key.txt'
21+
vault_password_file_content = ''
2022
inventory_name = 'my_inventory'
2123
inventory_content = ''
2224
ssh_no_strict_host_key_checking = "-o StrictHostKeyChecking=no"
@@ -36,6 +38,9 @@ class PlaybookRunnerBase(object):
3638
'[ -d {tmp_dir}/{vars_file} ]'.format(
3739
tmp_dir=tmp_dir, vars_file=vars_file_name
3840
): failure,
41+
'[ -d {tmp_dir}/{vault_password_file} ]'.format(
42+
tmp_dir=tmp_dir, vault_password_file=vault_password_file_name,
43+
): failure,
3944
'[ -d {tmp_dir}/{inventory} ]'.format(
4045
tmp_dir=tmp_dir, inventory=inventory_name
4146
): failure,
@@ -65,6 +70,17 @@ class PlaybookRunnerBase(object):
6570
inventory=PlaybookRunner.default_inventory_name,
6671
playbook=playbook_name
6772
): success,
73+
# Vault password file has been provided
74+
'{bin} -e@{tmp_dir}/{vars_file} '
75+
'--vault-password-file={tmp_dir}/{vault_password_file} '
76+
'-i {tmp_dir}/{inventory} -v {tmp_dir}/{playbook}'.format(
77+
bin=PlaybookRunner.binary,
78+
vars_file=vars_file_name,
79+
vault_password_file=vault_password_file_name,
80+
tmp_dir=tmp_dir,
81+
inventory=PlaybookRunner.default_inventory_name,
82+
playbook=playbook_name
83+
): success,
6884
# Custom inventory has been provided
6985
'{bin} -i {tmp_dir}/{inventory} -v {tmp_dir}/{playbook}'.format(
7086
bin=PlaybookRunner.binary,
@@ -236,6 +252,47 @@ def test_vars_file(self, playbook_runner, fake_playbook, fake_vars_file):
236252
)
237253

238254

255+
class TestVaultPasswordFile(PlaybookRunnerBase):
256+
257+
files = {}
258+
259+
@pytest.fixture()
260+
def fake_protected_file(self, tmpdir):
261+
fpf = tmpdir.join(self.vars_file_name)
262+
fpf.write(self.vars_file_content)
263+
return str(fpf)
264+
265+
@pytest.fixture()
266+
def fake_vault_password_file(self, tmpdir):
267+
fvpf = tmpdir.join(self.vault_password_file_name)
268+
fvpf.write(self.vault_password_file_content)
269+
return str(fvpf)
270+
271+
def test_vault_password_file(
272+
self, playbook_runner, fake_playbook,
273+
fake_protected_file, fake_vault_password_file
274+
):
275+
"""
276+
User has provided YAML file with variables protected by ansible-vault.
277+
They also provided vault password file unlocking vars file.
278+
"""
279+
rc, _, _ = playbook_runner.run(
280+
playbook=fake_playbook,
281+
vars_files=[fake_protected_file],
282+
vault_password_file=fake_vault_password_file,
283+
)
284+
assert not rc
285+
assert self.check_files_on_host(
286+
[
287+
os.path.join(
288+
self.tmp_dir, PlaybookRunner.default_inventory_name
289+
),
290+
os.path.join(self.tmp_dir, self.vars_file_name),
291+
os.path.join(self.tmp_dir, self.vault_password_file_name)
292+
]
293+
)
294+
295+
239296
class TestInventory(PlaybookRunnerBase):
240297

241298
files = {}

0 commit comments

Comments
 (0)