mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-28 16:14:09 +02:00
parent
3aa21fb340
commit
9d87ce571b
@ -1 +1,42 @@
|
|||||||
These scripts are used by build.icinga.org to set up a test VM.
|
Set of scripts to set up and test a virtual demo machine
|
||||||
|
========================================================
|
||||||
|
|
||||||
|
This directory contains a few scripts primarily used by build.icinga.org.
|
||||||
|
|
||||||
|
* bootstrap-vm.sh
|
||||||
|
Ensures that all required software is installed and its configuration
|
||||||
|
is applied to the VM. (Usually not of interest for the typical user.)
|
||||||
|
|
||||||
|
* run_tests.sh
|
||||||
|
This is a wrapper script intended to be ran manually by a user.
|
||||||
|
|
||||||
|
* run_tests.py
|
||||||
|
The actual test-runner. Accepts one option (-C|--config) and expects
|
||||||
|
one or more filenames or -patterns that should be run on the VM.
|
||||||
|
|
||||||
|
* run_tests.conf
|
||||||
|
The default configuration file for the test-runner. (Used when running
|
||||||
|
the wrapper script or when no custom configuration file is passed to the
|
||||||
|
test-runner.)
|
||||||
|
|
||||||
|
Format:
|
||||||
|
- commands: This section is mandatory and contains the commands to use.
|
||||||
|
- settings: This section is mandatory and defines settings that are applied to
|
||||||
|
all tests.
|
||||||
|
- setups: This section is optional and contains setup routines that should
|
||||||
|
be ran before (setup) and after (teardown) any matching test is
|
||||||
|
executed. (Note that only one setup can be effective at a time.)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
"^v[1-9]\.test$": {
|
||||||
|
"setup": {
|
||||||
|
"copy": ["source >> target"], // Files that should be copied.
|
||||||
|
// Note that these files remain
|
||||||
|
// if not removed explicitly
|
||||||
|
"clean": ["target"], // Files to delete from the system
|
||||||
|
"exec": ["cmd1", "cmd2"] // Commands to execute on the system
|
||||||
|
},
|
||||||
|
"teardown": {
|
||||||
|
// The same kind of instructions as above can be added here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import sys
|
|
||||||
from xml.dom.minidom import getDOMImplementation
|
|
||||||
from subprocess import Popen, PIPE
|
|
||||||
|
|
||||||
impl = getDOMImplementation()
|
|
||||||
result = impl.createDocument(None, "testsuite", None)
|
|
||||||
testsuite = result.documentElement
|
|
||||||
|
|
||||||
for fn in sys.argv[1:]:
|
|
||||||
process = Popen(["./" + fn], stdout=PIPE, stderr=PIPE)
|
|
||||||
(stdoutdata, stderrdata) = process.communicate()
|
|
||||||
|
|
||||||
testcase = result.createElement("testcase")
|
|
||||||
testcase.setAttribute("classname", "vm")
|
|
||||||
testcase.setAttribute("name", fn)
|
|
||||||
|
|
||||||
systemout = result.createElement("system-out")
|
|
||||||
systemout.appendChild(result.createTextNode(stdoutdata))
|
|
||||||
testcase.appendChild(systemout)
|
|
||||||
|
|
||||||
systemerr = result.createElement("system-err")
|
|
||||||
systemerr.appendChild(result.createTextNode(stderrdata))
|
|
||||||
testcase.appendChild(systemerr)
|
|
||||||
|
|
||||||
if process.returncode != 0:
|
|
||||||
failure = result.createElement("failure")
|
|
||||||
failure.setAttribute("type", "returncode")
|
|
||||||
failure.appendChild(result.createTextNode("code: " + str(process.returncode)))
|
|
||||||
testcase.appendChild(failure)
|
|
||||||
|
|
||||||
testsuite.appendChild(testcase)
|
|
||||||
|
|
||||||
print result.toxml()
|
|
12
test/jenkins/run_tests.conf
Normal file
12
test/jenkins/run_tests.conf
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"commands": {
|
||||||
|
"copy": "scp -qF ssh_config {0} default:{1}",
|
||||||
|
"exec": "ssh -F ssh_config default {0}",
|
||||||
|
"clean": "ssh -F ssh_config default rm -f {0}"
|
||||||
|
},
|
||||||
|
"tests": {
|
||||||
|
"destination": "/tmp"
|
||||||
|
},
|
||||||
|
"setups": {
|
||||||
|
}
|
||||||
|
}
|
131
test/jenkins/run_tests.py
Executable file
131
test/jenkins/run_tests.py
Executable file
@ -0,0 +1,131 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import glob
|
||||||
|
import subprocess
|
||||||
|
from optparse import OptionParser
|
||||||
|
from xml.dom.minidom import getDOMImplementation
|
||||||
|
|
||||||
|
|
||||||
|
class TestSuite(object):
|
||||||
|
def __init__(self, configpath):
|
||||||
|
self._tests = []
|
||||||
|
self._results = {}
|
||||||
|
|
||||||
|
self.load_config(configpath)
|
||||||
|
|
||||||
|
def add_test(self, filepath):
|
||||||
|
self._tests.append(filepath)
|
||||||
|
|
||||||
|
def load_config(self, filepath):
|
||||||
|
with open(filepath) as f:
|
||||||
|
self._config = json.load(f)
|
||||||
|
|
||||||
|
def get_report(self):
|
||||||
|
dom = getDOMImplementation()
|
||||||
|
document = dom.createDocument(None, 'testsuite', None)
|
||||||
|
xml_root = document.documentElement
|
||||||
|
|
||||||
|
for name, info in self._results.iteritems():
|
||||||
|
testresult = document.createElement('testcase')
|
||||||
|
testresult.setAttribute('classname', 'vm')
|
||||||
|
testresult.setAttribute('name', name)
|
||||||
|
|
||||||
|
systemout = document.createElement('system-out')
|
||||||
|
systemout.appendChild(document.createTextNode(info['stdout']))
|
||||||
|
testresult.appendChild(systemout)
|
||||||
|
|
||||||
|
systemerr = document.createElement('system-err')
|
||||||
|
systemerr.appendChild(document.createTextNode(info['stderr']))
|
||||||
|
testresult.appendChild(systemerr)
|
||||||
|
|
||||||
|
if info['returncode'] != 0:
|
||||||
|
failure = document.createElement('failure')
|
||||||
|
failure.setAttribute('type', 'returncode')
|
||||||
|
failure.appendChild(document.createTextNode(
|
||||||
|
'code: {0}'.format(info['returncode'])))
|
||||||
|
testresult.appendChild(failure)
|
||||||
|
|
||||||
|
xml_root.appendChild(testresult)
|
||||||
|
|
||||||
|
return document.toxml()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
for path in self._tests:
|
||||||
|
test_name = os.path.basename(path)
|
||||||
|
self._apply_setup_routines(test_name, 'setup')
|
||||||
|
self._copy_test(path)
|
||||||
|
self._results[test_name] = self._run_test(path)
|
||||||
|
self._apply_setup_routines(test_name, 'teardown')
|
||||||
|
|
||||||
|
def _apply_setup_routines(self, test_name, context):
|
||||||
|
instructions = next((t[1].get(context)
|
||||||
|
for t in self._config.get('setups', {}).iteritems()
|
||||||
|
if re.match(t[0], test_name)), None)
|
||||||
|
if instructions is not None:
|
||||||
|
for instruction in instructions.get('copy', []):
|
||||||
|
source, _, destination = instruction.partition('>>')
|
||||||
|
self._copy_file(source.strip(), destination.strip())
|
||||||
|
for filepath in instructions.get('clean', []):
|
||||||
|
self._remove_file(filepath)
|
||||||
|
for command in instructions.get('exec', []):
|
||||||
|
self._exec_command(command)
|
||||||
|
|
||||||
|
def _remove_file(self, path):
|
||||||
|
command = self._config['commands']['clean'].format(path)
|
||||||
|
subprocess.call(command, shell=True)
|
||||||
|
|
||||||
|
def _exec_command(self, command):
|
||||||
|
command = self._config['commands']['exec'].format(command)
|
||||||
|
subprocess.call(command, shell=True)
|
||||||
|
|
||||||
|
def _copy_file(self, source, destination):
|
||||||
|
command = self._config['commands']['copy'].format(source, destination)
|
||||||
|
subprocess.call(command, shell=True)
|
||||||
|
|
||||||
|
def _copy_test(self, path):
|
||||||
|
self._copy_file(path, os.path.join(self._config['tests']['destination'],
|
||||||
|
os.path.basename(path)))
|
||||||
|
|
||||||
|
def _run_test(self, path):
|
||||||
|
command = self._config['commands']['exec']
|
||||||
|
target = os.path.join(self._config['tests']['destination'],
|
||||||
|
os.path.basename(path))
|
||||||
|
p = subprocess.Popen(command.format(target), stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE, shell=True)
|
||||||
|
out, err = p.communicate()
|
||||||
|
|
||||||
|
return {
|
||||||
|
'stdout': out.decode('utf-8'),
|
||||||
|
'stderr': err.decode('utf-8'),
|
||||||
|
'returncode': p.returncode
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def parse_commandline():
|
||||||
|
parser = OptionParser(version='0.1')
|
||||||
|
parser.add_option('-C', '--config', default="run_tests.conf",
|
||||||
|
help='The path to the config file to use [%default]')
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
options, arguments = parse_commandline()
|
||||||
|
suite = TestSuite(options.config)
|
||||||
|
|
||||||
|
for path in (p for a in arguments for p in glob.glob(a)):
|
||||||
|
suite.add_test(path)
|
||||||
|
|
||||||
|
suite.run()
|
||||||
|
print suite.get_report().encode('utf-8')
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
||||||
|
|
5
test/jenkins/run_tests.sh
Executable file
5
test/jenkins/run_tests.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
vagrant ssh-config > ssh_config
|
||||||
|
./run_tests.py *.test
|
||||||
|
rm -f ssh_config
|
Loading…
x
Reference in New Issue
Block a user