#!/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()