Skip to content

Commit b27719f

Browse files
committed
Merge pull request Containers-Testing-Framework#35 from vrutkovs/issue-32
Move common environment.py into file
2 parents 21894f7 + 123739f commit b27719f

File tree

4 files changed

+168
-179
lines changed

4 files changed

+168
-179
lines changed

ctf_cli/application.py

+1-11
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from ctf_cli.config import CTFCliConfig
2525
from ctf_cli.behave import BehaveWorkingDirectory, BehaveRunner
2626
from ctf_cli.exceptions import CTFCliError
27-
from ctf_cli.common_environment import common_environment_py_content, sample_ctl_ctf_config, common_steps_py_content
27+
from ctf_cli.common_environment import sample_ctl_ctf_config, common_steps_py_content
2828

2929

3030
class Application(object):
@@ -66,16 +66,6 @@ def init(self):
6666
os.mkdir(tests_dir)
6767
check_call("git add %s" % tests_dir, shell=True)
6868

69-
env_py_path = os.path.join(tests_dir, "environment.py")
70-
if os.path.exists(env_py_path):
71-
logger.info("File tests/environment.py already exists")
72-
else:
73-
logger.info("Creating environment.py")
74-
# Create environment.py
75-
with open(env_py_path, "w") as f:
76-
f.write(common_environment_py_content)
77-
check_call("git add %s" % env_py_path, shell=True)
78-
7969
features_dir = os.path.join(tests_dir, "features")
8070
if os.path.exists(features_dir):
8171
logger.info("Directory tests/features already exists")

ctf_cli/behave.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
from ctf_cli.logger import logger
2727
from ctf_cli.exceptions import CTFCliError
2828
from ctf_cli.config import CTFCliConfig
29-
from ctf_cli.common_environment import common_environment_py_content, common_environment_py_header
29+
from ctf_cli.common_environment import common_environment_py_header
30+
from ctf_cli import __path__
3031

3132
class BehaveTestsConfig(object):
3233
"""
@@ -277,10 +278,11 @@ def _write_environment_py(self):
277278
import_statement = ''
278279

279280
# create the environment.py
280-
with open(os.path.join(self._working_dir, 'environment.py'), 'w') as f:
281+
with open(os.path.join(self._working_dir, 'environment.py'), 'w') as f, \
282+
open(os.path.join(__path__[0], 'common_environment_content.py'), 'r') as src:
281283
logger.debug("Writing '%s'", os.path.join(self._working_dir, 'environment.py'))
282284
f.write(common_environment_py_header.format(project_env_py_import=import_statement))
283-
f.write(common_environment_py_content)
285+
f.write(src.read())
284286

285287
def _add_remote_steps(self):
286288
"""

ctf_cli/common_environment.py

