def test_create_new_job_fail(self, _base_poll, _poll, _job_poll): _job_poll.return_value = {} _poll.return_value = { 'jobs': [ {'name': 'job_one', 'url': 'http://localhost:8080/job_one', 'color': 'blue'}, {'name': 'job_one', 'url': 'http://localhost:8080/job_one', 'color': 'blue'}, ] } _base_poll.return_value = _poll.return_value mock_requester = Requester(username='******', password='******') mock_requester.post_xml_and_confirm_status = mock.MagicMock( return_value='') J = Jenkins('http://localhost:8080/', username='******', password='******', requester=mock_requester) with self.assertRaises(JenkinsAPIException) as ar: J.create_job('job_new', None) self.assertEquals(str(ar.exception), 'Cannot create job job_new')
def test_create_new_job_fail(self, _base_poll, _poll, _job_poll): _job_poll.return_value = {} _poll.return_value = { 'jobs': [ { 'name': 'job_one', 'url': 'http://localhost:8080/job_one', 'color': 'blue' }, { 'name': 'job_one', 'url': 'http://localhost:8080/job_one', 'color': 'blue' }, ] } _base_poll.return_value = _poll.return_value mock_requester = Requester(username='******', password='******') mock_requester.post_xml_and_confirm_status = mock.MagicMock( return_value='') J = Jenkins('http://localhost:8080/', username='******', password='******', requester=mock_requester) with self.assertRaises(JenkinsAPIException) as ar: J.create_job('job_new', None) self.assertEquals(str(ar.exception), 'Cannot create job job_new')
def tmp_job_name(request, tmpdir, jenkins_settings): config = file(os.path.join(os.path.dirname(__file__), 'test_config.xml')).read() jenkins_url, jenkins_user, jenkins_pass = jenkins_settings jenkins = Jenkins(jenkins_url, jenkins_user, jenkins_pass) # create job using base config hasher = hashlib.sha1(str(time.time())) job_name = '%s%s' % (JOB_TEST_PREFIX, hasher.hexdigest()) job = jenkins.create_job(job_name, config) job.update_config(config) # configure local cit information using this job as base cit_config = { 'jobs': [{ 'source-job': job_name, 'feature-branch-job': job_name + '-$name', }], } cit_config_file = str(tmpdir.join('.cit.yaml')) yaml.dump(cit_config, file(cit_config_file, 'w')) def delete_test_jobs(): ''' finalizer for this fixture that removes left-over test jobs from the live jenkins server. ''' jenkins = Jenkins(jenkins_url, jenkins_user, jenkins_pass) for job_name in jenkins.iterkeys(): if job_name.startswith(JOB_TEST_PREFIX): jenkins.delete_job(job_name) request.addfinalizer(delete_test_jobs) return job_name
def main(): m = AnsibleModule( argument_spec = dict( project_key = dict(required=True), repo_name = dict(required=True), scm_host = dict(required=True), scm_port = dict(required=True), api_url = dict(required=True), api_username = dict(required=True), api_password = dict(required=True), )) p = m.params p['repo_name'] = p['repo_name'].lower() job_name = "{0}-{1}".format(p['project_key'], p["repo_name"]) view_name = p['project_key'] jenkins = Jenkins(p['api_url'], p['api_username'], p['api_password']) if jenkins.has_job(job_name): m.exit_json(changed=False, status="Job already exists: {0}".format(job_name)) cfg = job_config % p job = jenkins.create_job(job_name, cfg) if job is None: m.fail_json(msg="Failed to create job: {0}".format(cfg)) # create view # if view_name not in jenkins.views: # view = jenkins.views.create(view_name) # view.add(job_name) jenkins.build_job(job_name) m.exit_json(changed=True, status="DSL Job created: {0}".format(job_name))
class BaseSystemTest(unittest.TestCase): def setUp(self): self.jenkins = Jenkins('http://localhost:8080') self._delete_all_jobs() self._delete_all_views() def tearDown(self): pass def _delete_all_jobs(self): self.jenkins.poll() for name in self.jenkins.get_jobs_list(): self.jenkins.delete_job(name) def _delete_all_views(self): all_view_names = self.jenkins.views.keys()[1:] for name in all_view_names: del self.jenkins.views[name] def _create_job(self, name='whatever', config=EMPTY_JOB): job = self.jenkins.create_job(name, config) self.jenkins.poll() return job def assertJobIsPresent(self, name): self.jenkins.poll() self.assertTrue(name in self.jenkins, 'Job %r is absent in jenkins.' % name) def assertJobIsAbsent(self, name): self.jenkins.poll() self.assertTrue(name not in self.jenkins, 'Job %r is present in jenkins.' % name)
def tmp_job_name(request, tmpdir): config = file(os.path.join(os.path.dirname(__file__), 'test_config.xml')).read() jenkins = Jenkins(JENKINS_URL) # create job using base config hasher = hashlib.sha1(str(time.time())) job_name = '%s%s' % (JOB_TEST_PREFIX, hasher.hexdigest()) job = jenkins.create_job(job_name, config) job.update_config(config) # configure local cit information using this job as base cit_config = { 'jobs' : [{ 'source-job' : job_name, 'feature-branch-job' : job_name + '-$name', }], } cit_config_file = str(tmpdir.join('.cit.yaml')) yaml.dump(cit_config, file(cit_config_file, 'w')) def delete_test_jobs(): ''' finalizer for this fixture that removes left-over test jobs from the live jenkins server. ''' jenkins = Jenkins(JENKINS_URL) for name, job in jenkins.get_jobs(): if name.startswith(JOB_TEST_PREFIX): jenkins.delete_job(name) request.addfinalizer(delete_test_jobs) return job_name
class JenkinsApi(object): def __init__(self, url, username, token): logger.debug('create jenkins api instance') logger.debug('url %s username %s token %s', url, username, token) self.jenkins = Jenkins(url, username, token) def has_job(self, name): logger.info('check task "%s" exists', name) result = self.jenkins.has_job(name) logger.debug('return result %s', result) return result def create_job(self, name, xml): logger.debug('create task "%s", xml %s', name, xml) return self.jenkins.create_job(name, xml) def delete_job(self, name): logger.debug('upgrade task "%s", delete it', name) self.jenkins.delete_job(name) def get_config(self, name): logger.debug('get task task "%s"', name) return self.jenkins[name].get_config() def update_config(self, name, xml): logger.debug('upgrade task task "%s"', name) return self.jenkins[name].update_config(xml)
class BaseSystemTest(unittest.TestCase): def setUp(self): port = jenkinsapi_tests.systests.state['launcher'].http_port self.jenkins = Jenkins('http://localhost:%d' % port) self._delete_all_jobs() self._delete_all_views() def tearDown(self): pass def _delete_all_jobs(self): self.jenkins.poll() for name in self.jenkins.get_jobs_list(): self.jenkins.delete_job(name) def _delete_all_views(self): all_view_names = self.jenkins.views.keys()[1:] for name in all_view_names: del self.jenkins.views[name] def _create_job(self, name='whatever', config=EMPTY_JOB): job = self.jenkins.create_job(name, config) self.jenkins.poll() return job def assertJobIsPresent(self, name): self.jenkins.poll() self.assertTrue(name in self.jenkins, 'Job %r is absent in jenkins.' % name) def assertJobIsAbsent(self, name): self.jenkins.poll() self.assertTrue(name not in self.jenkins, 'Job %r is present in jenkins.' % name)
class TestCrumbsRequester(unittest.TestCase): def setUp(self): try: port = jenkinsapi_tests.systests.state['launcher'].http_port except KeyError: log.warning( "Jenkins was not launched from the test-framework, " "assuming port %i" % DEFAULT_JENKINS_PORT) port = DEFAULT_JENKINS_PORT self.jenkins = Jenkins('http://localhost:%d' % port) self.jenkins.requester.post_and_confirm_status( self.jenkins.baseurl + '/configureSecurity/configure', data={ 'Submit': 'save', 'json': json.dumps(ENABLE_CRUMBS_CONFIG) }, headers={'Content-Type': 'application/x-www-form-urlencoded'} ) self.jenkins = Jenkins( self.jenkins.baseurl, requester=CrumbRequester(baseurl=self.jenkins.baseurl)) def tearDown(self): self.jenkins.requester.post_and_confirm_status( self.jenkins.baseurl + '/configureSecurity/configure', data={ 'Submit': 'save', 'json': json.dumps(DISABLE_CRUMBS_CONFIG) }, headers={'Content-Type': 'application/x-www-form-urlencoded'} ) def test_invoke_job_with_file(self): file_data = random_string() param_file = StringIO(file_data) job_name = 'create1_%s' % random_string() job = self.jenkins.create_job(job_name, JOB_WITH_FILE) self.assertTrue(job.has_params()) self.assertTrue(len(job.get_params_list()) != 0) job.invoke(block=True, files={'file.txt': param_file}) build = job.get_last_build() while build.is_running(): time.sleep(0.25) artifacts = build.get_artifact_dict() self.assertIsInstance(artifacts, dict) art_file = artifacts['file.txt'] self.assertTrue(art_file.get_data().strip(), file_data)
def tmp_job_name(): config = file(os.path.join(os.path.dirname(__file__), 'test_config.xml')).read() jenkins = Jenkins(JENKINS_URL) hasher = hashlib.sha1(str(time.time())) job_name = '%s%s' % (JOB_TEST_PREFIX, hasher.hexdigest()) job = jenkins.create_job(job_name, config) job.update_config(config) return job_name
def main(): # TODO: specify requirements and check inputs. module=AnsibleModule( argument_spec=dict( host=dict(), state=dict(), name=dict(), template=dict(), ) ) host = module.params['host'] state = module.params['state'] name = module.params['name'] template = module.params['template'] # TODO: try catch here J = Jenkins(host) # TODO: try catch here # TODO: how to handle paths? if (template): txt = open(template) job_config = txt.read() job_config_xml = etree.fromstring(job_config) # There are 4 possible outcomes: created, updated, deleted, nochange. if (state == 'present'): # If the desired state is present we must check if the job exists and then check if the job has changed. if (J.has_job(name)): # The job exists so we must compare the XMLs for changes and update if they don't match. current_conf = J[name].get_config() current_conf = current_conf.encode('ascii','replace') current_conf_xml = etree.fromstring(current_conf) if (xml_compare(job_config_xml, current_conf_xml)): module.exit_json(msg="job exists", changed=False) else: J[name].update_config(job_config) module.exit_json(msg="job updated", changed=True) else: new_job = J.create_job(name, job_config) module.exit_json(msg="job created", changed=True) elif (state == 'absent'): if (J.has_job(name)): J.delete_job(name) module.exit_json(msg="job deleted", changed=True) else: module.exit_json(msg="job does not exist", changed=False) module.exit_json(msg=J.version, changed=False)
def test_create_new_job(self, _poll, _job_poll): _job_poll.return_value = {} mock_requester = Requester(username='******', password='******') mock_requester.post_xml_and_confirm_status = mock.MagicMock(return_value='') J = Jenkins('http://localhost:8080/', username='******', password='******', requester=mock_requester) job = J.create_job('job_new', None) self.assertTrue(isinstance(job, Job)) self.assertTrue(job.baseurl == 'http://localhost:8080/job_new') self.assertTrue(job.name == 'job_new')
class Myjenkins(): def __init__(self,url,username,password): self.server=Jenkins(url, username=username, password=password) def get_job_details(self): for job_name,job_instance in self.server.get_jobs(): print(job_instance.name) print(job_instance.get_description()) print(job_instance.is_running()) print(job_instance.is_enabled()) print("######") def create_job(self,**config): curr_con=open(config['xml'],'r+',encoding='utf-8') cc=curr_con.read() self.server.create_job(config["jobname"],cc.encode('utf-8')) def create_job_str(self,**config): cc=jkconfig.base self.server.create_job(config["jobname"],cc.encode('utf-8')) def build_job(self,jobname,params=None): self.server.build_job(jobname,params)
def fixupFile(filename, config_xml, branch): # # fixup job template # ApplicationType = sys.argv[1] ApplicationFlavor = sys.argv[2] ApplicationName = sys.argv[3] GitRepoPath = sys.argv[4] PomPath = sys.argv[5] ArtifactoryUrl = sys.argv[6] PomPathOnly = os.path.dirname(PomPath) # s = Template(config_xml) job_def = s.substitute( ApplicationType = ApplicationType, ApplicationFlavor = ApplicationFlavor, ApplicationName = ApplicationName, GitRepoPath = GitRepoPath, PomPath = PomPath, ArtifactoryUrl = ArtifactoryUrl, PomPathOnly = PomPathOnly, CodeBranch = branch ) jenkins_url = None if "JENKINS_URL" in os.environ: jenkins_url = os.environ["JENKINS_URL"] else: print "JENKINS_URL environment variable must be set." exit(1) jenkins_user = None if "NUI_USER" in os.environ: jenkins_user = os.environ["NUI_USER"] jenkins_password = None if "NUI_PWD" in os.environ: jenkins_password = os.environ["NUI_PWD"] if jenkins_password is None or jenkins_user is None: api = Jenkins(jenkins_url, requester = Requester(baseurl=jenkins_url, ssl_verify=False)) else: # If authentication is not turned on, this call raises an exception try: api = Jenkins(jenkins_url, jenkins_user, jenkins_password, requester = Requester(username=jenkins_user, password=jenkins_password, baseurl=jenkins_url, ssl_verify=False)) except: api = Jenkins(jenkins_url, requester = Requester(baseurl=jenkins_url, ssl_verify=False)) filenames = filename.split(".") project_name = filenames[0]+" "+ApplicationName print "Creating project '"+project_name+"'" job = api.create_job(project_name, job_def)
def main(): # TODO: specify requirements and check inputs. module = AnsibleModule(argument_spec=dict( host=dict(), state=dict(), name=dict(), template=dict(), )) host = module.params['host'] state = module.params['state'] name = module.params['name'] template = module.params['template'] # TODO: try catch here J = Jenkins(host) # TODO: try catch here # TODO: how to handle paths? if (template): txt = open(template) job_config = txt.read() job_config_xml = etree.fromstring(job_config) # There are 4 possible outcomes: created, updated, deleted, nochange. if (state == 'present'): # If the desired state is present we must check if the job exists and then check if the job has changed. if (J.has_job(name)): # The job exists so we must compare the XMLs for changes and update if they don't match. current_conf = J[name].get_config() current_conf = current_conf.encode('ascii', 'replace') current_conf_xml = etree.fromstring(current_conf) if (xml_compare(job_config_xml, current_conf_xml)): module.exit_json(msg="job exists", changed=False) else: J[name].update_config(job_config) module.exit_json(msg="job updated", changed=True) else: new_job = J.create_job(name, job_config) module.exit_json(msg="job created", changed=True) elif (state == 'absent'): if (J.has_job(name)): J.delete_job(name) module.exit_json(msg="job deleted", changed=True) else: module.exit_json(msg="job does not exist", changed=False) module.exit_json(msg=J.version, changed=False)
def test_create_new_job_fail(mocker, monkeypatch): def fake_jenkins_poll(cls, tree=None): # pylint: disable=unused-argument return TWO_JOBS_DATA def fake_job_poll(cls, tree=None): # pylint: disable=unused-argument return {} monkeypatch.setattr(JenkinsBase, '_poll', fake_jenkins_poll) monkeypatch.setattr(Jenkins, '_poll', fake_jenkins_poll) monkeypatch.setattr(Job, '_poll', fake_job_poll) mock_requester = Requester(username='******', password='******') mock_requester.post_xml_and_confirm_status = mocker.MagicMock( return_value='' ) jenkins = Jenkins('http://localhost:8080/', username='******', password='******', requester=mock_requester) with pytest.raises(JenkinsAPIException) as ar: jenkins.create_job('job_new', None) assert 'Job XML config cannot be empty' in str(ar.value)
def test_create_new_job_fail(mocker, monkeypatch): def fake_jenkins_poll(cls, tree=None): # pylint: disable=unused-argument return TWO_JOBS_DATA def fake_job_poll(cls, tree=None): # pylint: disable=unused-argument return {} monkeypatch.setattr(JenkinsBase, '_poll', fake_jenkins_poll) monkeypatch.setattr(Jenkins, '_poll', fake_jenkins_poll) monkeypatch.setattr(Job, '_poll', fake_job_poll) mock_requester = Requester(username='******', password='******') mock_requester.post_xml_and_confirm_status = mocker.MagicMock( return_value='') jenkins = Jenkins('http://localhost:8080/', username='******', password='******', requester=mock_requester) with pytest.raises(JenkinsAPIException) as ar: jenkins.create_job('job_new', None) assert 'Job XML config cannot be empty' in str(ar.value)
def test_create_dup_job(self, _base_poll, _poll, _job_poll): _poll.return_value = { 'jobs': [ {'name': 'job_one', 'url': 'http://localhost:8080/job_one', 'color': 'blue'}, {'name': 'job_two', 'url': 'http://localhost:8080/job_two', 'color': 'blue'}, ] } _base_poll.return_value = _poll.return_value _job_poll.return_value = {} J = Jenkins('http://localhost:8080/', username='******', password='******') job = J.create_job('job_one', None) self.assertTrue(isinstance(job, Job)) self.assertTrue(job.baseurl == 'http://localhost:8080/job_one') self.assertTrue(job.name == 'job_one')
def test_create_new_job(self, _poll, _job_poll): _job_poll.return_value = {} mock_requester = Requester(username='******', password='******') mock_requester.post_xml_and_confirm_status = mock.MagicMock( return_value='') J = Jenkins('http://localhost:8080/', username='******', password='******', requester=mock_requester) job = J.create_job('job_new', None) self.assertTrue(isinstance(job, Job)) self.assertTrue(job.baseurl == 'http://localhost:8080/job_new') self.assertTrue(job.name == 'job_new')
class BaseSystemTest(unittest.TestCase): def setUp(self): try: port = jenkinsapi_tests.systests.state['launcher'].http_port except KeyError: log.warning("Jenkins was not launched from the test-framework, " "assuming port %i" % DEFAULT_JENKINS_PORT) port = DEFAULT_JENKINS_PORT self.jenkins = Jenkins('http://localhost:%d' % port) self._delete_all_jobs() self._delete_all_views() self._delete_all_credentials() def tearDown(self): pass def _delete_all_jobs(self): self.jenkins.poll() for name in self.jenkins.keys(): del self.jenkins[name] def _delete_all_views(self): all_view_names = self.jenkins.views.keys()[1:] for name in all_view_names: del self.jenkins.views[name] def _delete_all_credentials(self): all_cred_names = self.jenkins.credentials.keys() for name in all_cred_names: del self.jenkins.credentials[name] def _create_job(self, name='whatever', config=EMPTY_JOB): job = self.jenkins.create_job(name, config) self.jenkins.poll() return job def assertJobIsPresent(self, name): self.jenkins.poll() self.assertTrue(name in self.jenkins, 'Job %r is absent in jenkins.' % name) self.assertIsInstance(self.jenkins.get_job(name), Job) self.assertIsInstance(self.jenkins[name], Job) def assertJobIsAbsent(self, name): self.jenkins.poll() self.assertTrue(name not in self.jenkins, 'Job %r is present in jenkins.' % name)
def fixupFile(filename, config_xml): # # fixup job template # ApplicationType = sys.argv[2] ApplicationFlavor = sys.argv[3] ApplicationName = sys.argv[4] GitRepoPath = sys.argv[5] GitCredentials = sys.argv[6] PomPath = sys.argv[7] PomPathOnly = os.path.dirname(PomPath) # s = Template(config_xml) job_def = s.substitute( ApplicationType = ApplicationType, ApplicationFlavor = ApplicationFlavor, ApplicationName = ApplicationName, GitRepoPath = GitRepoPath, GitCredentials = GitCredentials, PomPath = PomPath, PomPathOnly = PomPathOnly ) jenkins_url = None if "JENKINS_URL" in os.environ: jenkins_url = os.environ["JENKINS_URL"] else: print "JENKINS_URL environment variable must be set." exit(1) jenkins_user = None if "NUI_USER" in os.environ: jenkins_user = os.environ["NUI_USER"] jenkins_password = None if "NUI_PWD" in os.environ: jenkins_password = os.environ["NUI_PWD"] print "Connection: "+jenkins_url+" ("+jenkins_user+")" try: api = Jenkins(jenkins_url, jenkins_user, jenkins_password) except: api = Jenkins(jenkins_url) filenames = filename.split(".") project_name = filenames[0]+" "+ApplicationName print "Creating project '"+project_name+"'" job = api.create_job(project_name, job_def)
class BaseSystemTest(unittest.TestCase): def setUp(self): try: port = jenkinsapi_tests.systests.state['launcher'].http_port except KeyError: log.warning( "Jenkins was not launched from the test-framework, " "assuming port %i" % DEFAULT_JENKINS_PORT) port = DEFAULT_JENKINS_PORT self.jenkins = Jenkins('http://localhost:%d' % port) self._delete_all_jobs() self._delete_all_views() def tearDown(self): pass def _delete_all_jobs(self): self.jenkins.poll() for name in self.jenkins.keys(): del self.jenkins[name] def _delete_all_views(self): all_view_names = self.jenkins.views.keys()[1:] for name in all_view_names: del self.jenkins.views[name] def _create_job(self, name='whatever', config=EMPTY_JOB): job = self.jenkins.create_job(name, config) self.jenkins.poll() return job def assertJobIsPresent(self, name): self.jenkins.poll() self.assertTrue(name in self.jenkins, 'Job %r is absent in jenkins.' % name) self.assertIsInstance(self.jenkins.get_job(name), Job) self.assertIsInstance(self.jenkins[name], Job) def assertJobIsAbsent(self, name): self.jenkins.poll() self.assertTrue(name not in self.jenkins, 'Job %r is present in jenkins.' % name)
def test_create_dup_job(self, _base_poll, _poll, _job_poll): _poll.return_value = { 'jobs': [ { 'name': 'job_one', 'url': 'http://localhost:8080/job_one' }, { 'name': 'job_two', 'url': 'http://localhost:8080/job_two' }, ] } _base_poll.return_value = _poll.return_value _job_poll.return_value = {} J = Jenkins('http://localhost:8080/', username='******', password='******') job = J.create_job('job_one', None) self.assertTrue(isinstance(job, Job)) self.assertTrue(job.baseurl == 'http://localhost:8080/job_one') self.assertTrue(job.name == 'job_one')
# This is to test jenkins capability to handle a large number of # jobs. (e.g. 100000) # requires the jenkinsapi egg: # https://github.com/salimfadhley/jenkinsapi import time from jenkinsapi.jenkins import Jenkins limit = 100000 j = Jenkins('http://localhost:8080') text_buffer = None with open('test.xml') as fh: text_buffer = fh.read() print "Deleting jobs..." for i in range(limit): try: j.delete_job('job-%d' % i) except Exception: pass print "deleted!" start_time = time.time() for i in range(limit): print "Creating job #%d..." % i j.create_job('job-%d' % i, text_buffer) print "Success!" end_time = time.time() print "Elapsed time: %f" % (end_time - start_time)
#!/usr/bin/env python import logging from jenkinsapi.jenkins import Jenkins from pkg_resources import resource_string log_level = getattr(logging, 'DEBUG') logging.basicConfig(level=log_level) logger = logging.getLogger() jenkins_url = "http://docker:8080/" api = Jenkins(jenkins_url) job_name='cd-demo-seed' if not api.has_job(job_name): logger.info('create job ['+ job_name + ']') xml = resource_string(__name__, 'cd_demo_seed.xml') api.create_job(job_name, xml) job = api[job_name] logger.info('job [' + job.name + '] created') else: logger.info('job [' + job_name + '] exists already')
exit(1) if sys.argv[4] not in api.jobs: print "Job '"+sys.argv[4]+"' not found" exit(1) job = api.jobs[sys.argv[4]] view.add_job(sys.argv[4], job) print "Job added to view" elif sys.argv[2] == "create-job": if (len(sys.argv) < 5): print "Usage: python jenkins.py <host> create-job <name> <file>" exit(1) if sys.argv[3] in api.jobs: print "Job '"+sys.argv[3]+"' already exists" else: xml = readFile(sys.argv[4]) job = api.create_job(sys.argv[3], xml) print("Job created - "+job.name) elif sys.argv[2] == "create-job-add-to-view": if (len(sys.argv) < 6): print "Usage: python jenkins.py <host> create-job-add-to-view <view> <name> <file>" exit(1) if sys.argv[4] in api.jobs: job = api.jobs[sys.argv[4]] print "Job '"+sys.argv[4]+"' already exists" else: xml = readFile(sys.argv[5]) job = api.create_job(sys.argv[4], xml) print("Job created - "+job.name) api.views[sys.argv[3]].add_job(sys.argv[4], job) print "Job added to view" elif sys.argv[2] == "run-job":
class JenkinsWorks: """ Wrapper class that provides connection with Jenkins """ def __init__(self, url, username, password, repository_path, template_location, template_name, job_prefix, job_suffix, view_prefix, view_suffix, preview): """ JenkinsWorks constructor. Sets necessary variables """ self.jenkins_url = url self.jenkins_username = username self.jenkins_password = password self.repo_path = repository_path self.template_name = template_name self.job_prefix = job_prefix self.job_suffix = job_suffix self.view_prefix = view_prefix self.view_suffix = view_suffix self.preview = preview self.existing_jobs = [] self.existing_views = [] self.branches = [] self._get_api_instance() self._get_repo_origin() def _get_api_instance(self): """ Get Jenkins API object """ self.api = Jenkins(self.jenkins_url, self.jenkins_username, self.jenkins_password) return self.api def _get_repo_origin(self): """ Get Git origin url """ self.repo = git.Repo(self.repo_path) self.repo_url = self.repo.remotes.origin.url return self.repo_url def get_existing_jobs_list(self): """ Get existing Jenkins job names that conform to the following convention: prefix + branch_name + suffix """ for job in self.api.get_jobs(): job_instance = self.api.get_job(job[0]) if re.match(self.job_prefix + ".*" + self.job_suffix, job_instance.name): self.existing_jobs.append(job_instance.name) return self.existing_jobs def get_existing_views(self): """ Get existing Jenkins views that conform to the following convention: prefix + branch_name + suffix """ for view_name in self.api.views.keys(): if re.match(self.view_prefix + ".*" + self.view_suffix, view_name): self.existing_views.append(view_name) return self.existing_views def get_branches(self): """ Get all remote branches from Git """ pattern = re.compile('[\w\d]+\trefs/heads/(.*)') output = self.repo.git.ls_remote("--heads").split("\n") for line in output: result = pattern.match(line) if result: self.branches.append(result.group(1)) return self.branches def render_template(self, branch): """ Render XML from the Jinja2 template """ from jinja import FileSystemLoader from jinja.environment import Environment env = Environment() env.loader = FileSystemLoader('templates') template = env.get_template(self.template_name) rendered_xml = template.render(git_repo=self.repo_url, git_branch=branch) return rendered_xml def create_job(self, job_name, xml): """ Create Jenkins job with specific job name and rendered from Jinja2 template XML """ print("Creating job: %s" % job_name) if not self.preview: self.api.create_job(jobname=job_name, xml=xml) def delete_job(self, job_name): """ Delete Jenkins job """ print("Deleting job: %s" % job_name) if not self.preview: self.api.delete_job(jobname=job_name) def create_view(self, view_name): """ Create Jenkins view with specific view name """ print("Creating view: %s" % view_name) if not self.preview: view = self.api.views.create(view_name) return view return view_name def populate_view(self, view, job_name): """ Add job to the Jenkins view """ print("Adding job %s to view %s" % (job_name, view.__str__())) if not self.preview: view.add_job(job_name) def delete_view(self, view_name): """ Delete Jenkins view """ print("Deleting view: %s" % view_name) if not self.preview: del self.api.views[view_name] def update_jenkins_config(self): """ Function that decides what Jenkins jobs and views should be created and what should be deleted """ if self.preview: print("Going to run in the PREVIEW mode") created_jobs = [] created_views = [] for branch in self.branches: job_name = self.job_prefix + branch + self.job_suffix view_name = self.view_prefix + branch if job_name not in self.existing_jobs: xml = self.render_template(branch) self.create_job(job_name, xml) if view_name not in self.existing_views: view = self.create_view(view_name) self.populate_view(view, job_name) created_jobs.append(job_name) created_views.append(view_name) for job in self.existing_jobs: if job not in created_jobs: self.delete_job(job) for view in self.existing_views: if view not in created_views: self.delete_view(view)
""" A lower-level implementation of copying a job in Jenkins """ from __future__ import print_function import requests from jenkinsapi.jenkins import Jenkins from pkg_resources import resource_string from jenkinsapi_tests.test_utils.random_strings import random_string J = Jenkins('http://localhost:8080') jobName = random_string() jobName2 = '%s_2' % jobName url = 'http://localhost:8080/createItem?from=%s&name=%s&mode=copy' % (jobName, jobName2) xml = resource_string('examples', 'addjob.xml') j = J.create_job(jobname=jobName, xml=xml) h = {'Content-Type': 'application/x-www-form-urlencoded'} response = requests.post(url, data='dysjsjsjs', headers=h) print(response.text.encode('UTF-8'))
from __future__ import print_function from pkg_resources import resource_string from jenkinsapi.jenkins import Jenkins from jenkinsapi.utils.crumb_requester import CrumbRequester url = "jenkinsURL" username = "******" password = "******" crumb_requester = CrumbRequester(baseurl=url, username=username, password=password) j = Jenkins(url, username=username, password=password, requester=crumb_requester) job_name = 'jaydeepCreatedByPythonTest-4' xml = resource_string(__name__, 'job.xml') print(xml) job = j.create_job(jobname=job_name, xml=xml) # Get job from Jenkins by job name my_job = j[job_name] print(my_job)
JENKINS_INSTALLER_JOB_NAME = "selenium" #start a job jenkins_server_obj.build_job(JENKINS_INSTALLER_JOB_NAME) jenkins_job_instance = jenkins_server_obj.get_job(JENKINS_INSTALLER_JOB_NAME) #get job list print(jenkins_server_obj.get_jobs_list()) #get job selenium print(jenkins_job_instance) #global message jenkins_server_obj.pprint() #job config.xml xml = jenkins_server_obj['selenium'].get_config() print(xml) ''' #CURB JOB jenkins_server_obj.create_job('RF1',xml) jenkins_server_obj.delete_job('RF1') jenkins_server_obj.copy_job('selenium','selenium3') jenkins_server_obj.rename_job('selenium1','selenium4') ''' #job list jobs = jenkins_server_obj.get_jobs() for job in jobs: print(job[0]) #get plugin details for plugin in jenkins_server_obj.get_plugins().values(): print('-------------------------------------------------------------') print(plugin)
class JenkinsCI: def __init__(self, jenkins_url, username, password): self.jenkins_url = jenkins_url self.jenkins = Jenkins(self.jenkins_url, username=username, password=password) self.build_info = [] __user_data = "Basic " + (username + ":" + password).encode("base64").rstrip() self.__headers = {"Content-Type": "application/x-www-form-urlencoded", "Authorization": __user_data} def __invoke_method(self, command, method="GET", parameters=None, silent=False): if parameters is None: parameters = {} method_url = urljoin(self.jenkins_url, command) request_data = None if method == "GET": query_string = urlencode(parameters) method_url = method_url + "?" + query_string else: request_data = urlencode(parameters) req = Request(method_url, data=request_data, headers=self.__headers) req.get_method = lambda: method try: response = urlopen(req).read() except HTTPError as e: if not silent: print "{0} : {1}".format(method_url, e) return None try: return loads(response.decode("utf-8")) except ValueError: return response.decode("utf-8") def create_job(self, job_name, xml_config): try: self.jenkins.create_job(job_name, xml_config) except Exception as e: print e return False else: print "[+] : job {0} created".format(job_name) return True def format_path_folder(self, path_folder): return "job/" + path_folder.replace("/", "/job/") def rename_folder(self, path_folder, new_path_folder): new_folder_name = new_path_folder.split("/")[-1] command = "{0}/doRename".format(self.format_path_folder(path_folder)) json_parameters = dumps({"newName": new_folder_name}) parameters = {"newName": new_folder_name, "Submit": "Yes", "json": json_parameters} result = self.__invoke_method(command, "POST", parameters) if not result: raise JenkinsException("Cannot rename folder {0} to {1}".format(path_folder, new_path_folder), 1) print "[+] : folder {0} renamed to {1}".format(path_folder, new_path_folder) def create_folder(self, path_folder, recursive=False): if recursive: return self.recursive_create_folders(path_folder) split_path = path_folder.split("/") folder_name = split_path[-1] command = "createItem" if len(split_path) > 1: new_path = "/".join(f for f in split_path[:-1]) command = self.format_path_folder(new_path) + "/" + command json_parameters = dumps({"name": folder_name, "mode": "com.cloudbees.hudson.plugins.folder.Folder", "from": "", "Submit": "OK"}) parameters = {"name": folder_name, "mode": "com.cloudbees.hudson.plugins.folder.Folder", "from": "", "Submit": "OK", "json": json_parameters} result = self.__invoke_method(command, "GET", parameters) if not result: raise JenkinsException("Cannot create folder {0}".format(path_folder), 1) print "[+] : folder {0} created".format(path_folder) def recursive_create_folders(self, path_folder): split_path = path_folder.split("/") root = split_path[0] for folder in split_path[1:]: if not self.check_folder_exist(root): self.create_folder(root) root += "/{0}".format(folder) def check_folder_exist(self, path_folder): result = self.__invoke_method(self.format_path_folder(path_folder), "GET", silent=True) if result: return True return False def move_job_on_folder(self, job_name, path_folder): command = "{0}/move/move".format(self.format_path_folder(job_name)) json_parameters = {"destination": "/{0}".format(path_folder)} parameters = {"destination": "/{0}".format(path_folder), "json": json_parameters, "Submit": "Move"} result = self.__invoke_method(command, "POST", parameters) if not result: raise JenkinsException("Cannot move job {0} to {1} folder".format(job_name, path_folder), 2) print "[+] : Job {0} moved to {1} folder".format(job_name, path_folder) def get_plugins_version_dict(self, plugins_name_list): plugins_version_dict = {} all_plugins = self.jenkins.get_plugins().get_plugins_dict() for plugin in plugins_name_list: plugins_version_dict[plugin] = all_plugins[plugin].version return plugins_version_dict def copy_job(self, template_job, new_job): try: self.jenkins.copy_job(template_job, new_job) except Exception as e: print e return False else: print "[+] : Job {0} created".format(new_job) return True def plugins_checker(self, plugins_list): all_installed = True for plugin in plugins_list: if not self.jenkins.has_plugin(plugin): all_installed = False print "[-] : Plugin {0} is not installed".format(plugin) if not all_installed: return False return True def check_job_exist(self, job_name): if self.jenkins.has_job(job_name): return True return False def check_jobs_exist(self, jobs_list): status_exist = False for job in jobs_list: if self.check_job_exist(job): print "[-] : Job {0} already exist".format(job) status_exist = True return status_exist def create_view(self, view_name): views = self.jenkins.views if view_name not in views.keys(): views.create(view_name) print "[+] : view {0} created".format(view_name) def move_job_on_view(self, view_name, job_name): view_url = "{0}/view/{1}".format(self.jenkins_url, view_name) view = self.jenkins.get_view_by_url(view_url) view.add_job(job_name) def delete_job(self, job_name): if self.check_job_exist(job_name): self.jenkins.delete_job(job_name) print "[+] : job {0} deleted".format(job_name) def build_job(self, job_name, arguments): job = self.jenkins.get_job(job_name) build_number = job.get_next_build_number() job.invoke(build_params=arguments) return build_number def get_git_info_build(self, job_name, build_number): job = self.jenkins.get_job(job_name) build = job.get_build(build_number) return build.get_revision() def get_url_build(self, job_name, build_number): return "{0}/job/{1}/{2}".format(self.jenkins_url, job_name, build_number) def print_info_build(self, job_name, build_number): url = self.get_url_build(job_name, build_number) git_info = self.get_git_info_build(job_name, build_number) print "Job: {0} #{1}".format(job_name, build_number) print "Url: {0}".format(url) for info in git_info: print "Branch : {0} | Revision : {1}".format(info["name"], info["SHA1"])
output, errors = p.communicate() UPDATEMD5HASH=output.split()[0] if (UPDATEMD5HASH != INITIALMD5HASH ): print ("MD5 Hash For Hello.py has changed , Jenkins Job Triggered") # Trigger the jenkins job if the hash has changed J=Jenkins(JENKINS_SERVER_URL, username = JENKINS_SERVER_USERNAME, password = JENKINS_SERVER_PASSWORD) print ("Jenkins Server Version:" + str(J.version) ) job=J.get_job('test-job') print ("Is Jenkins Job Enabled:" + " " + str(job.is_enabled())) print ("Is Jenkins JOB Running already:" + " " + str(job.is_running())) #Feeding a sampple xml configuration file #required for the jenkins job xml = resource_string('examples', 'addjob.xml') #This XML config file is used by the create_job api #To create the jenkins job title 'test-job' job = J.create_job(jobname='test-job', xml='addjob.xml') #Invoking the 'test-job' jenkins job job.invoke() print ("Jenkins Job Triggered") sys.exit(0) else : print ("hello.py has not been modified") print ("Jenkins Job Not Triggered ") print ("Exiting.....") sys.exit(0) #If you are curious , Additional API calls follow # Jenkins objects appear to be dict-like, mapping keys (job-names) to their attributes #print J['test-job'] -> To obtain the attributes of jenkins job titled "jenkins-job" #print J['test_job'].get_last_good_build() -> Ex: To obtain the last successfull build
from pkg_resources import resource_string from jenkinsapi.view import View from jenkinsapi.views import Views from jenkinsapi.jenkins import Jenkins log_level = getattr(logging, 'DEBUG') logging.basicConfig(level=log_level) logger = logging.getLogger() jenkins_url = "http://127.0.0.1:8080/" api = Jenkins(jenkins_url) jobName = 'foo_job2' xml = resource_string('examples', 'addjob.xml') j = api.create_job(jobname=jobName, config=xml) # Create ListView in main view logger.info('Attempting to create new nested view') top_view = api.views.create('TopView', Views.NESTED_VIEW) logger.info('top_view is %s' % top_view) if top_view == None: logger.error('View was not created') else: logger.info('View has been created') print 'top_view.views=', top_view.views.keys() logger.info('Attempting to create view inside nested view') sub_view = top_view.views.create('SubView') if sub_view == None: logger.info('View was not created')
if new_view is None: logger.error("View %s was not created" % test_view_name) else: logger.info("View %s has been created: %s" % (new_view.name, new_view.baseurl)) else: logger.info("View %s already exists" % test_view_name) # No error is raised if view already exists logger.info("Attempting to create view that already exists") my_view = api.views.create(test_view_name) logger.info("Create job and assign it to a view") job_name = "foo_job2" xml = resource_string("examples", "addjob.xml") my_job = api.create_job(jobname=job_name, xml=xml) # add_job supports two parameters: job_name and job object # passing job object will remove verification calls to Jenkins my_view.add_job(job_name, my_job) assert len(my_view) == 1 logger.info("Attempting to delete view that already exists") del api.views[test_view_name] if test_view_name in api.views: logger.error("View was not deleted") else: logger.info("View has been deleted") # No error will be raised when attempting to remove non-existing view
import logging from pkg_resources import resource_string from jenkinsapi.views import Views from jenkinsapi.jenkins import Jenkins log_level = getattr(logging, 'DEBUG') logging.basicConfig(level=log_level) logger = logging.getLogger() jenkins_url = "http://127.0.0.1:8080/" api = Jenkins(jenkins_url) jobName = 'foo_job2' xml = resource_string('examples', 'addjob.xml') j = api.create_job(jobname=jobName, xml=xml) # Create ListView in main view logger.info('Attempting to create new nested view') top_view = api.views.create('TopView', Views.NESTED_VIEW) logger.info('top_view is %s' % top_view) if top_view is None: logger.error('View was not created') else: logger.info('View has been created') print('top_view.views=', top_view.views.keys()) logger.info('Attempting to create view inside nested view') sub_view = top_view.views.create('SubView') if sub_view is None: logger.info('View was not created')
J = Jenkins('http://localhost:8080') print J.items() j = J['foo'] j = J.get_job("foo") b = j.get_last_build() print b mjn = b.get_master_job_name() print(mjn) EMPTY_JOB_CONFIG = '''\ <?xml version='1.0' encoding='UTF-8'?> <project> <actions/> <description></description> <keepDependencies>false</keepDependencies> <properties/> <scm class="hudson.scm.NullSCM"/> <canRoam>true</canRoam> <disabled>false</disabled> <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding> <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding> <triggers class="vector"/> <concurrentBuild>false</concurrentBuild> <builders/> <publishers/> <buildWrappers/> </project> ''' new_job = J.create_job(name='foo_job', config=EMPTY_JOB_CONFIG)
""" This example shows how to create job from XML file and how to delete job """ from __future__ import print_function from pkg_resources import resource_string from jenkinsapi.jenkins import Jenkins jenkins = Jenkins('http://localhost:8080') job_name = 'pipeline2' xml = resource_string('examples', './jenkins_dir/jobs/config.xml') print(xml) job = jenkins.create_job(jobname=job_name, xml=xml) # Get job from Jenkins by job name my_job = jenkins[job_name] print(my_job)
# Date : 27.11.2013 # # Licensed under GPL # ########################################################################### import sys import jenkinsapi,pkg_resources from jenkinsapi import * from pkg_resources import * from jenkinsapi.jenkins import Jenkins New_Job_Name=sys.argv[1] XML_File=sys.argv[2] print "\n New_Job_Name : "+New_Job_Name print "\n XML File : "+XML_File+"\n" Jenkins_server=Jenkins('http://localhost:8080') #This XML file should be located in the same directory where the script is executed #This XML file decides so many jenkins parameters for the Job like configuration system,version control etc. #This XML File is used as a configuration either for creation or Reconfiguration xml=resource_string(__name__,XML_File) #if you want the sample content just do this command for any existing job #Now it should have reconfigured the job for you with the configuration you have mentioned in test.xml Jenkins_server.create_job(New_Job_Name,xml)
class LazyJenkins(object): jobs_filter = [p for p in SETTINGS.GHP_JOBS.split(',') if p] build_url_re = re.compile(r'.*/job/(?P<job>.*?)/.*(?P<buildno>\d+)/?') def __init__(self): self._instance = None def __getattr__(self, name): self.load() return getattr(self._instance, name) @retry def get_build_from_url(self, url): if not url.startswith(self.baseurl): raise Exception("%s is not on this Jenkins" % url) match = self.build_url_re.match(url) if not match: raise Exception("Failed to parse build URL %s" % url) job_name = match.group('job') job = self.get_job(job_name) buildno = int(match.group('buildno')) try: return Build(url, buildno, job) except requests.exceptions.HTTPError as e: if 404 == e.response.status_code: raise Exception("Build %s not found. Lost ?" % url) raise @retry def load(self): if not self._instance: logger.info("Connecting to Jenkins %s", SETTINGS.JENKINS_URL) self._instance = Jenkins(SETTINGS.JENKINS_URL) @retry def list_projects(self): """List github projects tested on this jenkins. Mine jobs configs to find github remote URL. Attach each job to the corresponding project. """ projects = {} if not SETTINGS.GHP_JOBS_AUTO and not self.jobs_filter: logger.warn("Use GHP_JOBS env var to list jobs to managed") return [] for name, job in self.get_jobs(): if not match(name, self.jobs_filter): logger.debug("Skipping %s", name) continue job = Job.factory(job) if SETTINGS.GHP_JOBS_AUTO and job.polled_by_jenkins: logger.debug("Skipping %s, polled by Jenkins", name) continue # This option works only with webhook, so we can safely use it to # mark a job for jenkins-ghp. if SETTINGS.GHP_JOBS_AUTO and not job.push_trigger: logger.debug("Skipping %s, trigger on push disabled", name) continue job_projects = [x for x in job.get_projects()] if not job_projects: logger.debug("Skipping %s, no GitHub project to poll", name) continue for project in job_projects: logger.info("Managing %s", name) project = projects.setdefault(str(project), project) project.jobs.append(job) repositories = filter(None, SETTINGS.GHP_REPOSITORIES.split(' ')) for entry in repositories: project, branches = entry.split(':') owner, repository = project.split('/') project = projects.setdefault( project, Project(owner, repository) ) project.branches_settings = [ 'refs/heads/' + b for b in branches.split(',') if b ] return sorted(projects.values(), key=str) @retry def is_queue_empty(self): return len(self.get_queue().keys()) == 0 @retry def create_job(self, job_spec): try: api_instance = self._instance.get_job(job_spec.name) except UnknownJob: env = jinja2.Environment( loader=jinja2.FileSystemLoader( os.path.join(os.path.dirname(__file__), 'jobs') ) ) template = env.get_template('freestyle.xml') config = template.render( name=job_spec.name, assigned_node=SETTINGS.GHP_JOBS_NODE, command=SETTINGS.GHP_JOBS_COMMAND, owner=job_spec.project.owner, repository=job_spec.project.repository, credentials=SETTINGS.GHP_JOBS_CREDENTIALS, publish=( not SETTINGS.GHP_DRY_RUN and not SETTINGS.GHP_GITHUB_RO ), ) if SETTINGS.GHP_DRY_RUN: logger.info("Would create new Jenkins job %s", job_spec) return None api_instance = self._instance.create_job(job_spec.name, config) logger.info("Created new Jenkins job %s", job_spec.name) else: logger.debug("Not updating job %s from Jenkins", job_spec.name) job = Job.factory(api_instance) job_spec.project.jobs.append(job) return job
from __future__ import print_function import logging logging.basicConfig() from jenkinsapi.jenkins import Jenkins from pkg_resources import resource_string J = Jenkins('http://localhost:8080') jobName = 'foo_job2' xml = resource_string('examples', 'addjob.xml') print(xml) j = J.create_job(jobname=jobName, config=xml) j2 = J[jobName] print(j) # Delete job J.delete_job(jobName)
import sys, os if __name__ == '__main__': if (len(sys.argv) < 4): # python $REPO_HOME/scripts/makejob.py "$StacksetType" "$CageName" print "Usage: python makejob.py <host> <stackset type> <cagename>" exit(1) jenkins_url = sys.argv[1] stackset_type = sys.argv[2] # print "SST "+stackset_type cage_name = sys.argv[3] # print "Cage "+cage_name path = os.environ['JENKINS_HOME'] with open (path+"/workspace/CheckoutTheGitRepo/jenkins/jobs/"+stackset_type+"/config.xml", "r") as myfile: xml=myfile.read() # # fixup job template # s = Template(xml) job_def = s.substitute(cage_name=cage_name, stackset_type=stackset_type) api = Jenkins(jenkins_url) project_name = "Create a \""+stackset_type+"\" in \""+cage_name+"\" cage" print "Creating project '"+project_name+"'" job = api.create_job(project_name, job_def) view = api.views["StackSets"] if view is None: api.views.create("StackSets") view.add_job(project_name, job) print("Project created - "+job.name+" and added to the 'StackSets' view.")
def server_upload_jobs(args, global_config, opts): ''' Uploads jobs found in a directory directly to jenkins. The jobs should be defined as with a "config.xml" file per job, while the directory containing the "config.xml" file will be used as the name of the job: source-dir /job-name1 /config.xml /job-name2 /config.xml Executing "cit server_upload_jobs source-dir" will upload "job-1" and "job-2" to jenkins, creating or updating them. ''' if not args: print >> sys.stderr, "error: Must pass a directory name" return 2 directory = args[0] if not os.path.exists(directory): print >> sys.stderr, 'error: Directory "%s" does not exist' % directory return 2 jenkins_url = global_config['jenkins']['url'] jenkins = Jenkins(jenkins_url) search_pattern = None local_jobs = [] for dir_name in glob.glob(directory + '/*'): # Ignore all files if not os.path.isdir(dir_name): continue job_info = JobInfo(dir_name) if job_info.config_filename is None: print 'Missing config.xml file from %r' % dir_name continue if opts.reindex: if search_pattern is None: search_pattern = job_info.SearchPattern() elif search_pattern != job_info.SearchPattern(): raise ValueError('Bad job names pattern: %r != %r' % (search_pattern, job_info.SearchPattern())) job_info.update = jenkins.has_job(job_info.name) local_jobs.append(job_info) rename_jobs = {} delete_jobs = [] if opts.reindex: remote_jobs = get_remote_job_infos(search_pattern, global_config, jenkins=jenkins) remote_basenames = dict((ji.BaseName(), ji) for ji in remote_jobs) for job_info in local_jobs: base_name = job_info.BaseName() remote_job = remote_basenames.pop(base_name, None) if remote_job is not None and remote_job.name != job_info.name: rename_jobs[job_info.name] = remote_job.name delete_jobs = [ji.name for ji in remote_basenames.itervalues()] for job_info in local_jobs: if job_info.name in rename_jobs: print 'Renaming %r -> %r' % (rename_jobs[job_info.name], job_info.name) elif job_info.update: print 'Updating %r' % job_info.name else: print 'Creating %r' % job_info.name for job_name in delete_jobs: print print 'Deleting %r' % job_name print if len(local_jobs) > 0: ans = raw_input('Update jobs (y|*n): ') if ans.startswith('y'): for job_info in local_jobs: config_xml = file(job_info.config_filename).read() if job_info.name in rename_jobs: remote_name = rename_jobs[job_info.name] print '\tUpdating job' job = jenkins.get_job(remote_job.name) job.update_config(config_xml) print 'Renaming %r -> %r' % (remote_name, job_info.name) jenkins.rename_job(remote_name, job_info.name) else: if job_info.update: print 'Updating %r' % job_info.name job = jenkins.get_job(job_info.name) job.update_config(config_xml) else: print 'Creating %r' % job_info.name job = jenkins.create_job(job_info.name, config_xml) for job_name in delete_jobs: print 'Deleting %r' % job_name job = jenkins.delete_job(job_name)
dst_view_url = 'http://buildserver:8080/hudson/view/DBCI/view/Trunk-new' api = Jenkins(URL, LOGIN, API_KEY) view_src = api.get_view_by_url(src_view_url) view_dst = api.get_view_by_url(dst_view_url) for job_name, job in view_src.items(): exclude_job = False if len(exclude_jobs_name_contains) > 0: for job_name_substr in exclude_jobs_name_contains: if job_name_substr in job_name: exclude_job = True if exclude_job: log.debug('skipping job: %s' % job_name) continue job = api.get_job(job_name) job_config = job.get_config() new_job_config = replace(job_config, replacements) new_job_name = make_job_name(job_name) log.info('new job name: %s, old: %s' % (new_job_name, job_name)) new_job = api.create_job(new_job_name, new_job_config) #new_job.disable() view_dst.add_job(new_job_name) log.info('%s job added to view: %s' % (new_job_name, view_dst))
logger.error('View %s was not created' % test_view_name) else: logger.info('View %s has been created: %s' % (new_view.name, new_view.baseurl)) else: logger.info('View %s already exists' % test_view_name) # No error is raised if view already exists logger.info('Attempting to create view that already exists') my_view = api.views.create(test_view_name) logger.info('Create job and assign it to a view') job_name = 'foo_job2' xml = resource_string('examples', 'addjob.xml') my_job = api.create_job(jobname=job_name, xml=xml) # add_job supports two parameters: job_name and job object # passing job object will remove verification calls to Jenkins my_view.add_job(job_name, my_job) assert len(my_view) == 1 logger.info('Attempting to delete view that already exists') del api.views[test_view_name] if test_view_name in api.views: logger.error('View was not deleted') else: logger.info('View has been deleted') # No error will be raised when attempting to remove non-existing view
logger.error('View %s was not created', test_view_name) else: logger.info('View %s has been created: %s', new_view.name, new_view.baseurl) else: logger.info('View %s already exists', test_view_name) # No error is raised if view already exists logger.info('Attempting to create view that already exists') my_view = jenkins.views.create(test_view_name) logger.info('Create job and assign it to a view') job_name = 'foo_job2' xml = resource_string('examples', 'addjob.xml') my_job = jenkins.create_job(jobname=job_name, xml=xml) # add_job supports two parameters: job_name and job object # passing job object will remove verification calls to Jenkins my_view.add_job(job_name, my_job) assert len(my_view) == 1 logger.info('Attempting to delete view that already exists') del jenkins.views[test_view_name] if test_view_name in jenkins.views: logger.error('View was not deleted') else: logger.info('View has been deleted') # No error will be raised when attempting to remove non-existing view
J = Jenkins('http://localhost:8080') print(J.items()) j = J.get_job("foo") b = j.get_last_build() print(b) mjn = b.get_master_job_name() print(mjn) EMPTY_JOB_CONFIG = '''\ <?xml version='1.0' encoding='UTF-8'?> <project> <actions/> <description></description> <keepDependencies>false</keepDependencies> <properties/> <scm class="hudson.scm.NullSCM"/> <canRoam>true</canRoam> <disabled>false</disabled> <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding> <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding> <triggers class="vector"/> <concurrentBuild>false</concurrentBuild> <builders/> <publishers/> <buildWrappers/> </project> ''' new_job = J.create_job(jobname='foo_job', xml=EMPTY_JOB_CONFIG)
<keepDependencies>false</keepDependencies> <properties/> <scm class="hudson.scm.NullSCM"/> <canRoam>true</canRoam> <disabled>false</disabled> <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding> <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding> <triggers class="vector"/> <concurrentBuild>false</concurrentBuild> <builders/> <publishers/> <buildWrappers/> </project> ''' jobname = 'foo_job' new_job = J.create_job(jobname, EMPTY_JOB_CONFIG) new_conf = new_job.get_config() root = et.fromstring(new_conf.strip()) builders = root.find('builders') shell = et.SubElement(builders, 'hudson.tasks.Shell') command = et.SubElement(shell, 'command') command.text = "ls" print(et.tostring(root)) J[jobname].update_config(et.tostring(root)) # J.delete_job(jobname)
def configure_master(settings, docker_url, cert_path) -> bool: print("Setting up docker") docker = utils.setup_docker_client(docker_url, cert_path) containers = docker.containers.list(filters={"name": MASTER_IMAGE}) if len(containers) > 0: container = containers[0] print("Finding IP of container...") ip = utils.get_ip(container, docker, settings) while len(ip) == 0: ip = utils.get_ip(container, docker, settings) container.reload() jenkins_url = "http://{ip}:8080".format(ip=ip) while True: try: jenkins = Jenkins(jenkins_url) except: print("Waiting for jenkins to start...") time.sleep(5) else: break creds = jenkins.credentials print("Storing container credentials") env = govc.build_env(settings) env = utils.populate_env(env, container) env["GOVC_GUEST_LOGIN"] = container.id env["GOVC_VM"] = container.name + "-" + container.id[:12] files = os.listdir(cert_path) files = [os.path.join(cert_path, file) for file in files] destination = "/var/jenkins_home/docker_certs" govc.run(settings.gopath, env, ["guest.mkdir", destination]) govc.upload(settings.gopath, env, destination, files) with open("jenkins-ssh-keys/jenkins_ssh") as f: private_key = f.read() cred_dict = { 'description': utils.CREDS_DESCRIPTION, 'userName': '******', 'passphrase': '', 'private_key': private_key } if utils.CREDS_DESCRIPTION in creds: print("Deleting existing credentials.") del creds[utils.CREDS_DESCRIPTION] print("Uploading new credentials") creds[utils.CREDS_DESCRIPTION] = SSHKeyCredential(cred_dict) esx_settings = settings.integration_esx_settings vch_settings = populate_vch_template_settings(settings) if not populate_integration_esx_settings(esx_settings): return False xml = config_template_integration.format(**esx_settings) if INTEGRATION_JOB_NAME in jenkins: print("Updating integration job") job = jenkins[INTEGRATION_JOB_NAME] job.update_config(xml) else: print("Creating integration job") job = jenkins.create_job(jobname=INTEGRATION_JOB_NAME, xml=xml) pprint(job) xml = config_template_vch.format(**vch_settings) if VCH_JOB_NAME in jenkins: print("Updating vch job") job = jenkins[VCH_JOB_NAME] job.update_config(xml) else: print("Creating vch job") job = jenkins.create_job(jobname=VCH_JOB_NAME, xml=xml) pprint(job) return True else: print("Failed to find the container to configure.") return False
class JenkinsMaster(object): def __init__(self): self.args = self._parse_args() level = ["DEBUG", "INFO", "WARN", "ERROR"][min(3, self.args.debug)] logging.basicConfig(level=getattr(logging, level)) self.log = logging.getLogger("app") self.config = ordered_load(open(self.args.config)) self.basedir = os.path.dirname(self.args.config) requester = Requester(ssl_verify=False, baseurl=self.args.server) self.jenkins = Jenkins(self.args.server, requester=requester) def _push_job(self, name, xml): if name in self.jenkins.jobs: print "Update job: %s" % name job = self.jenkins.jobs[name].update_config(xml) assert not job, job else: print "Create job: %s" % name job = self.jenkins.create_job(name, xml) assert job is not None, job def _push_nested_view(self, name, subviews): if name in self.jenkins.views: print "Delete root view: %s" % name del (self.jenkins.views[name]) print "Create root view: %s" % name root = self.jenkins.views.create(name, Views.NESTED_VIEW) assert root is not None, root for view, jobs in subviews.iteritems(): print " Create nested view: %s" % view view = root.views.create(view) assert view is not None, view for job in jobs: print " Add job: %s" % job assert view.add_job(job) def _pull_jobs(self, location): xmls = sorted(glob.glob(os.path.join(os.path.abspath(location), "*.xml"))) jobs = [os.path.basename(_)[:-4] for _ in xmls] remote_all = self.jenkins.jobs.keys() for name, xml in izip(jobs, xmls): if name in remote_all: job = self.jenkins.jobs[name] assert job is not None, job print "Job %s updated" % name open(xml, "w").write(job.get_config()) else: print "Job %s removed" % name os.remove(xml) def _parse_args(self): parser = ArgumentParser(description="Jenkins master to manage your " "Jenkins job/views") parser.add_argument("-d", "--debug", action="count", default=0, help="Set the level of logging") parser.add_argument( "-s", "--server", help="Set the jenkins server " "address [http://localhost:8080]", default="http://localhost:8080", ) parser.add_argument("config", help="Set the config file location " "[./variants.yaml]", default="variants.yaml") return parser.parse_args() def run(self): def basename(job): return os.path.basename(job)[:-4] if raw_input("Pull jobs first? [no]"): self.pull_jobs() self.log.info("-" * 80) views = self.update_all_jobs() self.compare_jobs() self.log.info("-" * 80) if raw_input("Push changes? [no]"): changes = self.push_jobs() removed_jobs = [ basename(job) for job in glob.glob(os.path.join(self.basedir, ".jobs", "*")) if not os.path.exists(os.path.join(self.basedir, "jobs", basename(job) + ".xml")) ] if removed_jobs and raw_input("Remove deleted jobs? [no]"): changes += self.push_remove_jobs(removed_jobs) self.log.info("-" * 80) view = self.config["view"] if changes and raw_input("Update views? [no]"): self.push_view(view, views) else: self.log.debug("Remote: view %s unchanged" % view) def compare_jobs(self): orig = os.path.join(self.basedir, ".jobs") new = os.path.join(self.basedir, "jobs") os.system("meld %s %s" % (orig, new)) def pull_jobs(self): self._pull_jobs(os.path.join(self.basedir, ".jobs")) def update_all_jobs(self): per_view_jobs = OrderedDict() # Stores jobs for given variant # Remove the old job xmls for name in glob.glob(os.path.join(self.basedir, "jobs", "*.xml")): os.remove(name) for view, params in self.config["views"].iteritems(): if "__LONG_NAME__" in params: view_name = params["__LONG_NAME__"] else: view_name = view # Jobs from views if "__EXTENDS__" in params: # recursively extend values params = self._extends(self.config["views"], params) per_view_jobs[view_name] = self._update_jobs(view, params) # Extra jobs return per_view_jobs def _update_jobs(self, view, params): self.log.debug(" Processing view: %s", view) jobs = [] for job, job_params in params.get("JOBS", {}).iteritems(): self.log.debug(" Processing job: %s", job) if job in self.config["templates"]: if job_params: template_params = self.config["templates"][job].copy() template_params.update(job_params) job_params = template_params else: job_params = self.config["templates"][job] template = os.path.join(self.basedir, "templates", "jobs", "%s.tpl" % job_params["__TEMPLATE__"]) content = open(template).read() else: template = os.path.join(self.basedir, "templates", "jobs", "%s.tpl" % job) content = open(template).read() content = self._process_job(content, params, job_params) open(os.path.join(self.basedir, "jobs", "%s_%s.xml" % (job, view)), "w").write(content) jobs.append("%s_%s" % (job, view)) return jobs def _process_job(self, content, params, job_params): def machines(machines): return ( "<allowedSlaves>\n" " <string>%s</string>\n" "</allowedSlaves>\n" "<defaultSlaves>\n" " <string>%s</string>\n" "</defaultSlaves>" % ("</string>\n <string>".join(machines), machines[0]) ) if job_params is None: job_params = {} # First update MACHINES content = self._sub(content, "MACHINES", machines(params["MACHINES"])) # Job params for key, value in job_params.iteritems(): content = self._sub(content, key, value) for key, value in params.get("__SHARED__", {}).iteritems(): if key in job_params: continue content = self._sub(content, key, value, False) # Remove unused templates content = self._sub(content, r".*", "", False) return content def _sub(self, string, key, value, mandatory=True): if key[:2] == "__" and key[-2:] == "__": return string if isinstance(value, dict) and "__DATA__" in value: value = self.config["data"][value["__DATA__"]] string, count = re.subn("<!--TEMPLATE__%s__TEMPLATE-->" % key, value, string) if mandatory and not count: raise ValueError("No TEMPLATE__%s__TEMPLATE found in template." % key) return string def _extends(self, root, params): def recursive_default(params, _params): for key, value in _params.iteritems(): if key not in params: params[key] = value elif isinstance(value, dict): recursive_default(params[key], _params[key]) _params = root[params["__EXTENDS__"]] if "__EXTENDS__" in _params: _params = self._extends(root, _params) recursive_default(params, _params) return params def push_jobs(self): # Push all created jobs changes = 0 for xml_path in glob.glob(os.path.join(self.basedir, "jobs", "*.xml")): name = os.path.basename(xml_path)[:-4] # remove path + .xml _xml_path = os.path.join(self.basedir, ".jobs", "%s.xml" % name) if os.path.exists(_xml_path) and ( md5(open(xml_path).read()).hexdigest() == md5(open(_xml_path).read()).hexdigest() ): self.log.debug("Remote: job %s unchanged", name) continue self._push_job(name, open(xml_path).read()) shutil.copy2(xml_path, _xml_path) changes += 1 return changes def push_view(self, view, views): # Recreate the view and subviews self._push_nested_view(view, views) def push_remove_jobs(self, jobs): changes = 0 for name in jobs: self.log.debug("Remote: deleting job %s", name) del (self.jenkins.jobs[name]) os.remove(os.path.join(self.basedir, ".jobs", "%s.xml" % name)) changes += 1 return changes
'transfers'][ 'jenkins.plugins.publish__over__ssh.BapSshTransfer'][ 'sourceFiles'] = kwargs['sourcefiles'] # execcommand normal_config['maven2-moduleset']['postbuilders'][ 'jenkins.plugins.publish__over__ssh.BapSshBuilderPlugin']['delegate'][ 'delegate']['publishers'][ 'jenkins.plugins.publish__over__ssh.BapSshPublisher'][ 'transfers'][ 'jenkins.plugins.publish__over__ssh.BapSshTransfer'][ 'execCommand'] = kwargs['execcommand'] xml = dicttoxml.dicttoxml(normal_config).decode(encoding='utf-8') # print(type(xml)) print(xml) return xml args = { 'description': '测试下这个问题', 'git_url': 'https://github.com/linweili0615/testsearch.git', 'git_branches': '*/master', 'ssh': 'test1234', 'remotedirectory': 'source/test', 'sourcefiles': '**/target/demo-2.0.jar', 'execcommand': 'sh /usr/local/software/test3.sh test demo-1.0.jar 9301' } config_xml = get_normal_config(**args) jk.create_job('test999', xml=config_xml)