Skip to content

Commit db88514

Browse files
committed
Use a custom runner if ansible 2 is used
1 parent f75eefe commit db88514

File tree

2 files changed

+106
-20
lines changed

2 files changed

+106
-20
lines changed

ansible_runner.py

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from collections import namedtuple
2+
from ansible.parsing.dataloader import DataLoader
3+
from ansible.vars import VariableManager
4+
from ansible.playbook.play import Play
5+
from ansible.inventory import Inventory
6+
from ansible.executor.task_queue_manager import TaskQueueManager
7+
from ansible.plugins.callback import CallbackBase
8+
import logging
9+
10+
11+
class ResultCallback(CallbackBase):
12+
result = {}
13+
14+
def v2_runner_on_ok(self, result, **kwargs):
15+
self.result = {'contacted': {result._host: result._result}}
16+
17+
def v2_runner_on_failed(self, result, **kwargs):
18+
self.result = {'contacted': {result._host: result._result}}
19+
20+
def v2_runner_on_unreachable(self, result, **kwargs):
21+
self.result = {'dark': result._host, 'result': result._result}
22+
23+
24+
class Runner(object):
25+
def __init__(self, inventory_file, module_name, module_args):
26+
loader = DataLoader()
27+
variable_manager = VariableManager()
28+
29+
inventory = Inventory(loader=loader,
30+
variable_manager=variable_manager,
31+
host_list=inventory_file)
32+
variable_manager.set_inventory(inventory)
33+
34+
hosts = [x.name for x in inventory.get_hosts()]
35+
36+
play_source = {
37+
"name": "Ansible Play",
38+
"hosts": hosts,
39+
"gather_facts": "no",
40+
"tasks": [{
41+
"action": {
42+
"module": module_name,
43+
"args": module_args
44+
}
45+
}]
46+
}
47+
logging.info(play_source)
48+
play = Play().load(play_source,
49+
variable_manager=variable_manager,
50+
loader=loader)
51+
52+
Options = namedtuple('Options', ['connection', 'module_path', 'forks',
53+
'become', 'become_method',
54+
'become_user', 'check'])
55+
options = Options(connection='local',
56+
module_path='',
57+
forks=100,
58+
become=None,
59+
become_method=None,
60+
become_user=None,
61+
check=False)
62+
63+
self.inventory = inventory
64+
self.variable_manager = variable_manager
65+
self.loader = loader
66+
self.play = play
67+
self.options = options
68+
self.passwords = {"vault_pass": 'secret'}
69+
70+
def run(self):
71+
result = {}
72+
results_callback = ResultCallback()
73+
try:
74+
tqm = TaskQueueManager(
75+
inventory=self.inventory,
76+
variable_manager=self.variable_manager,
77+
loader=self.loader,
78+
options=self.options,
79+
passwords=self.passwords,
80+
stdout_callback=results_callback
81+
)
82+
tqm.run(self.play)
83+
finally:
84+
result = results_callback.result
85+
if tqm is not None:
86+
tqm.cleanup()
87+
return result

common_environment.py

+19-20
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
# Some useful functions for your environment.py
22
import tempfile
33
import shutil
4-
import ansible.runner
54
import logging
65
import re
76
import os
87
import glob
98
import stat
109

10+
from ansible_runner import Runner
11+
1112

1213
def sample_before_all(context):
1314
docker_setup(context)
@@ -31,22 +32,18 @@ def docker_setup(context):
3132

3233
# Read ansible inventory from config
3334
ansible_cfg = None
34-
inventory = None
3535

3636
logging.info("Reading ansible config")
3737
try:
3838
ansible_cfg = context.config.userdata['ANSIBLE']
3939
except KeyError:
4040
raise Exception("-D ANSIBLE missing")
4141

42-
inventory = ansible.inventory.Inventory(ansible_cfg)
43-
logging.info("Ansible inventory is set\n")
44-
4542
def open_file(path):
4643
context.temp_dir = tempfile.mkdtemp()
47-
ret = ansible.runner.Runner(
44+
ret = Runner(
4845
module_name='fetch',
49-
inventory=inventory,
46+
inventory_file=ansible_cfg,
5047
module_args='src={0} dest={1}'.format(
5148
path, context.temp_dir)).run()
5249
for _, value in ret['contacted'].iteritems():
@@ -61,19 +58,21 @@ def open_file(path):
6158
def run(command):
6259
if '{{' in command:
6360
command = command.replace("{{", "{{ '{{").replace("}}", "}}' }}")
61+
if '=' in command:
62+
command = command.replace('=', '\=')
6463
logging.info("Running '%s'", command)
65-
context.result = ansible.runner.Runner(
64+
context.result = Runner(
6665
module_name="shell",
67-
inventory=inventory,
66+
inventory_file=ansible_cfg,
6867
module_args="{0} chdir={1}".format(command, context.remote_dir)
6968
).run()
69+
7070
# dark means not responding
71-
if context.result['dark']:
71+
if 'dark' in context.result:
7272
print(context.result)
73-
if not context.result['contacted']:
74-
print("no contacted hosts")
7573
for host, values in context.result['contacted'].iteritems():
76-
logging.info("On {0} returned {1}".format(host, values['rc']))
74+
retvalue = values.get('rc')
75+
logging.info("On {0} returned {1}".format(host, retvalue))
7776

7877
if 'cmd' in values:
7978
logging.info("cmd: {0}".format(values['cmd']))
@@ -88,7 +87,7 @@ def run(command):
8887
logging.info('stdout:%s', values['stdout'])
8988
result = values['stdout']
9089

91-
if values['rc'] != 0:
90+
if 'failed' in values:
9291
assert False
9392
return result
9493
context.run = run
@@ -99,25 +98,25 @@ def copy_dockerfile():
9998
dockerfile = context.config.userdata['DOCKERFILE']
10099
dockerfile_dir = os.path.dirname(dockerfile)
101100
# create remote directory
102-
ansible.runner.Runner(
101+
Runner(
102+
inventory_file=ansible_cfg,
103103
module_name='file',
104-
inventory=inventory,
105104
module_args='dest={0} state=directory'.format(context.remote_dir)
106105
).run()
107106
# copy dockerfile
108-
ansible.runner.Runner(
107+
Runner(
108+
inventory_file=ansible_cfg,
109109
module_name='copy',
110-
inventory=inventory,
111110
module_args='src={0} dest={1}'.format(dockerfile, context.remote_dir)
112111
).run()
113112
# copy files from dockerfile
114113
f_in = open(dockerfile)
115114
for path in re.findall('(?:ADD|COPY) ([^ ]+) ', f_in.read()):
116115
for glob_path in glob.glob(os.path.join(dockerfile_dir, path)):
117116
# TODO Is there a nicer way to keep permissions?
118-
ansible.runner.Runner(
117+
Runner(
118+
inventory_file=ansible_cfg,
119119
module_name='copy',
120-
inventory=inventory,
121120
module_args='src={0} dest={1} directory_mode mode={2}'.format(
122121
glob_path, context.remote_dir,
123122
oct(stat.S_IMODE(os.stat(glob_path).st_mode)))

0 commit comments

Comments
 (0)