-165
Original file line numberDiff line numberDiff line change
@@ -23,171 +23,6 @@
2323
{project_env_py_import}
2424
"""
2525

26-
common_environment_py_content = """
27-
# Some useful functions for your environment.py
28-
from types import ModuleType
29-
import tempfile
30-
import shutil
31-
import ansible.runner
32-
import logging
33-
import re
34-
import os
35-
import glob
36-
import stat
37-
import inspect
38-
import copy
39-
40-
def _invoke_other_environment_hooks(*args):
41-
# we need a copy of current frame becase it will change
42-
frame_globals = copy.copy(inspect.currentframe().f_globals)
43-
# get which function invoked us
44-
current_function = inspect.stack()[1][3]
45-
# iterate for all modules wich ends with _environemnt
46-
# and execute current method from them
47-
for g in frame_globals:
48-
if isinstance(frame_globals[g], ModuleType):
49-
if frame_globals[g].__name__.endswith("_environment"):
50-
for func_name, func in inspect.getmembers(frame_globals[g], inspect.isfunction):
51-
if func_name == current_function:
52-
func(*args)
53-
54-
55-
def before_all(context):
56-
_invoke_other_environment_hooks(context)
57-
try:
58-
ansible_cfg = context.config.userdata['ANSIBLE']
59-
inventory = ansible.inventory.Inventory(ansible_cfg)
60-
except KeyError:
61-
raise Exception("-D ANSIBLE missing")
62-
remote_dir = '/var/tmp/dkrfile'
63-
64-
def open_file(path):
65-
context.temp_dir = tempfile.mkdtemp()
66-
ret = ansible.runner.Runner(
67-
module_name='fetch',
68-
inventory=inventory,
69-
module_args='src={0} dest={1}'.format(
70-
path, context.temp_dir)).run()
71-
for host, value in ret['contacted'].iteritems():
72-
try:
73-
ret_file = open(value['dest'])
74-
return ret_file
75-
except KeyError:
76-
print ("ansible output: {0}".format(ret))
77-
raise Exception(value['msg'])
78-
context.open_file = open_file
79-
80-
def run(command):
81-
if '{{' in command:
82-
command = command.replace("{{", "{{ '{{").replace("}}", "}}' }}")
83-
logging.info("Running '%s'" % command)
84-
context.result = ansible.runner.Runner(
85-
module_name="shell",
86-
inventory=inventory,
87-
module_args="{0} chdir={1}".format(command, remote_dir)
88-
).run()
89-
passed = True
90-
# dark means not responding
91-
if context.result['dark']:
92-
passed = False
93-
print(context.result)
94-
if not context.result['contacted']:
95-
passed = False
96-
print ("no contacted hosts")
97-
for host, values in context.result['contacted'].iteritems():
98-
if values['rc'] != 0:
99-
print("On {0} returned {1}".format(host, values['rc']))
100-
print("stderr: {0}".format(values['stderr']))
101-
print("cmd: {0}".format(values['cmd']))
102-
assert False
103-
logging.info('stdout:\\n%s' % values['stdout'])
104-
if values['stderr']:
105-
logging.info('stderr\\n:%s' % values['stderr'])
106-
return values['stdout']
107-
context.run = run
108-
109-
def copy_dockerfile():
110-
111-
try:
112-
# copy dockerfile
113-
dockerfile = context.config.userdata['DOCKERFILE']
114-
dockerfile_dir = os.path.dirname(dockerfile)
115-
# create remote directory
116-
ansible.runner.Runner(
117-
module_name='file',
118-
inventory=inventory,
119-
module_args='dest={0} state=directory'.format(remote_dir)
120-
).run()
121-
# copy dockerfile
122-
ansible.runner.Runner(
123-
module_name='copy',
124-
inventory=inventory,
125-
module_args='src={0} dest={1}'.format(dockerfile, remote_dir)
126-
).run()
127-
# copy files from dockerfile
128-
f_in = open(dockerfile)
129-
for path in re.findall('(?:ADD|COPY) ([^ ]+) ', f_in.read()):
130-
for glob_path in glob.glob(os.path.join(dockerfile_dir,path)):
131-
# TODO Is there a nicer way to keep permissions?
132-
ansible.runner.Runner(
133-
module_name='copy',
134-
inventory=inventory,
135-
module_args='src={0} dest={1} directory_mode mode={2}'.format(glob_path, remote_dir,
136-
oct(stat.S_IMODE(os.stat(glob_path).st_mode)))
137-
).run()
138-
except Exception as e:
139-
logging.warning("copy_dockerfile:%s" % e)
140-
141-
copy_dockerfile()
142-
143-
# build image if not exist
144-
try:
145-
context.image = context.config.userdata['IMAGE']
146-
run('docker pull {0}'.format(context.image))
147-
except AssertionError:
148-
pass
149-
except KeyError:
150-
context.image = 'ctf'
151-
try:
152-
run('docker build -t {0} .'.format(context.image))
153-
except AssertionError:
154-
pass
155-
156-
cid_file_name = re.sub(r'\W+', '', context.image)
157-
context.cid_file = "/tmp/%s.cid" % cid_file_name
158-
159-
def after_scenario(context, scenario):
160-
_invoke_other_environment_hooks(context ,scenario)
161-
try:
162-
if context.config.userdata['KEEP_CONTAINER_AFTER_TEST']:
163-
return
164-
except KeyError, e:
165-
pass
166-
167-
try:
168-
cid = context.run('cat %s' % context.cid_file)
169-
except AssertionError, e:
170-
logging.info("before_scenario: {0}".format(e))
171-
return
172-
if cid:
173-
context.run("docker logs %s" % cid)
174-
try:
175-
context.run("docker stop %s" % cid)
176-
context.run("docker kill %s" % cid)
177-
context.run("docker rm -v %s" % cid)
178-
except AssertionError:
179-
pass
180-
if hasattr(context, 'cid'):
181-
del context.cid
182-
context.run('rm {0}'.format(context.cid_file))
183-
184-
185-
def after_all(context):
186-
_invoke_other_environment_hooks(context)
187-
if hasattr(context, 'temp_dir'):
188-
shutil.rmtree(context.temp_dir) #FIXME catch exception
189-
190-
"""
19126

19227
sample_ctl_ctf_config = """
19328
[ctf]

ctf_cli/common_environment_content.py

