salt/tests/jenkins.py

234 lines
5.9 KiB
Python
Raw Normal View History

#!/usr/bin/env python
'''
This script is used to test Salt from a Jenkins server, specifically
jenkins.saltstack.com.
This script is intended to be shell-centric!!
'''
2013-08-10 07:23:32 +00:00
# Import python libs
import os
import re
2013-08-10 07:23:32 +00:00
import sys
import subprocess
import hashlib
import random
import optparse
try:
from salt.utils.nb_popen import NonBlockingPopen
except ImportError:
# Salt not installed, or nb_popen was not yet shipped with it
2013-09-06 11:14:27 +00:00
SALT_LIB = os.path.abspath(
os.path.dirname(os.path.dirname(__file__))
)
2013-09-06 11:14:27 +00:00
if SALT_LIB not in sys.path:
sys.path.insert(0, SALT_LIB)
try:
# Let's try using the current checked out code
from salt.utils.nb_popen import NonBlockingPopen
except ImportError:
# Still an ImportError??? Let's use some "brute-force"
sys.path.insert(
0,
2013-09-06 11:14:27 +00:00
os.path.join(SALT_LIB, 'salt', 'utils')
)
from nb_popen import NonBlockingPopen
2013-09-06 11:14:27 +00:00
def generate_vm_name(platform):
'''
Generate a random enough vm name
'''
return 'ZZZ-{0}-{1}'.format(
platform,
hashlib.md5(str(random.randint(1, 100000000))).hexdigest()[:6]
)
2013-08-17 06:59:13 +00:00
2013-09-06 11:14:27 +00:00
def delete_vm(vm_name):
'''
Stop a VM
'''
2013-08-17 06:59:13 +00:00
cmd = 'salt-cloud -d {0} -y'.format(vm_name)
print('Running CMD: {0}'.format(cmd))
sys.stdout.flush()
proc = NonBlockingPopen(
cmd,
shell=True,
stdout=subprocess.PIPE,
2013-08-22 10:59:25 +00:00
stderr=subprocess.STDOUT,
2013-08-17 06:59:13 +00:00
stream_stds=True
)
proc.poll_and_read_until_finish()
proc.communicate()
2013-09-06 11:14:27 +00:00
def echo_parseable_environment(platform, provider):
'''
Echo NAME=VAL parseable output
'''
name = generate_vm_name(platform)
output = (
'SALTCLOUD_VM_PROVIDER="{provider}"\n'
'SALTCLOUD_VM_PLATFORM="{platform}"\n'
'SALTCLOUD_VM_NAME="{name}"\n').format(name=name,
provider=provider,
platform=platform)
sys.stdout.write(output)
sys.stdout.flush()
def run(opts):
'''
RUN!
'''
2013-09-06 11:14:27 +00:00
vm_name = os.environ.get(
'SALTCLOUD_VM_PLATFORM',
generate_vm_name(opts.platform)
)
cmd = (
'salt-cloud -l debug --script-args "-D -n git {commit}" -p '
2013-09-06 11:32:22 +00:00
'{provider}_{platform} {0}'.format(vm_name, **opts.__dict__)
2013-09-06 11:14:27 +00:00
)
2013-08-10 07:53:28 +00:00
print('Running CMD: {0}'.format(cmd))
2013-08-13 10:54:12 +00:00
sys.stdout.flush()
proc = NonBlockingPopen(
cmd,
shell=True,
stdout=subprocess.PIPE,
2013-08-22 10:59:25 +00:00
stderr=subprocess.STDOUT,
stream_stds=True
)
proc.poll_and_read_until_finish()
2013-08-22 10:59:25 +00:00
proc.communicate()
retcode = proc.returncode
if retcode != 0:
print('Failed to bootstrap VM. Exit code: {0}'.format(retcode))
sys.stdout.flush()
2013-09-06 11:14:27 +00:00
if opts.clean:
delete_vm(vm_name)
sys.exit(retcode)
2013-08-13 10:54:12 +00:00
print('VM Bootstrapped. Exit code: {0}'.format(retcode))
sys.stdout.flush()
# Run tests here
2013-09-06 11:14:27 +00:00
cmd = (
'salt -t 1800 {vm_name} state.sls {sls} pillar="{pillar}" '
'--no-color'.format(
sls=opts.sls,
pillar=opts.pillar.format(commit=opts.commit),
vm_name=vm_name,
commit=opts.commit
)
)
print('Running CMD: {0}'.format(cmd))
sys.stdout.flush()
2013-08-22 11:27:58 +00:00
#proc = NonBlockingPopen(
proc = subprocess.Popen(
cmd,
shell=True,
stdout=subprocess.PIPE,
2013-08-22 10:59:25 +00:00
stderr=subprocess.STDOUT,
2013-08-22 11:27:58 +00:00
# stream_stds=True
)
2013-08-22 11:27:58 +00:00
#proc.poll_and_read_until_finish()
stdout, stderr = proc.communicate()
if stdout:
print(stdout)
sys.stdout.flush()
try:
match = re.search(r'Test Suite Exit Code: (?P<exitcode>[\d]+)', stdout)
retcode = int(match.group('exitcode'))
except AttributeError:
# No regex matching
2013-08-11 18:22:30 +00:00
retcode = 1
except ValueError:
# Not a number!?
retcode = 1
except TypeError:
# No output!?
retcode = 1
if stdout:
# Anything else, raise the exception
raise
2013-09-06 11:14:27 +00:00
if opts.clean:
delete_vm(vm_name)
return retcode
2013-08-10 07:23:32 +00:00
def parse():
'''
Parse the CLI options
2013-08-10 07:23:32 +00:00
'''
parser = optparse.OptionParser()
parser.add_option('--platform',
2013-09-06 11:14:27 +00:00
dest='platform',
default=os.environ.get('SALTCLOUD_VM_PLATFORM', None),
help='The target platform, choose from:\ncent6\ncent5\nubuntu12.04')
2013-08-10 07:23:32 +00:00
parser.add_option('--provider',
2013-09-06 11:14:27 +00:00
dest='provider',
default=os.environ.get('SALTCLOUD_VM_PROVIDER', None),
help='The vm provider')
parser.add_option('--commit',
2013-09-06 11:14:27 +00:00
dest='commit',
help='The git commit to track')
parser.add_option('--sls',
2013-09-06 11:14:27 +00:00
dest='sls',
default='testrun',
help='The sls file to execute')
parser.add_option('--pillar',
2013-09-06 11:14:27 +00:00
dest='pillar',
default='{{git_commit: {commit}}}',
help='Pillar values to pass to the sls file')
2013-08-10 08:06:03 +00:00
parser.add_option('--no-clean',
2013-09-06 11:14:27 +00:00
dest='clean',
default=True,
action='store_false',
help='Clean up the built vm')
parser.add_option(
'--echo-parseable-environment',
default=False,
action='store_true',
help='Print a parseable KEY=VAL output'
)
parser.add_option(
'--delete-vm',
2013-09-06 11:59:24 +00:00
default=None,
2013-09-06 11:14:27 +00:00
help='Print a parseable KEY=VAL output'
)
2013-08-10 07:23:32 +00:00
options, args = parser.parse_args()
2013-09-06 11:14:27 +00:00
if options.delete_vm is not None:
delete_vm(options.delete_vm)
parser.exit(0)
if not options.platform:
parser.exit('--platform is required')
2013-09-06 11:14:27 +00:00
if not options.provider:
parser.exit('--provider is required')
2013-09-06 11:14:27 +00:00
if options.echo_parseable_environment:
echo_parseable_environment(options.platform, options.provider)
parser.exit(0)
if not options.commit:
parser.exit('--commit is required')
2013-09-06 11:14:27 +00:00
return options
2013-08-10 07:23:32 +00:00
if __name__ == '__main__':
2013-09-06 11:14:27 +00:00
exit_code = run(parse())
print('Exit Code: {0}'.format(exit_code))
2013-08-10 07:23:32 +00:00
sys.exit(exit_code)