Add option to make test output file layout match Jenkins

Before, `jenkins-job-builder test -o outdir` would write

    outdir/job_name

With the new option `--config-xml`, it writes

    outdir/job_name/config.xml

to match the layout that Jenkins uses internally.  This is more useful
for diffing against existing Jenkins installations or uploading job
definitions by other means.

Also, it seems better to give the output files an .xml extension.

Change-Id: I78fc7aff531925ee071b8e19f40f766b4af0b5ad
This commit is contained in:
Peter Eisentraut 2015-11-21 11:19:10 -05:00 committed by Darragh Bailey
parent 3799ed2c98
commit 919052714c
4 changed files with 70 additions and 6 deletions

View File

@ -153,6 +153,14 @@ You can also pass JJB a directory containing multiple job definition files::
which will write XML files to the output directory for all of the jobs which will write XML files to the output directory for all of the jobs
defined in the defs directory. defined in the defs directory.
If you run::
jenkins-jobs test /path/to/defs -o /path/to/output --config-xml
the output directory will contain config.xml files similar to the
internal storage format of Jenkins. This might allow you to more
easily compare the output to an existing Jenkins installation.
.. _updating-jobs: .. _updating-jobs:
Updating Jobs Updating Jobs

View File

@ -194,7 +194,8 @@ class JenkinsManager(object):
logger.debug("'{0}' has not changed".format(job.name)) logger.debug("'{0}' has not changed".format(job.name))
return changed return changed
def update_jobs(self, xml_jobs, output=None, n_workers=None): def update_jobs(self, xml_jobs, output=None, n_workers=None,
config_xml=False):
orig = time.time() orig = time.time()
logger.info("Number of jobs generated: %d", len(xml_jobs)) logger.info("Number of jobs generated: %d", len(xml_jobs))
@ -230,7 +231,17 @@ class JenkinsManager(object):
raise raise
continue continue
output_fn = os.path.join(output, job.name) if config_xml:
output_dir = os.path.join(output, job.name)
logger.info("Creating directory %s" % output_dir)
try:
os.makedirs(output_dir)
except OSError:
if not os.path.isdir(output_dir):
raise
output_fn = os.path.join(output_dir, 'config.xml')
else:
output_fn = os.path.join(output, job.name)
logger.debug("Writing XML to '{0}'".format(output_fn)) logger.debug("Writing XML to '{0}'".format(output_fn))
with io.open(output_fn, 'w', encoding='utf-8') as f: with io.open(output_fn, 'w', encoding='utf-8') as f:
f.write(job.output().decode('utf-8')) f.write(job.output().decode('utf-8'))
@ -344,7 +355,8 @@ class JenkinsManager(object):
logger.info("Creating jenkins view {0}".format(view_name)) logger.info("Creating jenkins view {0}".format(view_name))
self.jenkins.create_view(view_name, xml) self.jenkins.create_view(view_name, xml)
def update_views(self, xml_views, output=None, n_workers=None): def update_views(self, xml_views, output=None, n_workers=None,
config_xml=False):
orig = time.time() orig = time.time()
logger.info("Number of views generated: %d", len(xml_views)) logger.info("Number of views generated: %d", len(xml_views))
@ -371,7 +383,17 @@ class JenkinsManager(object):
raise raise
continue continue
output_fn = os.path.join(output, view.name) if config_xml:
output_dir = os.path.join(output, view.name)
logger.info("Creating directory %s" % output_dir)
try:
os.makedirs(output_dir)
except OSError:
if not os.path.isdir(output_dir):
raise
output_fn = os.path.join(output_dir, 'config.xml')
else:
output_fn = os.path.join(output, view.name)
logger.debug("Writing XML to '{0}'".format(output_fn)) logger.debug("Writing XML to '{0}'".format(output_fn))
with io.open(output_fn, 'w', encoding='utf-8') as f: with io.open(output_fn, 'w', encoding='utf-8') as f:
f.write(view.output().decode('utf-8')) f.write(view.output().decode('utf-8'))

View File

@ -32,6 +32,12 @@ class TestSubCommand(update.UpdateSubCommand):
self.parse_arg_path(test) self.parse_arg_path(test)
self.parse_arg_names(test) self.parse_arg_names(test)
test.add_argument(
'--config-xml',
action='store_true',
dest='config_xml',
default=False,
help='use alternative output file layout using config.xml files')
test.add_argument( test.add_argument(
'-p', '-p',
dest='plugins_info_path', dest='plugins_info_path',
@ -48,5 +54,7 @@ class TestSubCommand(update.UpdateSubCommand):
builder, xml_jobs, xml_views = self._generate_xmljobs( builder, xml_jobs, xml_views = self._generate_xmljobs(
options, jjb_config) options, jjb_config)
builder.update_jobs(xml_jobs, output=options.output_dir, n_workers=1) builder.update_jobs(xml_jobs, output=options.output_dir, n_workers=1,
builder.update_views(xml_views, output=options.output_dir, n_workers=1) config_xml=options.config_xml)
builder.update_views(xml_views, output=options.output_dir, n_workers=1,
config_xml=options.config_xml)

View File

@ -74,6 +74,32 @@ class TestTests(CmdTestsBase):
'r', encoding='utf-8').read() 'r', encoding='utf-8').read()
self.assertEqual(console_out.getvalue().decode('utf-8'), xml_content) self.assertEqual(console_out.getvalue().decode('utf-8'), xml_content)
def test_output_dir(self):
"""
Run test mode with output to directory and verify that output files are
generated.
"""
tmpdir = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, tmpdir)
args = ['test', os.path.join(self.fixtures_path, 'cmd-001.yaml'),
'-o', tmpdir]
self.execute_jenkins_jobs_with_args(args)
self.expectThat(os.path.join(tmpdir, 'foo-job'),
testtools.matchers.FileExists())
def test_output_dir_config_xml(self):
"""
Run test mode with output to directory in "config.xml" mode and verify
that output files are generated.
"""
tmpdir = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, tmpdir)
args = ['test', os.path.join(self.fixtures_path, 'cmd-001.yaml'),
'-o', tmpdir, '--config-xml']
self.execute_jenkins_jobs_with_args(args)
self.expectThat(os.path.join(tmpdir, 'foo-job', 'config.xml'),
testtools.matchers.FileExists())
def test_stream_input_output_no_encoding_exceed_recursion(self): def test_stream_input_output_no_encoding_exceed_recursion(self):
""" """
Test that we don't have issues processing large number of jobs and Test that we don't have issues processing large number of jobs and