+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
# Some useful functions for your environment.py
2+
from types import ModuleType
3+
import tempfile
4+
import shutil
5+
import ansible.runner
6+
import logging
7+
import re
8+
import os
9+
import glob
10+
import stat
11+
import inspect
12+
import copy
13+
14+
15+
def _invoke_other_environment_hooks(*args):
16+
# we need a copy of current frame becase it will change
17+
frame_globals = copy.copy(inspect.currentframe().f_globals)
18+
# get which function invoked us
19+
current_function = inspect.stack()[1][3]
20+
# iterate for all modules wich ends with _environemnt
21+
# and execute current method from them
22+
for g in frame_globals:
23+
if isinstance(frame_globals[g], ModuleType):
24+
if frame_globals[g].__name__.endswith("_environment"):
25+
for func_name, func in inspect.getmembers(frame_globals[g], inspect.isfunction):
26+
if func_name == current_function:
27+
func(*args)
28+
29+
30+
def before_all(context):
31+
_invoke_other_environment_hooks(context)
32+
try:
33+
ansible_cfg = context.config.userdata['ANSIBLE']
34+
inventory = ansible.inventory.Inventory(ansible_cfg)
35+
except KeyError:
36+
raise Exception("-D ANSIBLE missing")
37+
remote_dir = '/var/tmp/dkrfile'
38+
39+
def open_file(path):
40+
context.temp_dir = tempfile.mkdtemp()
41+
ret = ansible.runner.Runner(
42+
module_name='fetch',
43+
inventory=inventory,
44+
module_args='src={0} dest={1}'.format(
45+
path, context.temp_dir)).run()
46+
for host, value in ret['contacted'].iteritems():
47+
try:
48+
ret_file = open(value['dest'])
49+
return ret_file
50+
except KeyError:
51+
print("ansible output: {0}".format(ret))
52+
raise Exception(value['msg'])
53+
context.open_file = open_file
54+
55+
def run(command):
56+
if '{{' in command:
57+
command = command.replace("{{", "{{ '{{").replace("}}", "}}' }}")
58+
logging.info("Running '%s'" % command)
59+
context.result = ansible.runner.Runner(
60+
module_name="shell",
61+
inventory=inventory,
62+
module_args="{0} chdir={1}".format(command, remote_dir)
63+
).run()
64+
# dark means not responding
65+
if context.result['dark']:
66+
print(context.result)
67+
if not context.result['contacted']:
68+
print("no contacted hosts")
69+
for host, values in context.result['contacted'].iteritems():
70+
if values['rc'] != 0:
71+
print("On {0} returned {1}".format(host, values['rc']))
72+
print("stderr: {0}".format(values['stderr']))
73+
print("cmd: {0}".format(values['cmd']))
74+
assert False
75+
logging.info('stdout:\\n%s' % values['stdout'])
76+
if values['stderr']:
77+
logging.info('stderr\\n:%s' % values['stderr'])
78+
return values['stdout']
79+
context.run = run
80+
81+
def copy_dockerfile():
82+
83+
try:
84+
# copy dockerfile
85+
dockerfile = context.config.userdata['DOCKERFILE']
86+
dockerfile_dir = os.path.dirname(dockerfile)
87+
# create remote directory
88+
ansible.runner.Runner(
89+
module_name='file',
90+
inventory=inventory,
91+
module_args='dest={0} state=directory'.format(remote_dir)
92+
).run()
93+
# copy dockerfile
94+
ansible.runner.Runner(
95+
module_name='copy',
96+
inventory=inventory,
97+
module_args='src={0} dest={1}'.format(dockerfile, remote_dir)
98+
).run()
99+
# copy files from dockerfile
100+
f_in = open(dockerfile)
101+
for path in re.findall('(?:ADD|COPY) ([^ ]+) ', f_in.read()):
102+
for glob_path in glob.glob(os.path.join(dockerfile_dir, path)):
103+
# TODO Is there a nicer way to keep permissions?
104+
ansible.runner.Runner(
105+
module_name='copy',
106+
inventory=inventory,
107+
module_args='src={0} dest={1} directory_mode mode={2}'.format(
108+
glob_path, remote_dir,
109+
oct(stat.S_IMODE(os.stat(glob_path).st_mode)))
110+
).run()
111+
except Exception as e:
112+
logging.warning("copy_dockerfile:%s" % e)
113+
114+
copy_dockerfile()
115+
116+
# build image if not exist
117+
try:
118+
context.image = context.config.userdata['IMAGE']
119+
run('docker pull {0}'.format(context.image))
120+
except AssertionError:
121+
pass
122+
except KeyError:
123+
context.image = 'ctf'
124+
try:
125+
run('docker build -t {0} .'.format(context.image))
126+
except AssertionError:
127+
pass
128+
129+
cid_file_name = re.sub(r'\W+', '', context.image)
130+
context.cid_file = "/tmp/%s.cid" % cid_file_name
131+
132+
133+
def after_scenario(context, scenario):
134+
_invoke_other_environment_hooks(context, scenario)
135+
try:
136+
if context.config.userdata['KEEP_CONTAINER_AFTER_TEST']:
137+
return
138+
except KeyError as e:
139+
pass
140+
141+
try:
142+
cid = context.run('cat %s' % context.cid_file)
143+
except AssertionError as e:
144+
logging.info("before_scenario: {0}".format(e))
145+
return
146+
if cid:
147+
context.run("docker logs %s" % cid)
148+
try:
149+
context.run("docker stop %s" % cid)
150+
context.run("docker kill %s" % cid)
151+
context.run("docker rm -v %s" % cid)
152+
except AssertionError:
153+
pass
154+
if hasattr(context, 'cid'):
155+
del context.cid
156+
context.run('rm {0}'.format(context.cid_file))
157+
158+
159+
def after_all(context):
160+
_invoke_other_environment_hooks(context)
161+
if hasattr(context, 'temp_dir'):
162+
shutil.rmtree(context.temp_dir) # FIXME catch exception

0 commit comments

Comments
 (0)