#!/usr/bin/env python
#
# Test all of the Jenkins API features used by the
# OpenStack Infrastructure project
#
# Copyright (C) 2013 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
#
# See the License for the specific language governing permissions and
# limitations under the License.
import jenkins
import urllib
import urllib2
import urlparse
from pprint import pprint
import time
from uuid import uuid4
import ConfigParser
import os
import re
import sys
sys.path.insert(0, '../../zuul/zuul')
from launcher.jenkins import ExtendedJenkins
sys.path.insert(0, '../../devstack-gate/')
from myjenkins import Jenkins as DGJenkins
JOB_NAME = 'test-job'
NODE_NAME = 'test-node'
class JenkinsTest(object):
def __init__(self):
self.config = ConfigParser.ConfigParser()
if len(sys.argv) < 2:
print "Usage: %s zuul.conf" % sys.argv[0]
sys.exit(1)
fp = sys.argv[1]
if os.path.exists(os.path.expanduser(fp)):
self.config.read(os.path.expanduser(fp))
server = self.config.get('jenkins', 'server')
user = self.config.get('jenkins', 'user')
apikey = self.config.get('jenkins', 'apikey')
self.jenkins = ExtendedJenkins(server, user, apikey)
self.dgjenkins = DGJenkins(server, user, apikey)
def nodeExists(self):
return self.dgjenkins.node_exists(NODE_NAME)
def createNode(self):
assert not self.nodeExists()
priv_key = '/var/lib/jenkins/.ssh/id_rsa'
self.dgjenkins.create_node(
NODE_NAME, numExecutors=1,
nodeDescription='Test node',
remoteFS='/home/jenkins',
labels='testnode',
exclusive=True,
launcher='hudson.plugins.sshslaves.SSHLauncher',
launcher_params={'port': 22,
'username': 'jenkins',
'privatekey': priv_key,
'host': 'nowhere.example.com'})
assert self.nodeExists()
def reconfigNode(self):
LABEL_RE = re.compile(r'')
config = self.dgjenkins.get_node_config(NODE_NAME)
assert '' in config
config = LABEL_RE.sub('', config)
self.dgjenkins.reconfig_node(NODE_NAME, config)
config = self.dgjenkins.get_node_config(NODE_NAME)
assert '' in config
def deleteNode(self):
assert self.nodeExists()
self.dgjenkins.delete_node(NODE_NAME)
assert not self.nodeExists()
def findBuildInQueue(self, build):
for item in self.jenkins.get_queue_info():
if 'actions' not in item:
continue
for action in item['actions']:
if 'parameters' not in action:
continue
parameters = action['parameters']
for param in parameters:
# UUID is deprecated in favor of ZUUL_UUID
if ((param['name'] in ['ZUUL_UUID', 'UUID'])
and build == param['value']):
return item
return False
def addJob(self, quiet_period):
assert not self.jobExists()
xml = open('jenkins-job.xml').read()
xml = xml % quiet_period
self.jenkins.create_job(JOB_NAME, xml)
assert self.jobExists()
def reconfigJob(self, quiet_period):
assert self.jobExists()
xml = open('jenkins-job.xml').read()
xml = xml % quiet_period
self.jenkins.reconfig_job(JOB_NAME, xml)
xml2 = self.jenkins.get_job_config(JOB_NAME)
s = '%s' % quiet_period
assert s in xml2
def jobExists(self):
return self.jenkins.job_exists(JOB_NAME)
def deleteJob(self):
assert self.jobExists()
self.jenkins.delete_job(JOB_NAME)
assert not self.jobExists()
def getJobs(self):
pprint(self.jenkins.get_jobs())
def testCancelQueue(self):
uuid = str(uuid4().hex)
self.jenkins.build_job(JOB_NAME, parameters=dict(UUID=uuid))
item = self.findBuildInQueue(uuid)
assert item
self.jenkins.cancel_queue(item['id'])
assert not self.findBuildInQueue(uuid)
def testCancelBuild(self):
uuid = str(uuid4().hex)
self.jenkins.build_job(JOB_NAME, parameters=dict(UUID=uuid))
assert self.findBuildInQueue(uuid)
for x in range(60):
if not self.findBuildInQueue(uuid):
break
assert not self.findBuildInQueue(uuid)
time.sleep(1)
buildno = self.jenkins.get_job_info(JOB_NAME)['lastBuild']['number']
info = self.jenkins.get_build_info(JOB_NAME, buildno)
assert info['building']
self.jenkins.stop_build(JOB_NAME, buildno)
time.sleep(1)
info = self.jenkins.get_build_info(JOB_NAME, buildno)
assert not info['building']
console_url = urlparse.urljoin(info['url'], 'consoleFull')
self.jenkins.jenkins_open(urllib2.Request(console_url))
self.jenkins.set_build_description(JOB_NAME, buildno,
"test description")
info = self.jenkins.get_build_info(JOB_NAME, buildno)
assert info['description'] == 'test description'
j = JenkinsTest()
if j.nodeExists():
j.deleteNode()
j.createNode()
j.reconfigNode()
j.deleteNode()
if j.jobExists():
j.deleteJob()
j.addJob(5)
j.reconfigJob(10)
j.testCancelQueue()
j.testCancelBuild()
j.deleteJob()