Auto-generated output from python-black

Please review the following patch containing the code changes in
the repo. This patch is a transition patch and is the auto-generated
output of the python-black tool.

Change-Id: I2d2de71da8a105fb62b561899ae78441ddab4032
Signed-off-by: Thanh Ha <zxiiro@gmail.com>
This commit is contained in:
Thanh Ha
2019-08-23 09:14:39 -04:00
committed by Sorin Sbarnea
parent ead185134d
commit 4d90c187a9
89 changed files with 10446 additions and 9903 deletions

View File

@@ -18,8 +18,8 @@ from jenkins_jobs.version import version_info as jenkins_jobs_version
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('../..'))
sys.path.insert(0, os.path.abspath('../../jenkins_jobs/modules'))
sys.path.insert(0, os.path.abspath("../.."))
sys.path.insert(0, os.path.abspath("../../jenkins_jobs/modules"))
# -- General configuration ----------------------------------------------------
@@ -28,25 +28,30 @@ sys.path.insert(0, os.path.abspath('../../jenkins_jobs/modules'))
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.coverage',
'jenkins_jobs.sphinx.yaml', 'sphinxcontrib.programoutput',
'sphinx.ext.extlinks', 'sphinx.ext.doctest']
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.coverage",
"jenkins_jobs.sphinx.yaml",
"sphinxcontrib.programoutput",
"sphinx.ext.extlinks",
"sphinx.ext.doctest",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
# The suffix of source filenames.
source_suffix = '.rst'
source_suffix = ".rst"
# The encoding of source files.
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# General information about the project.
project = u'Jenkins Job Builder'
copyright = u'2012, Jenkins Job Builder Maintainers'
project = u"Jenkins Job Builder"
copyright = u"2012, Jenkins Job Builder Maintainers"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -86,7 +91,7 @@ exclude_patterns = []
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
@@ -96,7 +101,7 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'default'
html_theme = "default"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@@ -169,7 +174,7 @@ html_theme = 'default'
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'JenkinsJobBuilderdoc'
htmlhelp_basename = "JenkinsJobBuilderdoc"
# -- Options for LaTeX output -------------------------------------------------
@@ -177,10 +182,8 @@ htmlhelp_basename = 'JenkinsJobBuilderdoc'
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
# 'preamble': '',
}
@@ -189,8 +192,13 @@ latex_elements = {
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index', 'JenkinsJobBuilder.tex', u'Jenkins Job Builder Documentation',
u'Jenkins Job Builder Maintainers', 'manual'),
(
"index",
"JenkinsJobBuilder.tex",
u"Jenkins Job Builder Documentation",
u"Jenkins Job Builder Maintainers",
"manual",
)
]
# The name of an image file (relative to this directory) to place at the top of
@@ -225,8 +233,13 @@ linkcheck_timeout = 15
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'jenkins-jobs', u'Jenkins Job Builder Documentation',
[u'Jenkins Job Builder Maintainers'], 1)
(
"index",
"jenkins-jobs",
u"Jenkins Job Builder Documentation",
[u"Jenkins Job Builder Maintainers"],
1,
)
]
# If true, show URL addresses after external links.
@@ -239,10 +252,15 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'JenkinsJobBuilder', u'Jenkins Job Builder Documentation',
u'Jenkins Job Builder Maintainers',
'JenkinsJobBuilder', 'One line description of project.',
'Miscellaneous'),
(
"index",
"JenkinsJobBuilder",
u"Jenkins Job Builder Documentation",
u"Jenkins Job Builder Maintainers",
"JenkinsJobBuilder",
"One line description of project.",
"Miscellaneous",
)
]
# Documents to append as an appendix to all manuals.
@@ -254,6 +272,7 @@ texinfo_documents = [
# How to display URL addresses: 'footnote', 'no', or 'inline'.
# texinfo_show_urls = 'footnote'
extlinks = {'jenkins-wiki': ('https://wiki.jenkins.io/display/JENKINS/%s',
None),
'jenkins-plugins': ('https://plugins.jenkins.io/%s', None)}
extlinks = {
"jenkins-wiki": ("https://wiki.jenkins.io/display/JENKINS/%s", None),
"jenkins-plugins": ("https://plugins.jenkins.io/%s", None),
}

View File

@@ -42,9 +42,9 @@ def getchunk(item):
# Subtract the matched portion from the original string
# if there was a match, otherwise set it to ""
item = (item[itemchunk.end():] if itemchunk else "")
item = item[itemchunk.end() :] if itemchunk else ""
# Don't return the match object, just the text
itemchunk = (itemchunk.group() if itemchunk else "")
itemchunk = itemchunk.group() if itemchunk else ""
return (itemchunk, item)
@@ -54,28 +54,28 @@ def cmp(a, b):
def alphanum(a, b):
a = a.name if hasattr(a, 'name') else str(a)
b = b.name if hasattr(b, 'name') else str(b)
a = a.name if hasattr(a, "name") else str(a)
b = b.name if hasattr(b, "name") else str(b)
n = 0
while (n == 0):
while n == 0:
# Get a chunk and the original string with the chunk subtracted
(ac, a) = getchunk(a)
(bc, b) = getchunk(b)
# Both items contain only letters
if (re_letters.match(ac) and re_letters.match(bc)):
if re_letters.match(ac) and re_letters.match(bc):
n = cmp(ac, bc)
else:
# Both items contain only numbers
if (re_numbers.match(ac) and re_numbers.match(bc)):
if re_numbers.match(ac) and re_numbers.match(bc):
n = cmp(int(ac), int(bc))
# item has letters and one item has numbers, or one item is empty
else:
n = cmp(ac, bc)
# Prevent deadlocks
if (n == 0):
if n == 0:
n = 1
return n
@@ -105,5 +105,5 @@ class AlphanumSort(object):
if __name__ == "__main__":
mylist = ['a2', 'a1', 'a10', 'a']
assert sorted(mylist, key=AlphanumSort) == ['a', 'a1', 'a2', 'a10']
mylist = ["a2", "a1", "a10", "a"]
assert sorted(mylist, key=AlphanumSort) == ["a", "a1", "a2", "a10"]

View File

@@ -34,9 +34,7 @@ from jenkins_jobs.constants import MAGIC_MANAGE_STRING
from jenkins_jobs.parallel import concurrent
from jenkins_jobs import utils
__all__ = [
"JenkinsManager"
]
__all__ = ["JenkinsManager"]
logger = logging.getLogger(__name__)
@@ -44,22 +42,22 @@ _DEFAULT_TIMEOUT = object()
class JenkinsManager(object):
def __init__(self, jjb_config):
url = jjb_config.jenkins['url']
user = jjb_config.jenkins['user']
password = jjb_config.jenkins['password']
timeout = jjb_config.jenkins['timeout']
url = jjb_config.jenkins["url"]
user = jjb_config.jenkins["user"]
password = jjb_config.jenkins["password"]
timeout = jjb_config.jenkins["timeout"]
if timeout != _DEFAULT_TIMEOUT:
self.jenkins = jenkins.Jenkins(url, user, password, timeout)
else:
self.jenkins = jenkins.Jenkins(url, user, password)
self.cache = JobCache(jjb_config.jenkins['url'],
flush=jjb_config.builder['flush_cache'])
self.cache = JobCache(
jjb_config.jenkins["url"], flush=jjb_config.builder["flush_cache"]
)
self._plugins_list = jjb_config.builder['plugins_info']
self._plugins_list = jjb_config.builder["plugins_info"]
self._jobs = None
self._job_list = None
self._views = None
@@ -69,16 +67,15 @@ class JenkinsManager(object):
def _setup_output(self, output, item, config_xml=False):
output_dir = output
output_fn = os.path.join(output, item)
if '/' in item:
if "/" in item:
# in item folder
output_fn = os.path.join(output, os.path.normpath(item))
output_dir = os.path.dirname(output_fn)
# if in a folder, re-adding name to the directory here
if config_xml:
output_dir = os.path.join(
output_dir, os.path.basename(item))
output_fn = os.path.join(output_dir, 'config.xml')
output_dir = os.path.join(output_dir, os.path.basename(item))
output_fn = os.path.join(output_dir, "config.xml")
if output_dir != output:
logger.debug("Creating directory %s" % output_dir)
@@ -102,36 +99,43 @@ class JenkinsManager(object):
def job_list(self):
if self._job_list is None:
# python-jenkins uses 'fullname' for folder/name combination
self._job_list = set(job['fullname'] for job in self.jobs)
self._job_list = set(job["fullname"] for job in self.jobs)
return self._job_list
def _job_format(self, job_name):
# returns job name or url based on config option
if self._jjb_config.builder['print_job_urls']:
return self._jjb_config.jenkins['url'] + \
'/job/' + quote(
'/job/'.join(job_name.split('/')).encode('utf8')) + '/'
if self._jjb_config.builder["print_job_urls"]:
return (
self._jjb_config.jenkins["url"]
+ "/job/"
+ quote("/job/".join(job_name.split("/")).encode("utf8"))
+ "/"
)
else:
return job_name
def _view_format(self, view_name):
# returns job name or url based on config option
if self._jjb_config.builder['print_job_urls']:
parts = view_name.split('/')
return self._jjb_config.jenkins['url'] + \
''.join(['/job/' + item for item in parts[:-1]]) + \
'/view/' + parts[-1] + '/'
if self._jjb_config.builder["print_job_urls"]:
parts = view_name.split("/")
return (
self._jjb_config.jenkins["url"]
+ "".join(["/job/" + item for item in parts[:-1]])
+ "/view/"
+ parts[-1]
+ "/"
)
else:
return view_name
def update_job(self, job_name, xml):
if self.is_job(job_name):
logger.info("Reconfiguring jenkins job {0}".format(
self._job_format(job_name)))
logger.info(
"Reconfiguring jenkins job {0}".format(self._job_format(job_name))
)
self.jenkins.reconfig_job(job_name, xml)
else:
logger.info("Creating jenkins job {0}".format(
self._job_format(job_name)))
logger.info("Creating jenkins job {0}".format(self._job_format(job_name)))
self.jenkins.create_job(job_name, xml)
def is_job(self, job_name, use_cache=True):
@@ -143,7 +147,7 @@ class JenkinsManager(object):
def get_job_md5(self, job_name):
xml = self.jenkins.get_job_config(job_name)
return hashlib.md5(xml.encode('utf-8')).hexdigest()
return hashlib.md5(xml.encode("utf-8")).hexdigest()
def delete_job(self, job_name):
if self.is_job(job_name):
@@ -162,10 +166,10 @@ class JenkinsManager(object):
logger.warning(
"Unable to retrieve Jenkins Plugin Info from {0},"
" using default empty plugins info list.".format(
self.jenkins.server))
plugins_list = [{'shortName': '',
'version': '',
'longName': ''}]
self.jenkins.server
)
)
plugins_list = [{"shortName": "", "version": "", "longName": ""}]
else:
raise
logger.debug("Jenkins Plugin Info {0}".format(pformat(plugins_list)))
@@ -181,7 +185,7 @@ class JenkinsManager(object):
def is_managed(self, job_name):
xml = self.jenkins.get_job_config(job_name)
try:
out = XML.fromstring(xml.encode('utf-8'))
out = XML.fromstring(xml.encode("utf-8"))
description = out.find(".//description").text
return description.endswith(MAGIC_MANAGE_STRING)
except (TypeError, AttributeError):
@@ -202,18 +206,21 @@ class JenkinsManager(object):
for job in jobs:
# python-jenkins stores the folder and name as 'fullname'
# Check if the job was deleted when his parent folder was deleted
if job['fullname'] not in keep and \
self.is_job(job['fullname'], use_cache=False):
if self.is_managed(job['fullname']):
logger.info("Removing obsolete jenkins job {0}"
.format(job['fullname']))
self.delete_job(job['fullname'])
if job["fullname"] not in keep and self.is_job(
job["fullname"], use_cache=False
):
if self.is_managed(job["fullname"]):
logger.info(
"Removing obsolete jenkins job {0}".format(job["fullname"])
)
self.delete_job(job["fullname"])
deleted_jobs += 1
else:
logger.info("Not deleting unmanaged jenkins job %s",
job['fullname'])
logger.info(
"Not deleting unmanaged jenkins job %s", job["fullname"]
)
else:
logger.debug("Keeping job %s", job['fullname'])
logger.debug("Keeping job %s", job["fullname"])
return deleted_jobs
def delete_jobs(self, jobs):
@@ -221,15 +228,17 @@ class JenkinsManager(object):
logger.info("Removing jenkins job(s): %s" % ", ".join(jobs))
for job in jobs:
self.delete_job(job)
if(self.cache.is_cached(job)):
self.cache.set(job, '')
if self.cache.is_cached(job):
self.cache.set(job, "")
self.cache.save()
def delete_all_jobs(self):
jobs = self.get_jobs()
logger.info("Number of jobs to delete: %d", len(jobs))
script = ('for(job in jenkins.model.Jenkins.theInstance.getAllItems())'
' { job.delete(); }')
script = (
"for(job in jenkins.model.Jenkins.theInstance.getAllItems())"
" { job.delete(); }"
)
self.jenkins.run_script(script)
# Need to clear the JJB cache after deletion
self.cache.clear()
@@ -237,8 +246,9 @@ class JenkinsManager(object):
def changed(self, job):
md5 = job.md5()
changed = (self._jjb_config.builder['ignore_cache'] or
self.cache.has_changed(job.name, md5))
changed = self._jjb_config.builder["ignore_cache"] or self.cache.has_changed(
job.name, md5
)
if not changed:
logger.debug("'{0}' has not changed".format(job.name))
return changed
@@ -249,15 +259,20 @@ class JenkinsManager(object):
logger.debug("'{0}' does not currently exist".format(job.name))
return exists
def update_jobs(self, xml_jobs, output=None, n_workers=None,
existing_only=None, config_xml=False):
def update_jobs(
self,
xml_jobs,
output=None,
n_workers=None,
existing_only=None,
config_xml=False,
):
orig = time.time()
logger.info("Number of jobs generated: %d", len(xml_jobs))
xml_jobs.sort(key=AlphanumSort)
if (output and not hasattr(output, 'write') and
not os.path.isdir(output)):
if output and not hasattr(output, "write") and not os.path.isdir(output):
logger.debug("Creating directory %s" % output)
try:
os.makedirs(output)
@@ -267,11 +282,11 @@ class JenkinsManager(object):
if output:
# ensure only wrapped once
if hasattr(output, 'write'):
if hasattr(output, "write"):
output = utils.wrap_stream(output)
for job in xml_jobs:
if hasattr(output, 'write'):
if hasattr(output, "write"):
# `output` is a file-like object
logger.info("Job name: %s", job.name)
logger.debug("Writing XML to '{0}'".format(output))
@@ -289,39 +304,31 @@ class JenkinsManager(object):
output_fn = self._setup_output(output, job.name, config_xml)
logger.debug("Writing XML to '{0}'".format(output_fn))
with io.open(output_fn, 'w', encoding='utf-8') as f:
f.write(job.output().decode('utf-8'))
with io.open(output_fn, "w", encoding="utf-8") as f:
f.write(job.output().decode("utf-8"))
return xml_jobs, len(xml_jobs)
# Filter out the jobs that did not change
logging.debug('Filtering %d jobs for changed jobs',
len(xml_jobs))
logging.debug("Filtering %d jobs for changed jobs", len(xml_jobs))
step = time.time()
jobs = [job for job in xml_jobs
if self.changed(job)]
logging.debug("Filtered for changed jobs in %ss",
(time.time() - step))
jobs = [job for job in xml_jobs if self.changed(job)]
logging.debug("Filtered for changed jobs in %ss", (time.time() - step))
if existing_only:
# Filter out the jobs not already in the cache
logging.debug('Filtering %d jobs for existing jobs',
len(jobs))
logging.debug("Filtering %d jobs for existing jobs", len(jobs))
step = time.time()
jobs = [job for job in jobs
if self.exists(job)]
logging.debug("Filtered for existing jobs in %ss",
(time.time() - step))
jobs = [job for job in jobs if self.exists(job)]
logging.debug("Filtered for existing jobs in %ss", (time.time() - step))
if not jobs:
return [], 0
# Update the jobs
logging.debug('Updating jobs')
logging.debug("Updating jobs")
step = time.time()
p_params = [{'job': job} for job in jobs]
results = self.parallel_update_job(
n_workers=n_workers,
concurrent=p_params)
p_params = [{"job": job} for job in jobs]
results = self.parallel_update_job(n_workers=n_workers, concurrent=p_params)
logging.debug("Parsing results")
# generalize the result parsing, as a concurrent job always returns a
# list
@@ -336,15 +343,13 @@ class JenkinsManager(object):
self.cache.set(j_name, j_md5)
# write cache to disk
self.cache.save()
logging.debug("Updated %d jobs in %ss",
len(jobs),
time.time() - step)
logging.debug("Updated %d jobs in %ss", len(jobs), time.time() - step)
logging.debug("Total run took %ss", (time.time() - orig))
return jobs, len(jobs)
@concurrent
def parallel_update_job(self, job):
self.update_job(job.name, job.output().decode('utf-8'))
self.update_job(job.name, job.output().decode("utf-8"))
return (job.name, job.md5())
################
@@ -361,7 +366,7 @@ class JenkinsManager(object):
@property
def view_list(self):
if self._view_list is None:
self._view_list = set(view['name'] for view in self.views)
self._view_list = set(view["name"] for view in self.views)
return self._view_list
def get_views(self, cache=True):
@@ -389,7 +394,7 @@ class JenkinsManager(object):
for view in views:
self.delete_view(view)
if self.cache.is_cached(view):
self.cache.set(view, '')
self.cache.set(view, "")
self.cache.save()
def delete_all_views(self):
@@ -399,22 +404,30 @@ class JenkinsManager(object):
views.pop(0)
logger.info("Number of views to delete: %d", len(views))
for view in views:
self.delete_view(view['name'])
self.delete_view(view["name"])
# Need to clear the JJB cache after deletion
self.cache.clear()
def update_view(self, view_name, xml):
if self.is_view(view_name):
logger.info("Reconfiguring jenkins view {0}".format(
self._view_format(view_name)))
logger.info(
"Reconfiguring jenkins view {0}".format(self._view_format(view_name))
)
self.jenkins.reconfig_view(view_name, xml)
else:
logger.info("Creating jenkins view {0}".format(
self._view_format(view_name)))
logger.info(
"Creating jenkins view {0}".format(self._view_format(view_name))
)
self.jenkins.create_view(view_name, xml)
def update_views(self, xml_views, output=None, n_workers=None,
existing_only=None, config_xml=False):
def update_views(
self,
xml_views,
output=None,
n_workers=None,
existing_only=None,
config_xml=False,
):
orig = time.time()
logger.info("Number of views generated: %d", len(xml_views))
@@ -422,11 +435,11 @@ class JenkinsManager(object):
if output:
# ensure only wrapped once
if hasattr(output, 'write'):
if hasattr(output, "write"):
output = utils.wrap_stream(output)
for view in xml_views:
if hasattr(output, 'write'):
if hasattr(output, "write"):
# `output` is a file-like object
logger.info("View name: %s", view.name)
logger.debug("Writing XML to '{0}'".format(output))
@@ -444,39 +457,31 @@ class JenkinsManager(object):
output_fn = self._setup_output(output, view.name, config_xml)
logger.debug("Writing XML to '{0}'".format(output_fn))
with io.open(output_fn, 'w', encoding='utf-8') as f:
f.write(view.output().decode('utf-8'))
with io.open(output_fn, "w", encoding="utf-8") as f:
f.write(view.output().decode("utf-8"))
return xml_views, len(xml_views)
# Filter out the views that did not change
logging.debug('Filtering %d views for changed views',
len(xml_views))
logging.debug("Filtering %d views for changed views", len(xml_views))
step = time.time()
views = [view for view in xml_views
if self.changed(view)]
logging.debug("Filtered for changed views in %ss",
(time.time() - step))
views = [view for view in xml_views if self.changed(view)]
logging.debug("Filtered for changed views in %ss", (time.time() - step))
if existing_only:
# Filter out the jobs not already in the cache
logging.debug('Filtering %d views for existing jobs',
len(views))
logging.debug("Filtering %d views for existing jobs", len(views))
step = time.time()
views = [view for view in views
if self.exists(view)]
logging.debug("Filtered for existing views in %ss",
(time.time() - step))
views = [view for view in views if self.exists(view)]
logging.debug("Filtered for existing views in %ss", (time.time() - step))
if not views:
return [], 0
# Update the views
logging.debug('Updating views')
logging.debug("Updating views")
step = time.time()
p_params = [{'view': view} for view in views]
results = self.parallel_update_view(
n_workers=n_workers,
concurrent=p_params)
p_params = [{"view": view} for view in views]
results = self.parallel_update_view(n_workers=n_workers, concurrent=p_params)
logging.debug("Parsing results")
# generalize the result parsing, as a concurrent view always returns a
# list
@@ -491,13 +496,11 @@ class JenkinsManager(object):
self.cache.set(v_name, v_md5)
# write cache to disk
self.cache.save()
logging.debug("Updated %d views in %ss",
len(views),
time.time() - step)
logging.debug("Updated %d views in %ss", len(views), time.time() - step)
logging.debug("Total run took %ss", (time.time() - orig))
return views, len(views)
@concurrent
def parallel_update_view(self, view):
self.update_view(view.name, view.output().decode('utf-8'))
self.update_view(view.name, view.output().decode("utf-8"))
return (view.name, view.md5())

View File

@@ -43,43 +43,45 @@ class JobCache(object):
def __init__(self, jenkins_url, flush=False):
cache_dir = self.get_cache_dir()
# One cache per remote Jenkins URL:
host_vary = re.sub(r'[^A-Za-z0-9\-\~]', '_', jenkins_url)
host_vary = re.sub(r"[^A-Za-z0-9\-\~]", "_", jenkins_url)
self.cachefilename = os.path.join(
cache_dir, 'cache-host-jobs-' + host_vary + '.yml')
cache_dir, "cache-host-jobs-" + host_vary + ".yml"
)
# generate named lockfile if none exists, and lock it
self._locked = self._lock()
if not self._locked:
raise errors.JenkinsJobsException(
"Unable to lock cache for '%s'" % jenkins_url)
"Unable to lock cache for '%s'" % jenkins_url
)
if flush or not os.path.isfile(self.cachefilename):
self.data = {}
else:
with io.open(self.cachefilename, 'r', encoding='utf-8') as yfile:
with io.open(self.cachefilename, "r", encoding="utf-8") as yfile:
self.data = yaml.load(yfile)
logger.debug("Using cache: '{0}'".format(self.cachefilename))
def _lock(self):
self._fastener = fasteners.InterProcessLock("%s.lock" %
self.cachefilename)
self._fastener = fasteners.InterProcessLock("%s.lock" % self.cachefilename)
return self._fastener.acquire(delay=1, max_delay=2, timeout=60)
def _unlock(self):
if getattr(self, '_locked', False):
if getattr(self, '_fastener', None) is not None:
if getattr(self, "_locked", False):
if getattr(self, "_fastener", None) is not None:
self._fastener.release()
self._locked = None
@staticmethod
def get_cache_dir():
home = os.path.expanduser('~')
if home == '~':
raise OSError('Could not locate home folder')
xdg_cache_home = os.environ.get('XDG_CACHE_HOME') or \
os.path.join(home, '.cache')
path = os.path.join(xdg_cache_home, 'jenkins_jobs')
home = os.path.expanduser("~")
if home == "~":
raise OSError("Could not locate home folder")
xdg_cache_home = os.environ.get("XDG_CACHE_HOME") or os.path.join(
home, ".cache"
)
path = os.path.join(xdg_cache_home, "jenkins_jobs")
if not os.path.isdir(path):
try:
os.makedirs(path)
@@ -111,9 +113,10 @@ class JobCache(object):
# use self references to required modules in case called via __del__
# write to tempfile under same directory and then replace to avoid
# issues around corruption such the process be killed
tfile = self._tempfile.NamedTemporaryFile(dir=self.get_cache_dir(),
delete=False)
tfile.write(self._yaml.dump(self.data).encode('utf-8'))
tfile = self._tempfile.NamedTemporaryFile(
dir=self.get_cache_dir(), delete=False
)
tfile.write(self._yaml.dump(self.data).encode("utf-8"))
# force contents to be synced on disk before overwriting cachefile
tfile.flush()
self._os.fsync(tfile.fileno())
@@ -131,10 +134,12 @@ class JobCache(object):
def __del__(self):
# check we initialized sufficiently in case called
# due to an exception occurring in the __init__
if getattr(self, 'data', None) is not None:
if getattr(self, "data", None) is not None:
try:
self.save()
except Exception as e:
self._logger.error("Failed to write to cache file '%s' on "
"exit: %s" % (self.cachefilename, e))
self._logger.error(
"Failed to write to cache file '%s' on "
"exit: %s" % (self.cachefilename, e)
)
self._unlock()

View File

@@ -31,8 +31,7 @@ logger = logging.getLogger()
def __version__():
return "Jenkins Job Builder version: %s" % \
version.version_info.version_string()
return "Jenkins Job Builder version: %s" % version.version_info.version_string()
class JenkinsJobs(object):
@@ -58,17 +57,17 @@ class JenkinsJobs(object):
self.parser = create_parser()
self.options = self.parser.parse_args(args)
self.jjb_config = JJBConfig(self.options.conf,
config_section=self.options.section,
**kwargs)
self.jjb_config = JJBConfig(
self.options.conf, config_section=self.options.section, **kwargs
)
if not self.options.command:
self.parser.error("Must specify a 'command' to be performed")
if (self.options.log_level is not None):
self.options.log_level = getattr(logging,
self.options.log_level.upper(),
logger.getEffectiveLevel())
if self.options.log_level is not None:
self.options.log_level = getattr(
logging, self.options.log_level.upper(), logger.getEffectiveLevel()
)
logger.setLevel(self.options.log_level)
self._parse_additional()
@@ -84,50 +83,58 @@ class JenkinsJobs(object):
def _parse_additional(self):
self._set_config(self.jjb_config.builder, 'ignore_cache')
self._set_config(self.jjb_config.builder, 'flush_cache')
self._set_config(self.jjb_config.builder, 'update')
self._set_config(self.jjb_config.yamlparser, 'allow_empty_variables')
self._set_config(self.jjb_config.jenkins, 'section')
self._set_config(self.jjb_config.jenkins, 'user')
self._set_config(self.jjb_config.jenkins, 'password')
self._set_config(self.jjb_config.builder, "ignore_cache")
self._set_config(self.jjb_config.builder, "flush_cache")
self._set_config(self.jjb_config.builder, "update")
self._set_config(self.jjb_config.yamlparser, "allow_empty_variables")
self._set_config(self.jjb_config.jenkins, "section")
self._set_config(self.jjb_config.jenkins, "user")
self._set_config(self.jjb_config.jenkins, "password")
# Note: CLI options override config file options.
if getattr(self.options, 'update', None) is None:
self.options.update = self.jjb_config.builder.get('update')
if getattr(self.options, "update", None) is None:
self.options.update = self.jjb_config.builder.get("update")
if self.options.update is None:
self.options.update = 'all'
self.options.update = "all"
if getattr(self.options, 'plugins_info_path', None) is not None:
with io.open(self.options.plugins_info_path, 'r',
encoding='utf-8') as yaml_file:
if getattr(self.options, "plugins_info_path", None) is not None:
with io.open(
self.options.plugins_info_path, "r", encoding="utf-8"
) as yaml_file:
plugins_info = yaml.load(yaml_file)
if not isinstance(plugins_info, list):
self.parser.error("{0} must contain a Yaml list!".format(
self.options.plugins_info_path))
self.jjb_config.builder['plugins_info'] = plugins_info
self.parser.error(
"{0} must contain a Yaml list!".format(
self.options.plugins_info_path
)
)
self.jjb_config.builder["plugins_info"] = plugins_info
if getattr(self.options, 'path', None):
if hasattr(self.options.path, 'read'):
if getattr(self.options, "path", None):
if hasattr(self.options.path, "read"):
logger.debug("Input file is stdin")
if self.options.path.isatty():
if platform.system() == 'Windows':
key = 'CTRL+Z'
if platform.system() == "Windows":
key = "CTRL+Z"
else:
key = 'CTRL+D'
logger.warning("Reading configuration from STDIN. "
"Press %s to end input.", key)
key = "CTRL+D"
logger.warning(
"Reading configuration from STDIN. " "Press %s to end input.",
key,
)
self.options.path = [self.options.path]
else:
# take list of paths
self.options.path = self.options.path.split(os.pathsep)
do_recurse = (getattr(self.options, 'recursive', False) or
self.jjb_config.recursive)
do_recurse = (
getattr(self.options, "recursive", False)
or self.jjb_config.recursive
)
excludes = ([e for elist in self.options.exclude
for e in elist.split(os.pathsep)] or
self.jjb_config.excludes)
excludes = [
e for elist in self.options.exclude for e in elist.split(os.pathsep)
] or self.jjb_config.excludes
paths = []
for path in self.options.path:
if do_recurse and os.path.isdir(path):
@@ -139,8 +146,8 @@ class JenkinsJobs(object):
def execute(self):
extension_manager = extension.ExtensionManager(
namespace='jjb.cli.subcommands',
invoke_on_load=True,)
namespace="jjb.cli.subcommands", invoke_on_load=True
)
ext = extension_manager[self.options.command]
ext.obj.execute(self.options, self.jjb_config)
@@ -154,10 +161,11 @@ def main():
if sys.version_info[0] == 2:
import codecs
reload(sys) # noqa
sys.setdefaultencoding('utf-8')
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
sys.stderr = codecs.getwriter('utf8')(sys.stderr)
sys.setdefaultencoding("utf-8")
sys.stdout = codecs.getwriter("utf8")(sys.stdout)
sys.stderr = codecs.getwriter("utf8")(sys.stderr)
# end of workaround
argv = sys.argv[1:]

View File

@@ -22,8 +22,10 @@ from stevedore import extension
def __version__():
return "Jenkins Job Builder version: %s" % \
jenkins_jobs.version.version_info.version_string()
return (
"Jenkins Job Builder version: %s"
% jenkins_jobs.version.version_info.version_string()
)
def create_parser():
@@ -31,67 +33,78 @@ def create_parser():
"""
parser = argparse.ArgumentParser()
parser.add_argument(
'--conf',
dest='conf',
default=os.environ.get('JJB_CONF', None),
help="configuration file [JJB_CONF]")
"--conf",
dest="conf",
default=os.environ.get("JJB_CONF", None),
help="configuration file [JJB_CONF]",
)
parser.add_argument(
'-l',
'--log_level',
dest='log_level',
default=os.environ.get('JJB_LOG_LEVEL', 'info'),
help="log level (default: %(default)s) [JJB_LOG_LEVEL]")
"-l",
"--log_level",
dest="log_level",
default=os.environ.get("JJB_LOG_LEVEL", "info"),
help="log level (default: %(default)s) [JJB_LOG_LEVEL]",
)
parser.add_argument(
'--ignore-cache',
action='store_true',
dest='ignore_cache',
"--ignore-cache",
action="store_true",
dest="ignore_cache",
default=None,
help="ignore the cache and update the jobs anyhow (that will "
"only flush the specified jobs cache)")
"only flush the specified jobs cache)",
)
parser.add_argument(
'--flush-cache',
action='store_true',
dest='flush_cache',
"--flush-cache",
action="store_true",
dest="flush_cache",
default=None,
help="flush all the cache entries before updating")
help="flush all the cache entries before updating",
)
parser.add_argument(
'--version',
dest='version',
action='version',
"--version",
dest="version",
action="version",
version=__version__(),
help="show version")
help="show version",
)
parser.add_argument(
'--allow-empty-variables',
action='store_true',
dest='allow_empty_variables',
"--allow-empty-variables",
action="store_true",
dest="allow_empty_variables",
default=None,
help="Don\'t fail if any of the variables inside any string are "
"not defined, replace with empty string instead.")
help="Don't fail if any of the variables inside any string are "
"not defined, replace with empty string instead.",
)
parser.add_argument(
'--server', '-s',
dest='section',
default=os.environ.get('JJB_SECTION', 'jenkins'),
"--server",
"-s",
dest="section",
default=os.environ.get("JJB_SECTION", "jenkins"),
help="The Jenkins server ini section to use. Defaults to 'jenkins' "
"[JJB_SECTION]")
"[JJB_SECTION]",
)
parser.add_argument(
'--user', '-u',
default=os.environ.get('JJB_USER', None),
"--user",
"-u",
default=os.environ.get("JJB_USER", None),
help="The Jenkins user to use for authentication. This overrides "
"the user specified in the configuration file. [JJB_USER]")
"the user specified in the configuration file. [JJB_USER]",
)
parser.add_argument(
'--password', '-p',
default=os.environ.get('JJB_PASSWORD', None),
"--password",
"-p",
default=os.environ.get("JJB_PASSWORD", None),
help="Password or API token to use for authenticating towards Jenkins."
" This overrides the password specified in the configuration file."
" [JJB_PASSWORD]")
" [JJB_PASSWORD]",
)
subparser = parser.add_subparsers(
dest='command',
help="update, test, list or delete job")
dest="command", help="update, test, list or delete job"
)
extension_manager = extension.ExtensionManager(
namespace='jjb.cli.subcommands',
invoke_on_load=True,
namespace="jjb.cli.subcommands", invoke_on_load=True
)
def parse_subcommand_args(ext, subparser):

View File

@@ -22,6 +22,7 @@ class BaseSubCommand(object):
"""Base class for Jenkins Job Builder subcommands, intended to allow
subcommands to be loaded as stevedore extensions by third party users.
"""
def __init__(self):
pass
@@ -52,16 +53,20 @@ class BaseSubCommand(object):
"""Add '--recursive' and '--exclude' arguments to given parser.
"""
parser.add_argument(
'-r', '--recursive',
action='store_true',
dest='recursive',
"-r",
"--recursive",
action="store_true",
dest="recursive",
default=False,
help="look for yaml files recursively")
help="look for yaml files recursively",
)
parser.add_argument(
'-x', '--exclude',
dest='exclude',
action='append',
"-x",
"--exclude",
dest="exclude",
action="append",
default=[],
help="paths to exclude when using recursive search, "
"uses standard globbing.")
"uses standard globbing.",
)

View File

@@ -22,32 +22,33 @@ import jenkins_jobs.cli.subcommand.base as base
class DeleteSubCommand(base.BaseSubCommand):
def parse_args(self, subparser):
delete = subparser.add_parser('delete')
delete = subparser.add_parser("delete")
self.parse_option_recursive_exclude(delete)
delete.add_argument("name", help="name of job", nargs="+")
delete.add_argument(
'name',
help='name of job',
nargs='+')
delete.add_argument(
'-p', '--path',
"-p",
"--path",
default=None,
help="colon-separated list of paths to YAML files "
"or directories")
delete.add_argument(
'-j', '--jobs-only',
action='store_true', dest='del_jobs',
default=False,
help='delete only jobs'
help="colon-separated list of paths to YAML files " "or directories",
)
delete.add_argument(
'-v', '--views-only',
action='store_true', dest='del_views',
"-j",
"--jobs-only",
action="store_true",
dest="del_jobs",
default=False,
help='delete only views'
help="delete only jobs",
)
delete.add_argument(
"-v",
"--views-only",
action="store_true",
dest="del_views",
default=False,
help="delete only views",
)
def execute(self, options, jjb_config):
@@ -55,7 +56,8 @@ class DeleteSubCommand(base.BaseSubCommand):
if options.del_jobs and options.del_views:
raise JenkinsJobsException(
'"--views-only" and "--jobs-only" cannot be used together.')
'"--views-only" and "--jobs-only" cannot be used together.'
)
fn = options.path
registry = ModuleRegistry(jjb_config, builder.plugins_list)
@@ -64,8 +66,8 @@ class DeleteSubCommand(base.BaseSubCommand):
if fn:
parser.load_files(fn)
parser.expandYaml(registry, options.name)
jobs = [j['name'] for j in parser.jobs]
views = [v['name'] for v in parser.views]
jobs = [j["name"] for j in parser.jobs]
views = [v["name"] for v in parser.views]
else:
jobs = options.name
views = options.name

View File

@@ -27,26 +27,30 @@ logger = logging.getLogger(__name__)
class DeleteAllSubCommand(base.BaseSubCommand):
def parse_args(self, subparser):
delete_all = subparser.add_parser(
'delete-all',
"delete-all",
help="delete *ALL* jobs from Jenkins server, including "
"those not managed by Jenkins Job Builder.")
"those not managed by Jenkins Job Builder.",
)
self.parse_option_recursive_exclude(delete_all)
delete_all.add_argument(
'-j', '--jobs-only',
action='store_true', dest='del_jobs',
"-j",
"--jobs-only",
action="store_true",
dest="del_jobs",
default=False,
help='delete only jobs'
help="delete only jobs",
)
delete_all.add_argument(
'-v', '--views-only',
action='store_true', dest='del_views',
"-v",
"--views-only",
action="store_true",
dest="del_views",
default=False,
help='delete only views'
help="delete only views",
)
def execute(self, options, jjb_config):
@@ -55,24 +59,26 @@ class DeleteAllSubCommand(base.BaseSubCommand):
reach = set()
if options.del_jobs and options.del_views:
raise JenkinsJobsException(
'"--views-only" and "--jobs-only" cannot be used together.')
'"--views-only" and "--jobs-only" cannot be used together.'
)
elif options.del_jobs and not options.del_views:
reach.add('jobs')
reach.add("jobs")
elif options.del_views and not options.del_jobs:
reach.add('views')
reach.add("views")
else:
reach.update(('jobs', 'views'))
reach.update(("jobs", "views"))
if not utils.confirm(
'Sure you want to delete *ALL* {} from Jenkins '
'server?\n(including those not managed by Jenkins '
'Job Builder)'.format(" AND ".join(reach))):
sys.exit('Aborted')
"Sure you want to delete *ALL* {} from Jenkins "
"server?\n(including those not managed by Jenkins "
"Job Builder)".format(" AND ".join(reach))
):
sys.exit("Aborted")
if 'jobs' in reach:
if "jobs" in reach:
logger.info("Deleting all jobs")
builder.delete_all_jobs()
if 'views' in reach:
if "views" in reach:
logger.info("Deleting all views")
builder.delete_all_views()

View File

@@ -25,17 +25,18 @@ logger = logging.getLogger(__name__)
class GetPluginsInfoSubCommand(base.BaseSubCommand):
def parse_args(self, subparser):
plugins_info = subparser.add_parser(
'get-plugins-info',
help='get plugins info yaml by querying Jenkins server.')
"get-plugins-info", help="get plugins info yaml by querying Jenkins server."
)
plugins_info.add_argument(
'-o', '--output-file',
default='plugins_info.yaml',
dest='plugins_info_file',
help='file to save output to.')
"-o",
"--output-file",
default="plugins_info.yaml",
dest="plugins_info_file",
help="file to save output to.",
)
def execute(self, options, jjb_config):
builder = JenkinsManager(jjb_config)
@@ -43,14 +44,14 @@ class GetPluginsInfoSubCommand(base.BaseSubCommand):
plugins_info = []
for plugin in plugin_data:
info = {
'longName': str(plugin['longName']),
'shortName': str(plugin['shortName']),
'version': str(plugin['version']),
"longName": str(plugin["longName"]),
"shortName": str(plugin["shortName"]),
"version": str(plugin["version"]),
}
plugins_info.append(info)
if options.plugins_info_file:
with open(options.plugins_info_file, 'w') as outfile:
with open(options.plugins_info_file, "w") as outfile:
outfile.write(yaml.dump(plugins_info))
logger.info("Generated {} file".format(options.plugins_info_file))
else:

View File

@@ -27,18 +27,15 @@ def list_duplicates(seq):
class ListSubCommand(base.BaseSubCommand):
def parse_args(self, subparser):
list = subparser.add_parser('list', help="List jobs")
list = subparser.add_parser("list", help="List jobs")
self.parse_option_recursive_exclude(list)
list.add_argument('names',
help='name(s) of job(s)',
nargs='*',
default=None)
list.add_argument('-p', '--path', default=None,
help='path to YAML file or directory')
list.add_argument("names", help="name(s) of job(s)", nargs="*", default=None)
list.add_argument(
"-p", "--path", default=None, help="path to YAML file or directory"
)
def execute(self, options, jjb_config):
self.jjb_config = jjb_config
@@ -50,24 +47,25 @@ class ListSubCommand(base.BaseSubCommand):
stdout = utils.wrap_stream(sys.stdout)
for job in jobs:
stdout.write((job + '\n').encode('utf-8'))
stdout.write((job + "\n").encode("utf-8"))
def get_jobs(self, jobs_glob=None, fn=None):
if fn:
r = registry.ModuleRegistry(self.jjb_config,
self.jenkins.plugins_list)
r = registry.ModuleRegistry(self.jjb_config, self.jenkins.plugins_list)
p = parser.YamlParser(self.jjb_config)
p.load_files(fn)
p.expandYaml(r, jobs_glob)
jobs = [j['name'] for j in p.jobs]
jobs = [j["name"] for j in p.jobs]
else:
jobs = [j['name'] for j in self.jenkins.get_jobs()
if not jobs_glob or parser.matches(j['name'], jobs_glob)]
jobs = [
j["name"]
for j in self.jenkins.get_jobs()
if not jobs_glob or parser.matches(j["name"], jobs_glob)
]
jobs = sorted(jobs)
for duplicate in list_duplicates(jobs):
logging.warning("Found duplicate job name '%s', likely bug.",
duplicate)
logging.warning("Found duplicate job name '%s', likely bug.", duplicate)
logging.debug("Builder.get_jobs: returning %r", jobs)

View File

@@ -23,9 +23,8 @@ logger = logging.getLogger(__name__)
class TestSubCommand(update.UpdateSubCommand):
def parse_args(self, subparser):
test = subparser.add_parser('test')
test = subparser.add_parser("test")
self.parse_option_recursive_exclude(test)
@@ -33,36 +32,46 @@ class TestSubCommand(update.UpdateSubCommand):
self.parse_arg_names(test)
test.add_argument(
'--config-xml',
action='store_true',
dest='config_xml',
"--config-xml",
action="store_true",
dest="config_xml",
default=False,
help='use alternative output file layout using config.xml files')
help="use alternative output file layout using config.xml files",
)
test.add_argument(
'-p', '--plugin-info',
dest='plugins_info_path',
"-p",
"--plugin-info",
dest="plugins_info_path",
default=None,
help='path to plugin info YAML file')
help="path to plugin info YAML file",
)
test.add_argument(
'-o',
dest='output_dir',
default=sys.stdout,
help='path to output XML')
"-o", dest="output_dir", default=sys.stdout, help="path to output XML"
)
def execute(self, options, jjb_config):
if not options.config_xml:
logger.warn('(Deprecated) The default output behavior of'
' `jenkins-jobs test` when given the --output'
' flag will change in JJB 3.0.'
' Instead of writing jobs to OUTPUT/jobname;'
' they will be written to OUTPUT/jobname/config.xml.'
' The new behavior can be enabled by the passing'
' `--config-xml` parameter.')
logger.warn(
"(Deprecated) The default output behavior of"
" `jenkins-jobs test` when given the --output"
" flag will change in JJB 3.0."
" Instead of writing jobs to OUTPUT/jobname;"
" they will be written to OUTPUT/jobname/config.xml."
" The new behavior can be enabled by the passing"
" `--config-xml` parameter."
)
builder, xml_jobs, xml_views = self._generate_xmljobs(
options, jjb_config)
builder, xml_jobs, xml_views = self._generate_xmljobs(options, jjb_config)
builder.update_jobs(xml_jobs, 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)
builder.update_jobs(
xml_jobs,
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

@@ -30,22 +30,19 @@ logger = logging.getLogger(__name__)
class UpdateSubCommand(base.BaseSubCommand):
def parse_arg_path(self, parser):
parser.add_argument(
'path',
nargs='?',
"path",
nargs="?",
default=sys.stdin,
help="colon-separated list of paths to YAML files "
"or directories")
help="colon-separated list of paths to YAML files " "or directories",
)
def parse_arg_names(self, parser):
parser.add_argument(
'names',
help='name(s) of job(s)', nargs='*')
parser.add_argument("names", help="name(s) of job(s)", nargs="*")
def parse_args(self, subparser):
update = subparser.add_parser('update')
update = subparser.add_parser("update")
self.parse_option_recursive_exclude(update)
@@ -53,51 +50,59 @@ class UpdateSubCommand(base.BaseSubCommand):
self.parse_arg_names(update)
update.add_argument(
'--delete-old',
action='store_true',
dest='delete_old',
"--delete-old",
action="store_true",
dest="delete_old",
default=False,
help='delete obsolete jobs')
help="delete obsolete jobs",
)
update.add_argument(
'-p', '--plugin-info',
dest='plugins_info_path',
"-p",
"--plugin-info",
dest="plugins_info_path",
default=None,
help='path to plugin info YAML file. Can be used to provide '
'previously retrieved plugins info when connecting credentials '
'don\'t have permissions to query.')
help="path to plugin info YAML file. Can be used to provide "
"previously retrieved plugins info when connecting credentials "
"don't have permissions to query.",
)
update.add_argument(
'--workers',
"--workers",
type=int,
default=1,
dest='n_workers',
dest="n_workers",
help="number of workers to use, 0 for autodetection and 1 "
"for just one worker.")
"for just one worker.",
)
update.add_argument(
'--existing-only',
action='store_true',
"--existing-only",
action="store_true",
default=False,
dest='existing_only',
help='update existing jobs only')
dest="existing_only",
help="update existing jobs only",
)
update_type = update.add_mutually_exclusive_group()
update_type.add_argument(
'-j', '--jobs-only',
action='store_const',
dest='update',
const='jobs',
help='update only jobs')
"-j",
"--jobs-only",
action="store_const",
dest="update",
const="jobs",
help="update only jobs",
)
update_type.add_argument(
'-v', '--views-only',
action='store_const',
dest='update',
const='views',
help='update only views')
"-v",
"--views-only",
action="store_const",
dest="update",
const="views",
help="update only views",
)
def _generate_xmljobs(self, options, jjb_config=None):
builder = JenkinsManager(jjb_config)
logger.info("Updating jobs in {0} ({1})".format(
options.path, options.names))
logger.info("Updating jobs in {0} ({1})".format(options.path, options.names))
orig = time.time()
# Generate XML
@@ -109,45 +114,51 @@ class UpdateSubCommand(base.BaseSubCommand):
parser.load_files(options.path)
registry.set_parser_data(parser.data)
job_data_list, view_data_list = parser.expandYaml(
registry, options.names)
job_data_list, view_data_list = parser.expandYaml(registry, options.names)
xml_jobs = xml_job_generator.generateXML(job_data_list)
xml_views = xml_view_generator.generateXML(view_data_list)
jobs = parser.jobs
step = time.time()
logging.debug('%d XML files generated in %ss',
len(jobs), str(step - orig))
logging.debug("%d XML files generated in %ss", len(jobs), str(step - orig))
return builder, xml_jobs, xml_views
def execute(self, options, jjb_config):
if options.n_workers < 0:
raise JenkinsJobsException(
'Number of workers must be equal or greater than 0')
"Number of workers must be equal or greater than 0"
)
builder, xml_jobs, xml_views = self._generate_xmljobs(
options, jjb_config)
builder, xml_jobs, xml_views = self._generate_xmljobs(options, jjb_config)
if options.update == 'jobs':
if options.update == "jobs":
jobs, num_updated_jobs = builder.update_jobs(
xml_jobs, n_workers=options.n_workers,
existing_only=options.existing_only)
xml_jobs,
n_workers=options.n_workers,
existing_only=options.existing_only,
)
logger.info("Number of jobs updated: %d", num_updated_jobs)
elif options.update == 'views':
elif options.update == "views":
views, num_updated_views = builder.update_views(
xml_views, n_workers=options.n_workers,
existing_only=options.existing_only)
xml_views,
n_workers=options.n_workers,
existing_only=options.existing_only,
)
logger.info("Number of views updated: %d", num_updated_views)
else:
jobs, num_updated_jobs = builder.update_jobs(
xml_jobs, n_workers=options.n_workers,
existing_only=options.existing_only)
xml_jobs,
n_workers=options.n_workers,
existing_only=options.existing_only,
)
logger.info("Number of jobs updated: %d", num_updated_jobs)
views, num_updated_views = builder.update_views(
xml_views, n_workers=options.n_workers,
existing_only=options.existing_only)
xml_views,
n_workers=options.n_workers,
existing_only=options.existing_only,
)
logger.info("Number of views updated: %d", num_updated_views)
keep_jobs = [job.name for job in xml_jobs]

View File

@@ -27,9 +27,7 @@ from jenkins_jobs import builder
from jenkins_jobs.errors import JJBConfigException
from jenkins_jobs.errors import JenkinsJobsException
__all__ = [
"JJBConfig"
]
__all__ = ["JJBConfig"]
logger = logging.getLogger(__name__)
@@ -50,21 +48,21 @@ url=http://localhost:8080/
query_plugins_info=False
"""
CONFIG_REQUIRED_MESSAGE = ("A valid configuration file is required. "
"No configuration file passed.")
CONFIG_REQUIRED_MESSAGE = (
"A valid configuration file is required. " "No configuration file passed."
)
DEPRECATED_PLUGIN_CONFIG_SECTION_MESSAGE = (
"Defining plugin configuration using a [{plugin}] section in your config"
" file is deprecated. The recommended way to define plugins now is by"
" using a [plugin \"{plugin}\"] section"
' using a [plugin "{plugin}"] section'
)
_NOTSET = object()
class JJBConfig(object):
def __init__(self, config_filename=None,
config_file_required=False,
config_section='jenkins'):
def __init__(
self, config_filename=None, config_file_required=False, config_section="jenkins"
):
"""
The JJBConfig class is intended to encapsulate and resolve priority
@@ -93,11 +91,11 @@ class JJBConfig(object):
config_parser = self._init_defaults()
global_conf = '/etc/jenkins_jobs/jenkins_jobs.ini'
user_conf = os.path.join(os.path.expanduser('~'), '.config',
'jenkins_jobs', 'jenkins_jobs.ini')
local_conf = os.path.join(os.path.dirname(__file__),
'jenkins_jobs.ini')
global_conf = "/etc/jenkins_jobs/jenkins_jobs.ini"
user_conf = os.path.join(
os.path.expanduser("~"), ".config", "jenkins_jobs", "jenkins_jobs.ini"
)
local_conf = os.path.join(os.path.dirname(__file__), "jenkins_jobs.ini")
conf = None
if config_filename is not None:
conf = config_filename
@@ -120,8 +118,10 @@ class JJBConfig(object):
if config_file_required:
raise JJBConfigException(CONFIG_REQUIRED_MESSAGE)
else:
logger.warning("Config file, {0}, not found. Using "
"default config values.".format(conf))
logger.warning(
"Config file, {0}, not found. Using "
"default config values.".format(conf)
)
if config_fp is not None:
if PY2:
@@ -162,33 +162,35 @@ class JJBConfig(object):
if os.path.isfile(config_filename):
self.__config_file = config_filename # remember file we read from
logger.debug("Reading config from {0}".format(config_filename))
config_fp = io.open(config_filename, 'r', encoding='utf-8')
config_fp = io.open(config_filename, "r", encoding="utf-8")
else:
raise JJBConfigException(
"A valid configuration file is required. "
"\n{0} is not valid.".format(config_filename))
"\n{0} is not valid.".format(config_filename)
)
return config_fp
def _handle_deprecated_hipchat_config(self):
config = self.config_parser
if config.has_section('hipchat'):
if config.has_section("hipchat"):
if config.has_section('plugin "hipchat"'):
logger.warning(
"Both [hipchat] and [plugin \"hipchat\"] sections "
'Both [hipchat] and [plugin "hipchat"] sections '
"defined, legacy [hipchat] section will be ignored."
)
else:
logger.warning(
"[hipchat] section is deprecated and should be moved to a "
"[plugins \"hipchat\"] section instead as the [hipchat] "
'[plugins "hipchat"] section instead as the [hipchat] '
"section will be ignored in the future."
)
config.add_section('plugin "hipchat"')
for option in config.options("hipchat"):
config.set('plugin "hipchat"', option,
config.get("hipchat", option))
config.set(
'plugin "hipchat"', option, config.get("hipchat", option)
)
config.remove_section("hipchat")
@@ -197,9 +199,10 @@ class JJBConfig(object):
# interpolation to remove the need for plugins to need information
# directly from the jenkins section within code and allow variables
# in the config file to refer instead.
if (config.has_section('plugin "hipchat"') and
not config.has_option('plugin "hipchat"', 'url')):
config.set('plugin "hipchat"', "url", config.get('jenkins', 'url'))
if config.has_section('plugin "hipchat"') and not config.has_option(
'plugin "hipchat"', "url"
):
config.set('plugin "hipchat"', "url", config.get("jenkins", "url"))
def _setup(self):
config = self.config_parser
@@ -208,26 +211,27 @@ class JJBConfig(object):
# check the ignore_cache setting
ignore_cache = False
if config.has_option(self._section, 'ignore_cache'):
logger.warning("ignore_cache option should be moved to the "
"[job_builder] section in the config file, the "
"one specified in the [jenkins] section will be "
"ignored in the future")
ignore_cache = config.getboolean(self._section, 'ignore_cache')
elif config.has_option('job_builder', 'ignore_cache'):
ignore_cache = config.getboolean('job_builder', 'ignore_cache')
self.builder['ignore_cache'] = ignore_cache
if config.has_option(self._section, "ignore_cache"):
logger.warning(
"ignore_cache option should be moved to the "
"[job_builder] section in the config file, the "
"one specified in the [jenkins] section will be "
"ignored in the future"
)
ignore_cache = config.getboolean(self._section, "ignore_cache")
elif config.has_option("job_builder", "ignore_cache"):
ignore_cache = config.getboolean("job_builder", "ignore_cache")
self.builder["ignore_cache"] = ignore_cache
# check the flush_cache setting
flush_cache = False
if config.has_option('job_builder', 'flush_cache'):
flush_cache = config.getboolean('job_builder', 'flush_cache')
self.builder['flush_cache'] = flush_cache
if config.has_option("job_builder", "flush_cache"):
flush_cache = config.getboolean("job_builder", "flush_cache")
self.builder["flush_cache"] = flush_cache
# check the print_job_urls setting
if config.has_option('job_builder', 'print_job_urls'):
self.print_job_urls = config.getboolean('job_builder',
'print_job_urls')
if config.has_option("job_builder", "print_job_urls"):
self.print_job_urls = config.getboolean("job_builder", "print_job_urls")
# Jenkins supports access as an anonymous user, which can be used to
# ensure read-only behaviour when querying the version of plugins
@@ -240,16 +244,16 @@ class JJBConfig(object):
# https://bugs.launchpad.net/openstack-ci/+bug/1259631
try:
user = config.get(self._section, 'user')
user = config.get(self._section, "user")
except (TypeError, configparser.NoOptionError):
user = None
self.jenkins['user'] = user
self.jenkins["user"] = user
try:
password = config.get(self._section, 'password')
password = config.get(self._section, "password")
except (TypeError, configparser.NoOptionError):
password = None
self.jenkins['password'] = password
self.jenkins["password"] = password
# None -- no timeout, blocking mode; same as setblocking(True)
# 0.0 -- non-blocking mode; same as setblocking(False) <--- default
@@ -259,86 +263,94 @@ class JJBConfig(object):
# "timeout=jenkins_jobs.builder._DEFAULT_TIMEOUT" or not set timeout at
# all.
try:
timeout = config.getfloat(self._section, 'timeout')
timeout = config.getfloat(self._section, "timeout")
except (ValueError):
raise JenkinsJobsException("Jenkins timeout config is invalid")
except (TypeError, configparser.NoOptionError):
timeout = builder._DEFAULT_TIMEOUT
self.jenkins['timeout'] = timeout
self.jenkins["timeout"] = timeout
plugins_info = None
if (config.has_option(self._section, 'query_plugins_info') and
not config.getboolean(self._section, "query_plugins_info")):
if config.has_option(
self._section, "query_plugins_info"
) and not config.getboolean(self._section, "query_plugins_info"):
logger.debug("Skipping plugin info retrieval")
plugins_info = []
self.builder['plugins_info'] = plugins_info
self.builder["plugins_info"] = plugins_info
self.recursive = config.getboolean('job_builder', 'recursive')
self.excludes = config.get('job_builder', 'exclude').split(os.pathsep)
self.recursive = config.getboolean("job_builder", "recursive")
self.excludes = config.get("job_builder", "exclude").split(os.pathsep)
# The way we want to do things moving forward:
self.jenkins['url'] = config.get(self._section, 'url')
self.builder['print_job_urls'] = self.print_job_urls
self.jenkins["url"] = config.get(self._section, "url")
self.builder["print_job_urls"] = self.print_job_urls
# keep descriptions ? (used by yamlparser)
keep_desc = False
if (config and config.has_section('job_builder') and
config.has_option('job_builder', 'keep_descriptions')):
keep_desc = config.getboolean('job_builder',
'keep_descriptions')
self.yamlparser['keep_descriptions'] = keep_desc
if (
config
and config.has_section("job_builder")
and config.has_option("job_builder", "keep_descriptions")
):
keep_desc = config.getboolean("job_builder", "keep_descriptions")
self.yamlparser["keep_descriptions"] = keep_desc
# figure out the include path (used by yamlparser)
path = ["."]
if (config and config.has_section('job_builder') and
config.has_option('job_builder', 'include_path')):
path = config.get('job_builder',
'include_path').split(':')
self.yamlparser['include_path'] = path
if (
config
and config.has_section("job_builder")
and config.has_option("job_builder", "include_path")
):
path = config.get("job_builder", "include_path").split(":")
self.yamlparser["include_path"] = path
# allow duplicates?
allow_duplicates = False
if config and config.has_option('job_builder', 'allow_duplicates'):
allow_duplicates = config.getboolean('job_builder',
'allow_duplicates')
self.yamlparser['allow_duplicates'] = allow_duplicates
if config and config.has_option("job_builder", "allow_duplicates"):
allow_duplicates = config.getboolean("job_builder", "allow_duplicates")
self.yamlparser["allow_duplicates"] = allow_duplicates
# allow empty variables?
self.yamlparser['allow_empty_variables'] = (
config and config.has_section('job_builder') and
config.has_option('job_builder', 'allow_empty_variables') and
config.getboolean('job_builder', 'allow_empty_variables'))
self.yamlparser["allow_empty_variables"] = (
config
and config.has_section("job_builder")
and config.has_option("job_builder", "allow_empty_variables")
and config.getboolean("job_builder", "allow_empty_variables")
)
# retain anchors across files?
retain_anchors = False
if config and config.has_option('job_builder', 'retain_anchors'):
retain_anchors = config.getboolean('job_builder',
'retain_anchors')
self.yamlparser['retain_anchors'] = retain_anchors
if config and config.has_option("job_builder", "retain_anchors"):
retain_anchors = config.getboolean("job_builder", "retain_anchors")
self.yamlparser["retain_anchors"] = retain_anchors
update = None
if (config and config.has_section('job_builder') and
config.has_option('job_builder', 'update')):
update = config.get('job_builder', 'update')
self.builder['update'] = update
if (
config
and config.has_section("job_builder")
and config.has_option("job_builder", "update")
):
update = config.get("job_builder", "update")
self.builder["update"] = update
def validate(self):
# Inform the user as to what is likely to happen, as they may specify
# a real jenkins instance in test mode to get the plugin info to check
# the XML generated.
if self.jenkins['user'] is None and self.jenkins['password'] is None:
if self.jenkins["user"] is None and self.jenkins["password"] is None:
logger.info("Will use anonymous access to Jenkins if needed.")
elif ((self.jenkins['user'] is not None and
self.jenkins['password'] is None) or
(self.jenkins['user'] is None and
self.jenkins['password'] is not None)):
elif (
self.jenkins["user"] is not None and self.jenkins["password"] is None
) or (self.jenkins["user"] is None and self.jenkins["password"] is not None):
raise JenkinsJobsException(
"Cannot authenticate to Jenkins with only one of User and "
"Password provided, please check your configuration."
)
if (self.builder['plugins_info'] is not None and
not isinstance(self.builder['plugins_info'], list)):
if self.builder["plugins_info"] is not None and not isinstance(
self.builder["plugins_info"], list
):
raise JenkinsJobsException("plugins_info must contain a list!")
def get_module_config(self, section, key, default=None):
@@ -349,19 +361,23 @@ class JJBConfig(object):
"""
result = default
try:
result = self.config_parser.get(
section, key
)
except (configparser.NoSectionError, configparser.NoOptionError,
JenkinsJobsException) as e:
result = self.config_parser.get(section, key)
except (
configparser.NoSectionError,
configparser.NoOptionError,
JenkinsJobsException,
) as e:
# use of default ignores missing sections/options
if result is None:
logger.warning(
"You didn't set a %s neither in the yaml job definition "
"nor in the %s section, blank default value will be "
"applied:\n%s", key, section, e)
"applied:\n%s",
key,
section,
e,
)
return result
def get_plugin_config(self, plugin, key, default=None):
return self.get_module_config('plugin "{}"'.format(plugin), key,
default)
return self.get_module_config('plugin "{}"'.format(plugin), key, default)

View File

@@ -4,9 +4,9 @@ import inspect
def is_sequence(arg):
return (not hasattr(arg, "strip") and
(hasattr(arg, "__getitem__") or
hasattr(arg, "__iter__")))
return not hasattr(arg, "strip") and (
hasattr(arg, "__getitem__") or hasattr(arg, "__iter__")
)
class JenkinsJobsException(Exception):
@@ -14,20 +14,19 @@ class JenkinsJobsException(Exception):
class ModuleError(JenkinsJobsException):
def get_module_name(self):
frame = inspect.currentframe()
co_name = frame.f_code.co_name
module_name = '<unresolved>'
while frame and co_name != 'run':
module_name = "<unresolved>"
while frame and co_name != "run":
# XML generation called via dispatch
if co_name == 'dispatch':
if co_name == "dispatch":
data = frame.f_locals
module_name = "%s.%s" % (data['component_type'], data['name'])
module_name = "%s.%s" % (data["component_type"], data["name"])
break
# XML generation done directly by class using gen_xml or root_xml
if co_name == 'gen_xml' or co_name == 'root_xml':
data = frame.f_locals['data']
if co_name == "gen_xml" or co_name == "root_xml":
data = frame.f_locals["data"]
module_name = next(iter(data.keys()))
break
frame = frame.f_back
@@ -37,47 +36,41 @@ class ModuleError(JenkinsJobsException):
class InvalidAttributeError(ModuleError):
def __init__(self, attribute_name, value, valid_values=None):
message = "'{0}' is an invalid value for attribute {1}.{2}".format(
value, self.get_module_name(), attribute_name)
value, self.get_module_name(), attribute_name
)
if is_sequence(valid_values):
message += "\nValid values include: {0}".format(
', '.join("'{0}'".format(value)
for value in valid_values))
", ".join("'{0}'".format(value) for value in valid_values)
)
super(InvalidAttributeError, self).__init__(message)
class MissingAttributeError(ModuleError):
def __init__(self, missing_attribute, module_name=None):
module = module_name or self.get_module_name()
if is_sequence(missing_attribute):
message = "One of {0} must be present in '{1}'".format(
', '.join("'{0}'".format(value)
for value in missing_attribute), module)
", ".join("'{0}'".format(value) for value in missing_attribute), module
)
else:
message = "Missing {0} from an instance of '{1}'".format(
missing_attribute, module)
missing_attribute, module
)
super(MissingAttributeError, self).__init__(message)
class AttributeConflictError(ModuleError):
def __init__(
self, attribute_name, attributes_in_conflict, module_name=None
):
def __init__(self, attribute_name, attributes_in_conflict, module_name=None):
module = module_name or self.get_module_name()
message = (
"Attribute '{0}' can not be used together with {1} in {2}".format(
attribute_name,
', '.join(
"'{0}'".format(value) for value in attributes_in_conflict
), module
)
message = "Attribute '{0}' can not be used together with {1} in {2}".format(
attribute_name,
", ".join("'{0}'".format(value) for value in attributes_in_conflict),
module,
)
super(AttributeConflictError, self).__init__(message)

View File

@@ -33,18 +33,22 @@ def deep_format(obj, paramdict, allow_empty=False):
# limitations on the values in paramdict - the post-format result must
# still be valid YAML (so substituting-in a string containing quotes, for
# example, is problematic).
if hasattr(obj, 'format'):
if hasattr(obj, "format"):
try:
ret = CustomFormatter(allow_empty).format(obj, **paramdict)
except KeyError as exc:
missing_key = exc.args[0]
desc = "%s parameter missing to format %s\nGiven:\n%s" % (
missing_key, obj, pformat(paramdict))
missing_key,
obj,
pformat(paramdict),
)
raise JenkinsJobsException(desc)
except Exception:
logging.error("Problem formatting with args:\nallow_empty:"
"%s\nobj: %s\nparamdict: %s" %
(allow_empty, obj, paramdict))
logging.error(
"Problem formatting with args:\nallow_empty:"
"%s\nobj: %s\nparamdict: %s" % (allow_empty, obj, paramdict)
)
raise
elif isinstance(obj, list):
@@ -55,17 +59,22 @@ def deep_format(obj, paramdict, allow_empty=False):
ret = type(obj)()
for item in obj:
try:
ret[CustomFormatter(allow_empty).format(item, **paramdict)] = \
deep_format(obj[item], paramdict, allow_empty)
ret[
CustomFormatter(allow_empty).format(item, **paramdict)
] = deep_format(obj[item], paramdict, allow_empty)
except KeyError as exc:
missing_key = exc.args[0]
desc = "%s parameter missing to format %s\nGiven:\n%s" % (
missing_key, obj, pformat(paramdict))
missing_key,
obj,
pformat(paramdict),
)
raise JenkinsJobsException(desc)
except Exception:
logging.error("Problem formatting with args:\nallow_empty:"
"%s\nobj: %s\nparamdict: %s" %
(allow_empty, obj, paramdict))
logging.error(
"Problem formatting with args:\nallow_empty:"
"%s\nobj: %s\nparamdict: %s" % (allow_empty, obj, paramdict)
)
raise
else:
ret = obj
@@ -81,6 +90,7 @@ class CustomFormatter(Formatter):
Custom formatter to allow non-existing key references when formatting a
string
"""
_expr = r"""
(?<!{){({{)* # non-pair opening {
(?:obj:)? # obj:
@@ -99,7 +109,7 @@ class CustomFormatter(Formatter):
# special case of returning the object if the entire string
# matches a single parameter
try:
result = re.match('^%s$' % self._expr, format_string, re.VERBOSE)
result = re.match("^%s$" % self._expr, format_string, re.VERBOSE)
except TypeError:
return format_string.format(**kwargs)
if result is not None:
@@ -130,8 +140,7 @@ class CustomFormatter(Formatter):
except KeyError:
if self.allow_empty:
logger.debug(
'Found uninitialized key %s, replaced with empty string',
key
"Found uninitialized key %s, replaced with empty string", key
)
return ''
return ""
raise

View File

@@ -235,9 +235,11 @@ class OrderedConstructor(BaseConstructor):
self.flatten_mapping(node)
else:
raise yaml.constructor.ConstructorError(
None, None,
'expected a mapping node, but found %s' % node.id,
node.start_mark)
None,
None,
"expected a mapping node, but found %s" % node.id,
node.start_mark,
)
mapping = OrderedDict()
for key_node, value_node in node.value:
@@ -246,23 +248,26 @@ class OrderedConstructor(BaseConstructor):
hash(key)
except TypeError as exc:
raise yaml.constructor.ConstructorError(
'while constructing a mapping', node.start_mark,
'found unacceptable key (%s)' % exc, key_node.start_mark)
"while constructing a mapping",
node.start_mark,
"found unacceptable key (%s)" % exc,
key_node.start_mark,
)
value = self.construct_object(value_node, deep=False)
mapping[key] = value
data.update(mapping)
class OrderedRepresenter(BaseRepresenter):
def represent_yaml_mapping(self, mapping, flow_style=None):
tag = u'tag:yaml.org,2002:map'
tag = u"tag:yaml.org,2002:map"
node = self.represent_mapping(tag, mapping, flow_style=flow_style)
return node
class LocalAnchorLoader(yaml.Loader):
"""Subclass for yaml.Loader which keeps Alias between calls"""
anchors = {}
def __init__(self, *args, **kwargs):
@@ -319,14 +324,13 @@ class LocalLoader(OrderedConstructor, LocalAnchorLoader):
# make sure to pop off any local settings before passing to
# the parent constructor as any unknown args may cause errors.
self.search_path = list()
if 'search_path' in kwargs:
for p in kwargs.pop('search_path'):
logger.debug("Adding '{0}' to search path for include tags"
.format(p))
if "search_path" in kwargs:
for p in kwargs.pop("search_path"):
logger.debug("Adding '{0}' to search path for include tags".format(p))
self.search_path.append(os.path.normpath(p))
if 'escape_callback' in kwargs:
self.escape_callback = kwargs.pop('escape_callback')
if "escape_callback" in kwargs:
self.escape_callback = kwargs.pop("escape_callback")
else:
self.escape_callback = self._escape
@@ -334,16 +338,17 @@ class LocalLoader(OrderedConstructor, LocalAnchorLoader):
# constructor to preserve order of maps and ensure that the order of
# keys returned is consistent across multiple python versions
self.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
type(self).construct_yaml_map)
self.add_constructor(
yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
type(self).construct_yaml_map,
)
if hasattr(self.stream, 'name'):
self.search_path.append(os.path.normpath(
os.path.dirname(self.stream.name)))
if hasattr(self.stream, "name"):
self.search_path.append(os.path.normpath(os.path.dirname(self.stream.name)))
self.search_path.append(os.path.normpath(os.path.curdir))
def _escape(self, data):
return re.sub(r'({|})', r'\1\1', data)
return re.sub(r"({|})", r"\1\1", data)
class LocalDumper(OrderedRepresenter, yaml.Dumper):
@@ -352,12 +357,10 @@ class LocalDumper(OrderedRepresenter, yaml.Dumper):
# representer to ensure conversion back looks like normal
# mapping and hides that we use OrderedDict internally
self.add_representer(OrderedDict,
type(self).represent_yaml_mapping)
self.add_representer(OrderedDict, type(self).represent_yaml_mapping)
# convert any tuples to lists as the JJB input is generally
# in list format
self.add_representer(tuple,
type(self).represent_list)
self.add_representer(tuple, type(self).represent_list)
class BaseYAMLObject(YAMLObject):
@@ -366,7 +369,7 @@ class BaseYAMLObject(YAMLObject):
class J2String(BaseYAMLObject):
yaml_tag = u'!j2:'
yaml_tag = u"!j2:"
@classmethod
def from_yaml(cls, loader, node):
@@ -374,7 +377,7 @@ class J2String(BaseYAMLObject):
class YamlListJoin(BaseYAMLObject):
yaml_tag = u'!join:'
yaml_tag = u"!join:"
@classmethod
def from_yaml(cls, loader, node):
@@ -382,26 +385,34 @@ class YamlListJoin(BaseYAMLObject):
delimiter = node.value[0].value
if not isinstance(node.value[1], yaml.SequenceNode):
raise yaml.constructor.ConstructorError(
None, None, "expected sequence node for join data, but "
"found %s" % node.value[1].id, node.start_mark)
None,
None,
"expected sequence node for join data, but "
"found %s" % node.value[1].id,
node.start_mark,
)
return delimiter.join((v.value for v in node.value[1].value))
else:
raise yaml.constructor.ConstructorError(
None, None, "expected sequence node, but found %s" % node.id,
node.start_mark)
None,
None,
"expected sequence node, but found %s" % node.id,
node.start_mark,
)
class YamlInclude(BaseYAMLObject):
yaml_tag = u'!include:'
yaml_tag = u"!include:"
@classmethod
def _find_file(cls, filename, search_path):
for dirname in search_path:
candidate = os.path.expanduser(os.path.join(dirname, filename))
if os.path.isfile(candidate):
logger.debug("Including file '{0}' from path '{1}'"
.format(filename, dirname))
logger.debug(
"Including file '{0}' from path '{1}'".format(filename, dirname)
)
return candidate
return filename
@@ -415,11 +426,14 @@ class YamlInclude(BaseYAMLObject):
filename = cls._find_file(node_str, loader.search_path)
try:
with io.open(filename, 'r', encoding='utf-8') as f:
with io.open(filename, "r", encoding="utf-8") as f:
return f.read()
except Exception:
logger.error("Failed to include file using search path: '{0}'"
.format(':'.join(loader.search_path)))
logger.error(
"Failed to include file using search path: '{0}'".format(
":".join(loader.search_path)
)
)
raise
@classmethod
@@ -428,15 +442,14 @@ class YamlInclude(BaseYAMLObject):
if isinstance(contents, LazyLoader):
return contents
data = yaml.load(contents,
functools.partial(cls.yaml_loader,
search_path=loader.search_path))
data = yaml.load(
contents, functools.partial(cls.yaml_loader, search_path=loader.search_path)
)
return data
@classmethod
def _lazy_load(cls, loader, tag, node_str):
logger.info("Lazy loading of file template '{0}' enabled"
.format(node_str))
logger.info("Lazy loading of file template '{0}' enabled".format(node_str))
return LazyLoader((cls, loader, node_str))
@classmethod
@@ -444,20 +457,24 @@ class YamlInclude(BaseYAMLObject):
if isinstance(node, yaml.ScalarNode):
return cls._from_file(loader, node)
elif isinstance(node, yaml.SequenceNode):
contents = [cls._from_file(loader, scalar_node)
for scalar_node in node.value]
contents = [
cls._from_file(loader, scalar_node) for scalar_node in node.value
]
if any(isinstance(s, CustomLoader) for s in contents):
return CustomLoaderCollection(contents)
return u'\n'.join(contents)
return u"\n".join(contents)
else:
raise yaml.constructor.ConstructorError(
None, None, "expected either a sequence or scalar node, but "
"found %s" % node.id, node.start_mark)
None,
None,
"expected either a sequence or scalar node, but " "found %s" % node.id,
node.start_mark,
)
class YamlIncludeRaw(YamlInclude):
yaml_tag = u'!include-raw:'
yaml_tag = u"!include-raw:"
@classmethod
def _from_file(cls, loader, node):
@@ -465,23 +482,26 @@ class YamlIncludeRaw(YamlInclude):
class YamlIncludeRawEscape(YamlIncludeRaw):
yaml_tag = u'!include-raw-escape:'
yaml_tag = u"!include-raw-escape:"
@classmethod
def from_yaml(cls, loader, node):
data = YamlIncludeRaw.from_yaml(loader, node)
if isinstance(data, LazyLoader):
logger.warning("Replacing %s tag with %s since lazy loading means "
"file contents will not be deep formatted for "
"variable substitution.", cls.yaml_tag,
YamlIncludeRaw.yaml_tag)
logger.warning(
"Replacing %s tag with %s since lazy loading means "
"file contents will not be deep formatted for "
"variable substitution.",
cls.yaml_tag,
YamlIncludeRaw.yaml_tag,
)
return data
else:
return loader.escape_callback(data)
class YamlIncludeJinja2(YamlIncludeRaw):
yaml_tag = u'!include-jinja2:'
yaml_tag = u"!include-jinja2:"
@classmethod
def _from_file(cls, loader, node):
@@ -492,26 +512,28 @@ class YamlIncludeJinja2(YamlIncludeRaw):
class DeprecatedTag(BaseYAMLObject):
@classmethod
def from_yaml(cls, loader, node):
logger.warning("tag '%s' is deprecated, switch to using '%s'",
cls.yaml_tag, cls._new.yaml_tag)
logger.warning(
"tag '%s' is deprecated, switch to using '%s'",
cls.yaml_tag,
cls._new.yaml_tag,
)
return cls._new.from_yaml(loader, node)
class YamlIncludeDeprecated(DeprecatedTag):
yaml_tag = u'!include'
yaml_tag = u"!include"
_new = YamlInclude
class YamlIncludeRawDeprecated(DeprecatedTag):
yaml_tag = u'!include-raw'
yaml_tag = u"!include-raw"
_new = YamlIncludeRaw
class YamlIncludeRawEscapeDeprecated(DeprecatedTag):
yaml_tag = u'!include-raw-escape'
yaml_tag = u"!include-raw-escape"
_new = YamlIncludeRawEscape
@@ -525,8 +547,7 @@ class Jinja2Loader(CustomLoader):
def __init__(self, contents, search_path):
self._template = jinja2.Template(contents)
self._template.environment.undefined = jinja2.StrictUndefined
self._template.environment.loader = jinja2.FileSystemLoader(
search_path)
self._template.environment.loader = jinja2.FileSystemLoader(search_path)
self._loader = self._template.environment.loader
def format(self, **kwargs):
@@ -539,11 +560,12 @@ class Jinja2Loader(CustomLoader):
class CustomLoaderCollection(object):
"""Helper class to format a collection of CustomLoader objects"""
def __init__(self, sequence):
self._data = sequence
def format(self, *args, **kwargs):
return u'\n'.join(item.format(*args, **kwargs) for item in self._data)
return u"\n".join(item.format(*args, **kwargs) for item in self._data)
class LazyLoader(CustomLoader):
@@ -564,8 +586,8 @@ class LazyLoader(CustomLoader):
def format(self, *args, **kwargs):
node = yaml.ScalarNode(
tag=self._node.tag,
value=self._node.value.format(*args, **kwargs))
tag=self._node.tag, value=self._node.value.format(*args, **kwargs)
)
return self._cls.from_yaml(self._loader, node)

File diff suppressed because it is too large Load Diff

View File

@@ -123,88 +123,85 @@ class General(jenkins_jobs.modules.base.Base):
logrotate_warn_issued = False
def gen_xml(self, xml, data):
jdk = data.get('jdk', None)
jdk = data.get("jdk", None)
if jdk:
XML.SubElement(xml, 'jdk').text = jdk
XML.SubElement(xml, 'actions')
desc_text = data.get('description', None)
XML.SubElement(xml, "jdk").text = jdk
XML.SubElement(xml, "actions")
desc_text = data.get("description", None)
if desc_text is not None:
description = XML.SubElement(xml, 'description')
description = XML.SubElement(xml, "description")
description.text = desc_text
XML.SubElement(xml, 'keepDependencies').text = 'false'
XML.SubElement(xml, "keepDependencies").text = "false"
# Need to ensure we support the None parameter to allow disabled to
# remain the last setting if the user purposely adds and then removes
# the disabled parameter.
# See: http://lists.openstack.org/pipermail/openstack-infra/2016-March/003980.html # noqa
disabled = data.get('disabled', None)
disabled = data.get("disabled", None)
if disabled is not None:
XML.SubElement(xml, 'disabled').text = str(disabled).lower()
XML.SubElement(xml, "disabled").text = str(disabled).lower()
if 'display-name' in data:
XML.SubElement(xml, 'displayName').text = data['display-name']
if data.get('block-downstream'):
XML.SubElement(xml,
'blockBuildWhenDownstreamBuilding').text = 'true'
if "display-name" in data:
XML.SubElement(xml, "displayName").text = data["display-name"]
if data.get("block-downstream"):
XML.SubElement(xml, "blockBuildWhenDownstreamBuilding").text = "true"
else:
XML.SubElement(xml,
'blockBuildWhenDownstreamBuilding').text = 'false'
if data.get('block-upstream'):
XML.SubElement(xml,
'blockBuildWhenUpstreamBuilding').text = 'true'
XML.SubElement(xml, "blockBuildWhenDownstreamBuilding").text = "false"
if data.get("block-upstream"):
XML.SubElement(xml, "blockBuildWhenUpstreamBuilding").text = "true"
else:
XML.SubElement(xml,
'blockBuildWhenUpstreamBuilding').text = 'false'
authtoken = data.get('auth-token', None)
XML.SubElement(xml, "blockBuildWhenUpstreamBuilding").text = "false"
authtoken = data.get("auth-token", None)
if authtoken is not None:
XML.SubElement(xml, 'authToken').text = authtoken
if data.get('concurrent'):
XML.SubElement(xml, 'concurrentBuild').text = 'true'
XML.SubElement(xml, "authToken").text = authtoken
if data.get("concurrent"):
XML.SubElement(xml, "concurrentBuild").text = "true"
else:
XML.SubElement(xml, 'concurrentBuild').text = 'false'
if 'workspace' in data:
XML.SubElement(xml, 'customWorkspace').text = \
str(data['workspace'])
if (xml.tag == 'matrix-project') and ('child-workspace' in data):
XML.SubElement(xml, 'childCustomWorkspace').text = \
str(data['child-workspace'])
if 'quiet-period' in data:
XML.SubElement(xml, 'quietPeriod').text = str(data['quiet-period'])
node = data.get('node', None)
XML.SubElement(xml, "concurrentBuild").text = "false"
if "workspace" in data:
XML.SubElement(xml, "customWorkspace").text = str(data["workspace"])
if (xml.tag == "matrix-project") and ("child-workspace" in data):
XML.SubElement(xml, "childCustomWorkspace").text = str(
data["child-workspace"]
)
if "quiet-period" in data:
XML.SubElement(xml, "quietPeriod").text = str(data["quiet-period"])
node = data.get("node", None)
if node:
XML.SubElement(xml, 'assignedNode').text = node
XML.SubElement(xml, 'canRoam').text = 'false'
XML.SubElement(xml, "assignedNode").text = node
XML.SubElement(xml, "canRoam").text = "false"
else:
XML.SubElement(xml, 'canRoam').text = 'true'
if 'retry-count' in data:
XML.SubElement(xml, 'scmCheckoutRetryCount').text = \
str(data['retry-count'])
XML.SubElement(xml, "canRoam").text = "true"
if "retry-count" in data:
XML.SubElement(xml, "scmCheckoutRetryCount").text = str(data["retry-count"])
if 'logrotate' in data:
if "logrotate" in data:
if not self.logrotate_warn_issued:
logging.warning('logrotate is deprecated on jenkins>=1.637,'
' the property build-discarder on newer'
' jenkins instead')
logging.warning(
"logrotate is deprecated on jenkins>=1.637,"
" the property build-discarder on newer"
" jenkins instead"
)
self.logrotate_warn_issued = True
lr_xml = XML.SubElement(xml, 'logRotator')
logrotate = data['logrotate']
lr_days = XML.SubElement(lr_xml, 'daysToKeep')
lr_days.text = str(logrotate.get('daysToKeep', -1))
lr_num = XML.SubElement(lr_xml, 'numToKeep')
lr_num.text = str(logrotate.get('numToKeep', -1))
lr_adays = XML.SubElement(lr_xml, 'artifactDaysToKeep')
lr_adays.text = str(logrotate.get('artifactDaysToKeep', -1))
lr_anum = XML.SubElement(lr_xml, 'artifactNumToKeep')
lr_anum.text = str(logrotate.get('artifactNumToKeep', -1))
lr_xml = XML.SubElement(xml, "logRotator")
logrotate = data["logrotate"]
lr_days = XML.SubElement(lr_xml, "daysToKeep")
lr_days.text = str(logrotate.get("daysToKeep", -1))
lr_num = XML.SubElement(lr_xml, "numToKeep")
lr_num.text = str(logrotate.get("numToKeep", -1))
lr_adays = XML.SubElement(lr_xml, "artifactDaysToKeep")
lr_adays.text = str(logrotate.get("artifactDaysToKeep", -1))
lr_anum = XML.SubElement(lr_xml, "artifactNumToKeep")
lr_anum.text = str(logrotate.get("artifactNumToKeep", -1))
if 'raw' in data:
raw(self.registry, xml, data['raw'])
if "raw" in data:
raw(self.registry, xml, data["raw"])
def raw(registry, xml_parent, data):
# documented in definition.rst since includes and docs is not working well
# For cross cutting method like this
root = XML.fromstring(data.get('xml'))
root = XML.fromstring(data.get("xml"))
remove_ignorable_whitespace(root)
xml_parent.append(root)

View File

@@ -29,59 +29,62 @@ def build_trends_publisher(plugin_name, xml_element, data):
"""Appends the status thresholds.
"""
for status in ['unstable', 'failed']:
for status in ["unstable", "failed"]:
status_data = data.get(status, {})
limits = [
('total-all', 'TotalAll'),
('total-high', 'TotalHigh'),
('total-normal', 'TotalNormal'),
('total-low', 'TotalLow')]
("total-all", "TotalAll"),
("total-high", "TotalHigh"),
("total-normal", "TotalNormal"),
("total-low", "TotalLow"),
]
if only_totals is False:
limits.extend([
('new-all', 'NewAll'),
('new-high', 'NewHigh'),
('new-normal', 'NewNormal'),
('new-low', 'NewLow')])
limits.extend(
[
("new-all", "NewAll"),
("new-high", "NewHigh"),
("new-normal", "NewNormal"),
("new-low", "NewLow"),
]
)
for key, tag_suffix in limits:
tag_name = status + tag_suffix
XML.SubElement(element, tag_name).text = str(
status_data.get(key, ''))
XML.SubElement(element, tag_name).text = str(status_data.get(key, ""))
# Tuples containing: setting name, tag name, default value
settings = [
('healthy', 'healthy', ''),
('unhealthy', 'unHealthy', ''),
('health-threshold', 'thresholdLimit', 'low'),
('plugin-name', 'pluginName', plugin_name),
('default-encoding', 'defaultEncoding', ''),
('can-run-on-failed', 'canRunOnFailed', False),
('use-stable-build-as-reference', 'useStableBuildAsReference', False),
('use-previous-build-as-reference',
'usePreviousBuildAsReference', False),
('use-delta-values', 'useDeltaValues', False),
('thresholds', 'thresholds', {}),
('should-detect-modules', 'shouldDetectModules', False),
('dont-compute-new', 'dontComputeNew', True),
('do-not-resolve-relative-paths', 'doNotResolveRelativePaths', False),
('pattern', 'pattern', '')]
("healthy", "healthy", ""),
("unhealthy", "unHealthy", ""),
("health-threshold", "thresholdLimit", "low"),
("plugin-name", "pluginName", plugin_name),
("default-encoding", "defaultEncoding", ""),
("can-run-on-failed", "canRunOnFailed", False),
("use-stable-build-as-reference", "useStableBuildAsReference", False),
("use-previous-build-as-reference", "usePreviousBuildAsReference", False),
("use-delta-values", "useDeltaValues", False),
("thresholds", "thresholds", {}),
("should-detect-modules", "shouldDetectModules", False),
("dont-compute-new", "dontComputeNew", True),
("do-not-resolve-relative-paths", "doNotResolveRelativePaths", False),
("pattern", "pattern", ""),
]
thresholds = ['low', 'normal', 'high']
thresholds = ["low", "normal", "high"]
for key, tag_name, default in settings:
xml_config = XML.SubElement(xml_element, tag_name)
config_value = data.get(key, default)
if key == 'thresholds':
if key == "thresholds":
append_thresholds(
xml_config,
config_value,
data.get('dont-compute-new', True))
elif key == 'health-threshold' and config_value not in thresholds:
raise JenkinsJobsException("health-threshold must be one of %s" %
", ".join(thresholds))
xml_config, config_value, data.get("dont-compute-new", True)
)
elif key == "health-threshold" and config_value not in thresholds:
raise JenkinsJobsException(
"health-threshold must be one of %s" % ", ".join(thresholds)
)
else:
if isinstance(default, bool):
xml_config.text = str(config_value).lower()
@@ -91,379 +94,385 @@ def build_trends_publisher(plugin_name, xml_element, data):
def config_file_provider_builder(xml_parent, data):
"""Builder / Wrapper helper"""
xml_files = XML.SubElement(xml_parent, 'managedFiles')
xml_files = XML.SubElement(xml_parent, "managedFiles")
files = data.get('files', [])
files = data.get("files", [])
for file in files:
xml_file = XML.SubElement(xml_files, 'org.jenkinsci.plugins.'
'configfiles.buildwrapper.ManagedFile')
xml_file = XML.SubElement(
xml_files, "org.jenkinsci.plugins." "configfiles.buildwrapper.ManagedFile"
)
mapping = [
('file-id', 'fileId', None),
('target', 'targetLocation', ''),
('variable', 'variable', ''),
('replace-tokens', 'replaceTokens', False),
("file-id", "fileId", None),
("target", "targetLocation", ""),
("variable", "variable", ""),
("replace-tokens", "replaceTokens", False),
]
convert_mapping_to_xml(xml_file, file, mapping, fail_required=True)
def config_file_provider_settings(xml_parent, data):
SETTINGS_TYPES = ['file', 'cfp']
SETTINGS_TYPES = ["file", "cfp"]
settings = {
'default-settings':
'jenkins.mvn.DefaultSettingsProvider',
'settings':
'jenkins.mvn.FilePathSettingsProvider',
'config-file-provider-settings':
'org.jenkinsci.plugins.configfiles.maven.job.MvnSettingsProvider',
'default-global-settings':
'jenkins.mvn.DefaultGlobalSettingsProvider',
'global-settings':
'jenkins.mvn.FilePathGlobalSettingsProvider',
'config-file-provider-global-settings':
'org.jenkinsci.plugins.configfiles.maven.job.'
'MvnGlobalSettingsProvider',
"default-settings": "jenkins.mvn.DefaultSettingsProvider",
"settings": "jenkins.mvn.FilePathSettingsProvider",
"config-file-provider-settings": "org.jenkinsci.plugins.configfiles.maven.job.MvnSettingsProvider",
"default-global-settings": "jenkins.mvn.DefaultGlobalSettingsProvider",
"global-settings": "jenkins.mvn.FilePathGlobalSettingsProvider",
"config-file-provider-global-settings": "org.jenkinsci.plugins.configfiles.maven.job."
"MvnGlobalSettingsProvider",
}
if 'settings' in data:
if "settings" in data:
# Support for Config File Provider
settings_file = str(data['settings'])
settings_type = data.get('settings-type', 'file')
settings_file = str(data["settings"])
settings_type = data.get("settings-type", "file")
# For cfp versions <2.10.0 we are able to detect cfp via the config
# settings name.
text = 'org.jenkinsci.plugins.configfiles.maven.MavenSettingsConfig'
text = "org.jenkinsci.plugins.configfiles.maven.MavenSettingsConfig"
if settings_file.startswith(text):
settings_type = 'cfp'
settings_type = "cfp"
if settings_type == 'file':
if settings_type == "file":
lsettings = XML.SubElement(
xml_parent, 'settings',
{'class': settings['settings']})
XML.SubElement(lsettings, 'path').text = settings_file
elif settings_type == 'cfp':
xml_parent, "settings", {"class": settings["settings"]}
)
XML.SubElement(lsettings, "path").text = settings_file
elif settings_type == "cfp":
lsettings = XML.SubElement(
xml_parent, 'settings',
{'class': settings['config-file-provider-settings']})
XML.SubElement(lsettings, 'settingsConfigId').text = settings_file
xml_parent,
"settings",
{"class": settings["config-file-provider-settings"]},
)
XML.SubElement(lsettings, "settingsConfigId").text = settings_file
else:
raise InvalidAttributeError(
'settings-type', settings_type, SETTINGS_TYPES)
raise InvalidAttributeError("settings-type", settings_type, SETTINGS_TYPES)
else:
XML.SubElement(xml_parent, 'settings',
{'class': settings['default-settings']})
XML.SubElement(xml_parent, "settings", {"class": settings["default-settings"]})
if 'global-settings' in data:
if "global-settings" in data:
# Support for Config File Provider
global_settings_file = str(data['global-settings'])
global_settings_type = data.get('global-settings-type', 'file')
global_settings_file = str(data["global-settings"])
global_settings_type = data.get("global-settings-type", "file")
# For cfp versions <2.10.0 we are able to detect cfp via the config
# settings name.
text = ('org.jenkinsci.plugins.configfiles.maven.'
'GlobalMavenSettingsConfig')
text = "org.jenkinsci.plugins.configfiles.maven." "GlobalMavenSettingsConfig"
if global_settings_file.startswith(text):
global_settings_type = 'cfp'
global_settings_type = "cfp"
if global_settings_type == 'file':
gsettings = XML.SubElement(xml_parent, 'globalSettings',
{'class': settings['global-settings']})
XML.SubElement(gsettings, 'path').text = global_settings_file
elif global_settings_type == 'cfp':
if global_settings_type == "file":
gsettings = XML.SubElement(
xml_parent, 'globalSettings',
{'class': settings['config-file-provider-global-settings']})
XML.SubElement(
gsettings,
'settingsConfigId').text = global_settings_file
xml_parent, "globalSettings", {"class": settings["global-settings"]}
)
XML.SubElement(gsettings, "path").text = global_settings_file
elif global_settings_type == "cfp":
gsettings = XML.SubElement(
xml_parent,
"globalSettings",
{"class": settings["config-file-provider-global-settings"]},
)
XML.SubElement(gsettings, "settingsConfigId").text = global_settings_file
else:
raise InvalidAttributeError(
'settings-type', global_settings_type, SETTINGS_TYPES)
"settings-type", global_settings_type, SETTINGS_TYPES
)
else:
XML.SubElement(xml_parent, 'globalSettings',
{'class': settings['default-global-settings']})
XML.SubElement(
xml_parent, "globalSettings", {"class": settings["default-global-settings"]}
)
def copyartifact_build_selector(xml_parent, data, select_tag='selector'):
def copyartifact_build_selector(xml_parent, data, select_tag="selector"):
select = data.get('which-build', 'last-successful')
select = data.get("which-build", "last-successful")
selectdict = {
'last-successful': 'StatusBuildSelector',
'last-completed': 'LastCompletedBuildSelector',
'specific-build': 'SpecificBuildSelector',
'last-saved': 'SavedBuildSelector',
'upstream-build': 'TriggeredBuildSelector',
'permalink': 'PermalinkBuildSelector',
'workspace-latest': 'WorkspaceSelector',
'build-param': 'ParameterizedBuildSelector',
'downstream-build': 'DownstreamBuildSelector',
'multijob-build': 'MultiJobBuildSelector'
"last-successful": "StatusBuildSelector",
"last-completed": "LastCompletedBuildSelector",
"specific-build": "SpecificBuildSelector",
"last-saved": "SavedBuildSelector",
"upstream-build": "TriggeredBuildSelector",
"permalink": "PermalinkBuildSelector",
"workspace-latest": "WorkspaceSelector",
"build-param": "ParameterizedBuildSelector",
"downstream-build": "DownstreamBuildSelector",
"multijob-build": "MultiJobBuildSelector",
}
if select not in selectdict:
raise InvalidAttributeError('which-build',
select,
selectdict.keys())
permalink = data.get('permalink', 'last')
permalinkdict = {'last': 'lastBuild',
'last-stable': 'lastStableBuild',
'last-successful': 'lastSuccessfulBuild',
'last-failed': 'lastFailedBuild',
'last-unstable': 'lastUnstableBuild',
'last-unsuccessful': 'lastUnsuccessfulBuild'}
raise InvalidAttributeError("which-build", select, selectdict.keys())
permalink = data.get("permalink", "last")
permalinkdict = {
"last": "lastBuild",
"last-stable": "lastStableBuild",
"last-successful": "lastSuccessfulBuild",
"last-failed": "lastFailedBuild",
"last-unstable": "lastUnstableBuild",
"last-unsuccessful": "lastUnsuccessfulBuild",
}
if permalink not in permalinkdict:
raise InvalidAttributeError('permalink',
permalink,
permalinkdict.keys())
if select == 'multijob-build':
selector = XML.SubElement(xml_parent, select_tag,
{'class':
'com.tikal.jenkins.plugins.multijob.' +
selectdict[select]})
raise InvalidAttributeError("permalink", permalink, permalinkdict.keys())
if select == "multijob-build":
selector = XML.SubElement(
xml_parent,
select_tag,
{"class": "com.tikal.jenkins.plugins.multijob." + selectdict[select]},
)
else:
selector = XML.SubElement(xml_parent, select_tag,
{'class':
'hudson.plugins.copyartifact.' +
selectdict[select]})
selector = XML.SubElement(
xml_parent,
select_tag,
{"class": "hudson.plugins.copyartifact." + selectdict[select]},
)
mapping = []
if select == 'specific-build':
mapping.append(('build-number', 'buildNumber', ''))
if select == 'last-successful':
mapping.append(('stable', 'stable', False))
if select == 'upstream-build':
if select == "specific-build":
mapping.append(("build-number", "buildNumber", ""))
if select == "last-successful":
mapping.append(("stable", "stable", False))
if select == "upstream-build":
mapping.append(
('fallback-to-last-successful', 'fallbackToLastSuccessful', False))
if select == 'permalink':
mapping.append(('', 'id', permalinkdict[permalink]))
if select == 'build-param':
mapping.append(('param', 'parameterName', ''))
if select == 'downstream-build':
mapping.append(
('upstream-project-name', 'upstreamProjectName', ''))
mapping.append(
('upstream-build-number', 'upstreamBuildNumber', ''))
("fallback-to-last-successful", "fallbackToLastSuccessful", False)
)
if select == "permalink":
mapping.append(("", "id", permalinkdict[permalink]))
if select == "build-param":
mapping.append(("param", "parameterName", ""))
if select == "downstream-build":
mapping.append(("upstream-project-name", "upstreamProjectName", ""))
mapping.append(("upstream-build-number", "upstreamBuildNumber", ""))
convert_mapping_to_xml(selector, data, mapping, fail_required=False)
def findbugs_settings(xml_parent, data):
# General Options
mapping = [
('rank-priority', 'isRankActivated', False),
('include-files', 'includePattern', ''),
('exclude-files', 'excludePattern', ''),
("rank-priority", "isRankActivated", False),
("include-files", "includePattern", ""),
("exclude-files", "excludePattern", ""),
]
convert_mapping_to_xml(xml_parent, data, mapping, fail_required=True)
def get_value_from_yaml_or_config_file(key, section, data, jjb_config):
return jjb_config.get_plugin_config(section, key, data.get(key, ''))
return jjb_config.get_plugin_config(section, key, data.get(key, ""))
def cloudformation_region_dict():
region_dict = {'us-east-1': 'US_East_Northern_Virginia',
'us-west-1': 'US_WEST_Northern_California',
'us-west-2': 'US_WEST_Oregon',
'eu-central-1': 'EU_Frankfurt',
'eu-west-1': 'EU_Ireland',
'ap-southeast-1': 'Asia_Pacific_Singapore',
'ap-southeast-2': 'Asia_Pacific_Sydney',
'ap-northeast-1': 'Asia_Pacific_Tokyo',
'sa-east-1': 'South_America_Sao_Paulo'}
region_dict = {
"us-east-1": "US_East_Northern_Virginia",
"us-west-1": "US_WEST_Northern_California",
"us-west-2": "US_WEST_Oregon",
"eu-central-1": "EU_Frankfurt",
"eu-west-1": "EU_Ireland",
"ap-southeast-1": "Asia_Pacific_Singapore",
"ap-southeast-2": "Asia_Pacific_Sydney",
"ap-northeast-1": "Asia_Pacific_Tokyo",
"sa-east-1": "South_America_Sao_Paulo",
}
return region_dict
def cloudformation_init(xml_parent, data, xml_tag):
cloudformation = XML.SubElement(
xml_parent, 'com.syncapse.jenkinsci.'
'plugins.awscloudformationwrapper.' + xml_tag)
return XML.SubElement(cloudformation, 'stacks')
xml_parent,
"com.syncapse.jenkinsci." "plugins.awscloudformationwrapper." + xml_tag,
)
return XML.SubElement(cloudformation, "stacks")
def cloudformation_stack(xml_parent, stack, xml_tag, stacks, region_dict):
if 'name' not in stack or stack['name'] == '':
raise MissingAttributeError('name')
if "name" not in stack or stack["name"] == "":
raise MissingAttributeError("name")
step = XML.SubElement(
stacks, 'com.syncapse.jenkinsci.plugins.'
'awscloudformationwrapper.' + xml_tag)
stacks, "com.syncapse.jenkinsci.plugins." "awscloudformationwrapper." + xml_tag
)
if xml_tag == 'SimpleStackBean':
mapping = [('prefix', 'isPrefixSelected', False)]
if xml_tag == "SimpleStackBean":
mapping = [("prefix", "isPrefixSelected", False)]
else:
parameters_value = ','.join(stack.get('parameters', []))
parameters_value = ",".join(stack.get("parameters", []))
mapping = [
('description', 'description', ''),
('', 'parameters', parameters_value),
('timeout', 'timeout', '0'),
('sleep', 'sleep', '0'),
('recipe', 'cloudFormationRecipe', None)]
("description", "description", ""),
("", "parameters", parameters_value),
("timeout", "timeout", "0"),
("sleep", "sleep", "0"),
("recipe", "cloudFormationRecipe", None),
]
cloudformation_stack_mapping = [
('name', 'stackName', None),
('access-key', 'awsAccessKey', None),
('secret-key', 'awsSecretKey', None),
('region', 'awsRegion', None, region_dict)]
("name", "stackName", None),
("access-key", "awsAccessKey", None),
("secret-key", "awsSecretKey", None),
("region", "awsRegion", None, region_dict),
]
for map in mapping:
cloudformation_stack_mapping.append(map)
convert_mapping_to_xml(step, stack,
cloudformation_stack_mapping, fail_required=True)
convert_mapping_to_xml(
step, stack, cloudformation_stack_mapping, fail_required=True
)
def include_exclude_patterns(xml_parent, data, yaml_prefix,
xml_elem_name):
def include_exclude_patterns(xml_parent, data, yaml_prefix, xml_elem_name):
xml_element = XML.SubElement(xml_parent, xml_elem_name)
XML.SubElement(xml_element, 'includePatterns').text = ','.join(
data.get(yaml_prefix + '-include-patterns', []))
XML.SubElement(xml_element, 'excludePatterns').text = ','.join(
data.get(yaml_prefix + '-exclude-patterns', []))
XML.SubElement(xml_element, "includePatterns").text = ",".join(
data.get(yaml_prefix + "-include-patterns", [])
)
XML.SubElement(xml_element, "excludePatterns").text = ",".join(
data.get(yaml_prefix + "-exclude-patterns", [])
)
def artifactory_deployment_patterns(xml_parent, data):
include_exclude_patterns(xml_parent, data, 'deployment',
'artifactDeploymentPatterns')
include_exclude_patterns(
xml_parent, data, "deployment", "artifactDeploymentPatterns"
)
def artifactory_env_vars_patterns(xml_parent, data):
include_exclude_patterns(xml_parent, data, 'env-vars',
'envVarsPatterns')
include_exclude_patterns(xml_parent, data, "env-vars", "envVarsPatterns")
def artifactory_optional_props(xml_parent, data, target):
optional_str_props = [
('scopes', 'scopes'),
('violationRecipients', 'violation-recipients'),
('blackDuckAppName', 'black-duck-app-name'),
('blackDuckAppVersion', 'black-duck-app-version'),
('blackDuckReportRecipients', 'black-duck-report-recipients'),
('blackDuckScopes', 'black-duck-scopes')
("scopes", "scopes"),
("violationRecipients", "violation-recipients"),
("blackDuckAppName", "black-duck-app-name"),
("blackDuckAppVersion", "black-duck-app-version"),
("blackDuckReportRecipients", "black-duck-report-recipients"),
("blackDuckScopes", "black-duck-scopes"),
]
for (xml_prop, yaml_prop) in optional_str_props:
XML.SubElement(xml_parent, xml_prop).text = data.get(
yaml_prop, '')
XML.SubElement(xml_parent, xml_prop).text = data.get(yaml_prop, "")
common_bool_props = [
# yaml property name, xml property name, default value
('deploy-artifacts', 'deployArtifacts', True),
('discard-old-builds', 'discardOldBuilds', False),
('discard-build-artifacts', 'discardBuildArtifacts', False),
('publish-build-info', 'deployBuildInfo', False),
('env-vars-include', 'includeEnvVars', False),
('run-checks', 'runChecks', False),
('include-publish-artifacts', 'includePublishArtifacts', False),
('license-auto-discovery', 'licenseAutoDiscovery', True),
('enable-issue-tracker-integration', 'enableIssueTrackerIntegration',
False),
('aggregate-build-issues', 'aggregateBuildIssues', False),
('black-duck-run-checks', 'blackDuckRunChecks', False),
('black-duck-include-published-artifacts',
'blackDuckIncludePublishedArtifacts', False),
('auto-create-missing-component-requests',
'autoCreateMissingComponentRequests', True),
('auto-discard-stale-component-requests',
'autoDiscardStaleComponentRequests', True),
('filter-excluded-artifacts-from-build',
'filterExcludedArtifactsFromBuild', False)
("deploy-artifacts", "deployArtifacts", True),
("discard-old-builds", "discardOldBuilds", False),
("discard-build-artifacts", "discardBuildArtifacts", False),
("publish-build-info", "deployBuildInfo", False),
("env-vars-include", "includeEnvVars", False),
("run-checks", "runChecks", False),
("include-publish-artifacts", "includePublishArtifacts", False),
("license-auto-discovery", "licenseAutoDiscovery", True),
("enable-issue-tracker-integration", "enableIssueTrackerIntegration", False),
("aggregate-build-issues", "aggregateBuildIssues", False),
("black-duck-run-checks", "blackDuckRunChecks", False),
(
"black-duck-include-published-artifacts",
"blackDuckIncludePublishedArtifacts",
False,
),
(
"auto-create-missing-component-requests",
"autoCreateMissingComponentRequests",
True,
),
(
"auto-discard-stale-component-requests",
"autoDiscardStaleComponentRequests",
True,
),
(
"filter-excluded-artifacts-from-build",
"filterExcludedArtifactsFromBuild",
False,
),
]
convert_mapping_to_xml(
xml_parent, data, common_bool_props, fail_required=True)
convert_mapping_to_xml(xml_parent, data, common_bool_props, fail_required=True)
if 'wrappers' in target:
if "wrappers" in target:
wrapper_bool_props = [
('enable-resolve-artifacts', 'enableResolveArtifacts', False),
('disable-license-auto-discovery',
'disableLicenseAutoDiscovery', False),
('record-all-dependencies',
'recordAllDependencies', False)
("enable-resolve-artifacts", "enableResolveArtifacts", False),
("disable-license-auto-discovery", "disableLicenseAutoDiscovery", False),
("record-all-dependencies", "recordAllDependencies", False),
]
convert_mapping_to_xml(
xml_parent, data, wrapper_bool_props, fail_required=True)
convert_mapping_to_xml(xml_parent, data, wrapper_bool_props, fail_required=True)
if 'publishers' in target:
if "publishers" in target:
publisher_bool_props = [
('even-if-unstable', 'evenIfUnstable', False),
('pass-identified-downstream', 'passIdentifiedDownstream', False),
('allow-promotion-of-non-staged-builds',
'allowPromotionOfNonStagedBuilds', False)
("even-if-unstable", "evenIfUnstable", False),
("pass-identified-downstream", "passIdentifiedDownstream", False),
(
"allow-promotion-of-non-staged-builds",
"allowPromotionOfNonStagedBuilds",
False,
),
]
convert_mapping_to_xml(
xml_parent, data, publisher_bool_props, fail_required=True)
xml_parent, data, publisher_bool_props, fail_required=True
)
def artifactory_common_details(details, data):
mapping = [
('name', 'artifactoryName', ''),
('url', 'artifactoryUrl', ''),
]
mapping = [("name", "artifactoryName", ""), ("url", "artifactoryUrl", "")]
convert_mapping_to_xml(details, data, mapping, fail_required=True)
def artifactory_repository(xml_parent, data, target):
if 'release' in target:
if "release" in target:
release_mapping = [
('deploy-release-repo-key', 'keyFromText', ''),
('deploy-release-repo-key', 'keyFromSelect', ''),
('deploy-dynamic-mode', 'dynamicMode', False),
("deploy-release-repo-key", "keyFromText", ""),
("deploy-release-repo-key", "keyFromSelect", ""),
("deploy-dynamic-mode", "dynamicMode", False),
]
convert_mapping_to_xml(
xml_parent, data, release_mapping, fail_required=True)
convert_mapping_to_xml(xml_parent, data, release_mapping, fail_required=True)
if 'snapshot' in target:
if "snapshot" in target:
snapshot_mapping = [
('deploy-snapshot-repo-key', 'keyFromText', ''),
('deploy-snapshot-repo-key', 'keyFromSelect', ''),
('deploy-dynamic-mode', 'dynamicMode', False),
("deploy-snapshot-repo-key", "keyFromText", ""),
("deploy-snapshot-repo-key", "keyFromSelect", ""),
("deploy-dynamic-mode", "dynamicMode", False),
]
convert_mapping_to_xml(
xml_parent, data, snapshot_mapping, fail_required=True)
convert_mapping_to_xml(xml_parent, data, snapshot_mapping, fail_required=True)
def append_git_revision_config(parent, config_def):
params = XML.SubElement(
parent, 'hudson.plugins.git.GitRevisionBuildParameters')
params = XML.SubElement(parent, "hudson.plugins.git.GitRevisionBuildParameters")
try:
# If git-revision is a boolean, the get() will
# throw an AttributeError
combine_commits = str(
config_def.get('combine-queued-commits', False)).lower()
combine_commits = str(config_def.get("combine-queued-commits", False)).lower()
except AttributeError:
combine_commits = 'false'
combine_commits = "false"
XML.SubElement(params, 'combineQueuedCommits').text = combine_commits
XML.SubElement(params, "combineQueuedCommits").text = combine_commits
def test_fairy_common(xml_element, data):
xml_element.set('plugin', 'TestFairy')
valid_max_duration = ['10m', '60m', '300m', '1440m']
xml_element.set("plugin", "TestFairy")
valid_max_duration = ["10m", "60m", "300m", "1440m"]
valid_interval = [1, 2, 5]
valid_video_quality = ['high', 'medium', 'low']
valid_video_quality = ["high", "medium", "low"]
mappings = [
# General
('apikey', 'apiKey', None),
('appfile', 'appFile', None),
('tester-groups', 'testersGroups', ''),
('notify-testers', 'notifyTesters', True),
('autoupdate', 'autoUpdate', True),
("apikey", "apiKey", None),
("appfile", "appFile", None),
("tester-groups", "testersGroups", ""),
("notify-testers", "notifyTesters", True),
("autoupdate", "autoUpdate", True),
# Session
('max-duration', 'maxDuration', '10m', valid_max_duration),
('record-on-background', 'recordOnBackground', False),
('data-only-wifi', 'dataOnlyWifi', False),
("max-duration", "maxDuration", "10m", valid_max_duration),
("record-on-background", "recordOnBackground", False),
("data-only-wifi", "dataOnlyWifi", False),
# Video
('video-enabled', 'isVideoEnabled', True),
('screenshot-interval', 'screenshotInterval', 1, valid_interval),
('video-quality', 'videoQuality', 'high', valid_video_quality),
("video-enabled", "isVideoEnabled", True),
("screenshot-interval", "screenshotInterval", 1, valid_interval),
("video-quality", "videoQuality", "high", valid_video_quality),
# Metrics
('cpu', 'cpu', True),
('memory', 'memory', True),
('logs', 'logs', True),
('network', 'network', False),
('phone-signal', 'phoneSignal', False),
('wifi', 'wifi', False),
('gps', 'gps', False),
('battery', 'battery', False),
('opengl', 'openGl', False),
("cpu", "cpu", True),
("memory", "memory", True),
("logs", "logs", True),
("network", "network", False),
("phone-signal", "phoneSignal", False),
("wifi", "wifi", False),
("gps", "gps", False),
("battery", "battery", False),
("opengl", "openGl", False),
# Advanced options
('advanced-options', 'advancedOptions', '')
("advanced-options", "advancedOptions", ""),
]
convert_mapping_to_xml(xml_element, data, mappings, fail_required=True)
@@ -471,25 +480,31 @@ def test_fairy_common(xml_element, data):
def trigger_get_parameter_order(registry, plugin):
logger = logging.getLogger("%s:trigger_get_parameter_order" % __name__)
if str(registry.jjb_config.get_plugin_config(
plugin, 'param_order_from_yaml', True)).lower() == 'false':
if (
str(
registry.jjb_config.get_plugin_config(plugin, "param_order_from_yaml", True)
).lower()
== "false"
):
logger.warning(
"Using deprecated order for parameter sets in %s. It is "
"recommended that you update your job definition instead of "
"enabling use of the old hardcoded order", plugin)
"enabling use of the old hardcoded order",
plugin,
)
# deprecated order
return [
'predefined-parameters',
'git-revision',
'property-file',
'current-parameters',
'node-parameters',
'svn-revision',
'restrict-matrix-project',
'node-label-name',
'node-label',
'boolean-parameters',
"predefined-parameters",
"git-revision",
"property-file",
"current-parameters",
"node-parameters",
"svn-revision",
"restrict-matrix-project",
"node-label-name",
"node-label",
"boolean-parameters",
]
return None
@@ -498,7 +513,7 @@ def trigger_get_parameter_order(registry, plugin):
def trigger_project(tconfigs, project_def, param_order=None):
logger = logging.getLogger("%s:trigger_project" % __name__)
pt_prefix = 'hudson.plugins.parameterizedtrigger.'
pt_prefix = "hudson.plugins.parameterizedtrigger."
if param_order:
parameters = param_order
else:
@@ -509,88 +524,93 @@ def trigger_project(tconfigs, project_def, param_order=None):
if param_value is None:
continue
if param_type == 'predefined-parameters':
params = XML.SubElement(tconfigs, pt_prefix +
'PredefinedBuildParameters')
properties = XML.SubElement(params, 'properties')
if param_type == "predefined-parameters":
params = XML.SubElement(tconfigs, pt_prefix + "PredefinedBuildParameters")
properties = XML.SubElement(params, "properties")
properties.text = param_value
elif param_type == 'git-revision' and param_value:
if 'combine-queued-commits' in project_def:
elif param_type == "git-revision" and param_value:
if "combine-queued-commits" in project_def:
logger.warning(
"'combine-queued-commit' has moved to reside under "
"'git-revision' configuration, please update your "
"configs as support for this will be removed."
)
git_revision = {
'combine-queued-commits':
project_def['combine-queued-commits']
"combine-queued-commits": project_def["combine-queued-commits"]
}
else:
git_revision = project_def['git-revision']
git_revision = project_def["git-revision"]
append_git_revision_config(tconfigs, git_revision)
elif param_type == 'property-file':
params = XML.SubElement(tconfigs,
pt_prefix + 'FileBuildParameters')
elif param_type == "property-file":
params = XML.SubElement(tconfigs, pt_prefix + "FileBuildParameters")
property_file_mapping = [
('property-file', 'propertiesFile', None),
('fail-on-missing', 'failTriggerOnMissing', False)]
convert_mapping_to_xml(params, project_def,
property_file_mapping, fail_required=True)
if 'file-encoding' in project_def:
XML.SubElement(params, 'encoding'
).text = project_def['file-encoding']
if 'use-matrix-child-files' in project_def:
("property-file", "propertiesFile", None),
("fail-on-missing", "failTriggerOnMissing", False),
]
convert_mapping_to_xml(
params, project_def, property_file_mapping, fail_required=True
)
if "file-encoding" in project_def:
XML.SubElement(params, "encoding").text = project_def["file-encoding"]
if "use-matrix-child-files" in project_def:
# TODO: These parameters only affect execution in
# publishers of matrix projects; we should warn if they are
# used in other contexts.
use_matrix_child_files_mapping = [
('use-matrix-child-files', "useMatrixChild", None),
('matrix-child-combination-filter',
"combinationFilter", ''),
('only-exact-matrix-child-runs', "onlyExactRuns", False)]
convert_mapping_to_xml(params, project_def,
use_matrix_child_files_mapping, fail_required=True)
elif param_type == 'current-parameters' and param_value:
XML.SubElement(tconfigs, pt_prefix + 'CurrentBuildParameters')
elif param_type == 'node-parameters' and param_value:
XML.SubElement(tconfigs, pt_prefix + 'NodeParameters')
elif param_type == 'svn-revision' and param_value:
param = XML.SubElement(tconfigs, pt_prefix +
'SubversionRevisionBuildParameters')
XML.SubElement(param, 'includeUpstreamParameters').text = str(
project_def.get('include-upstream', False)).lower()
elif param_type == 'restrict-matrix-project' and param_value:
subset = XML.SubElement(tconfigs, pt_prefix +
'matrix.MatrixSubsetBuildParameters')
XML.SubElement(subset, 'filter'
).text = project_def['restrict-matrix-project']
elif (param_type == 'node-label-name' or
param_type == 'node-label'):
tag_name = ('org.jvnet.jenkins.plugins.nodelabelparameter.'
'parameterizedtrigger.NodeLabelBuildParameter')
("use-matrix-child-files", "useMatrixChild", None),
("matrix-child-combination-filter", "combinationFilter", ""),
("only-exact-matrix-child-runs", "onlyExactRuns", False),
]
convert_mapping_to_xml(
params,
project_def,
use_matrix_child_files_mapping,
fail_required=True,
)
elif param_type == "current-parameters" and param_value:
XML.SubElement(tconfigs, pt_prefix + "CurrentBuildParameters")
elif param_type == "node-parameters" and param_value:
XML.SubElement(tconfigs, pt_prefix + "NodeParameters")
elif param_type == "svn-revision" and param_value:
param = XML.SubElement(
tconfigs, pt_prefix + "SubversionRevisionBuildParameters"
)
XML.SubElement(param, "includeUpstreamParameters").text = str(
project_def.get("include-upstream", False)
).lower()
elif param_type == "restrict-matrix-project" and param_value:
subset = XML.SubElement(
tconfigs, pt_prefix + "matrix.MatrixSubsetBuildParameters"
)
XML.SubElement(subset, "filter").text = project_def[
"restrict-matrix-project"
]
elif param_type == "node-label-name" or param_type == "node-label":
tag_name = (
"org.jvnet.jenkins.plugins.nodelabelparameter."
"parameterizedtrigger.NodeLabelBuildParameter"
)
if tconfigs.find(tag_name) is not None:
# already processed and can only have one
continue
params = XML.SubElement(tconfigs, tag_name)
name = XML.SubElement(params, 'name')
if 'node-label-name' in project_def:
name.text = project_def['node-label-name']
label = XML.SubElement(params, 'nodeLabel')
if 'node-label' in project_def:
label.text = project_def['node-label']
elif param_type == 'boolean-parameters' and param_value:
params = XML.SubElement(tconfigs,
pt_prefix + 'BooleanParameters')
config_tag = XML.SubElement(params, 'configs')
param_tag_text = pt_prefix + 'BooleanParameterConfig'
name = XML.SubElement(params, "name")
if "node-label-name" in project_def:
name.text = project_def["node-label-name"]
label = XML.SubElement(params, "nodeLabel")
if "node-label" in project_def:
label.text = project_def["node-label"]
elif param_type == "boolean-parameters" and param_value:
params = XML.SubElement(tconfigs, pt_prefix + "BooleanParameters")
config_tag = XML.SubElement(params, "configs")
param_tag_text = pt_prefix + "BooleanParameterConfig"
params_list = param_value
for name, value in params_list.items():
param_tag = XML.SubElement(config_tag, param_tag_text)
mapping = [
('', 'name', name),
('', 'value', value or False)]
convert_mapping_to_xml(param_tag, project_def,
mapping, fail_required=True)
mapping = [("", "name", name), ("", "value", value or False)]
convert_mapping_to_xml(
param_tag, project_def, mapping, fail_required=True
)
def convert_mapping_to_xml(parent, data, mapping, fail_required=True):
@@ -661,19 +681,17 @@ def jms_messaging_common(parent, subelement, data):
data is passed to mapper helper function to map yaml fields to XML fields
"""
namespace = XML.SubElement(parent,
subelement)
namespace = XML.SubElement(parent, subelement)
if 'override-topic' in data:
overrides = XML.SubElement(namespace, 'overrides')
XML.SubElement(overrides,
'topic').text = str(data.get('override-topic', ''))
if "override-topic" in data:
overrides = XML.SubElement(namespace, "overrides")
XML.SubElement(overrides, "topic").text = str(data.get("override-topic", ""))
mapping = [
# option, xml name, default value
("provider-name", 'providerName', ''),
("msg-type", 'messageType', 'CodeQualityChecksDone'),
("msg-props", 'messageProperties', ''),
("msg-content", 'messageContent', ''),
("provider-name", "providerName", ""),
("msg-type", "messageType", "CodeQualityChecksDone"),
("msg-props", "messageProperties", ""),
("msg-content", "messageContent", ""),
]
convert_mapping_to_xml(namespace, data, mapping, fail_required=True)

View File

@@ -104,95 +104,99 @@ class HipChat(jenkins_jobs.modules.base.Base):
jjb_config = self.registry.jjb_config
if not self.authToken:
try:
self.authToken = jjb_config.get_plugin_config('hipchat',
'authtoken')
self.authToken = jjb_config.get_plugin_config("hipchat", "authtoken")
# Require that the authtoken is non-null
if self.authToken == '':
if self.authToken == "":
raise jenkins_jobs.errors.JenkinsJobsException(
"Hipchat authtoken must not be a blank string")
except (configparser.NoSectionError,
jenkins_jobs.errors.JenkinsJobsException) as e:
logger.fatal("The configuration file needs a hipchat section" +
" containing authtoken:\n{0}".format(e))
"Hipchat authtoken must not be a blank string"
)
except (
configparser.NoSectionError,
jenkins_jobs.errors.JenkinsJobsException,
) as e:
logger.fatal(
"The configuration file needs a hipchat section"
+ " containing authtoken:\n{0}".format(e)
)
sys.exit(1)
self.jenkinsUrl = jjb_config.get_plugin_config('hipchat', 'url')
self.sendAs = jjb_config.get_plugin_config('hipchat', 'send-as')
self.jenkinsUrl = jjb_config.get_plugin_config("hipchat", "url")
self.sendAs = jjb_config.get_plugin_config("hipchat", "send-as")
def gen_xml(self, xml_parent, data):
hipchat = data.get('hipchat')
if not hipchat or not hipchat.get('enabled', True):
hipchat = data.get("hipchat")
if not hipchat or not hipchat.get("enabled", True):
return
self._load_global_data()
# convert for compatibility before dispatch
if 'room' in hipchat:
if 'rooms' in hipchat:
logger.warning("Ignoring deprecated 'room' as 'rooms' also "
"defined.")
if "room" in hipchat:
if "rooms" in hipchat:
logger.warning("Ignoring deprecated 'room' as 'rooms' also " "defined.")
else:
logger.warning("'room' is deprecated, please use 'rooms'")
hipchat['rooms'] = [hipchat['room']]
hipchat["rooms"] = [hipchat["room"]]
plugin_info = self.registry.get_plugin_info("Jenkins HipChat Plugin")
version = pkg_resources.parse_version(plugin_info.get('version', '0'))
version = pkg_resources.parse_version(plugin_info.get("version", "0"))
if version >= pkg_resources.parse_version("0.1.9"):
publishers = xml_parent.find('publishers')
publishers = xml_parent.find("publishers")
if publishers is None:
publishers = XML.SubElement(xml_parent, 'publishers')
publishers = XML.SubElement(xml_parent, "publishers")
logger.warning(
"'hipchat' module supports the old plugin versions <1.9, "
"newer versions are supported via the 'publishers' module. "
"Please upgrade you job definition")
component = {'hipchat': hipchat}
return self.registry.dispatch('publisher', publishers, component)
"Please upgrade you job definition"
)
component = {"hipchat": hipchat}
return self.registry.dispatch("publisher", publishers, component)
else:
properties = xml_parent.find('properties')
properties = xml_parent.find("properties")
if properties is None:
properties = XML.SubElement(xml_parent, 'properties')
pdefhip = XML.SubElement(properties,
'jenkins.plugins.hipchat.'
'HipChatNotifier_-HipChatJobProperty')
properties = XML.SubElement(xml_parent, "properties")
pdefhip = XML.SubElement(
properties,
"jenkins.plugins.hipchat." "HipChatNotifier_-HipChatJobProperty",
)
room = XML.SubElement(pdefhip, 'room')
if 'rooms' in hipchat:
room.text = ",".join(hipchat['rooms'])
room = XML.SubElement(pdefhip, "room")
if "rooms" in hipchat:
room.text = ",".join(hipchat["rooms"])
# Handle backwards compatibility 'start-notify' but all add an element
# of standardization with notify-*
if hipchat.get('start-notify'):
logger.warning("'start-notify' is deprecated, please use "
"'notify-start'")
XML.SubElement(pdefhip, 'startNotification').text = str(
hipchat.get('notify-start', hipchat.get('start-notify',
False))).lower()
if hipchat.get("start-notify"):
logger.warning("'start-notify' is deprecated, please use " "'notify-start'")
XML.SubElement(pdefhip, "startNotification").text = str(
hipchat.get("notify-start", hipchat.get("start-notify", False))
).lower()
if version >= pkg_resources.parse_version("0.1.5"):
mapping = [
('notify-success', 'notifySuccess', False),
('notify-aborted', 'notifyAborted', False),
('notify-not-built', 'notifyNotBuilt', False),
('notify-unstable', 'notifyUnstable', False),
('notify-failure', 'notifyFailure', False),
('notify-back-to-normal', 'notifyBackToNormal', False),
("notify-success", "notifySuccess", False),
("notify-aborted", "notifyAborted", False),
("notify-not-built", "notifyNotBuilt", False),
("notify-unstable", "notifyUnstable", False),
("notify-failure", "notifyFailure", False),
("notify-back-to-normal", "notifyBackToNormal", False),
]
helpers.convert_mapping_to_xml(pdefhip,
hipchat, mapping, fail_required=True)
helpers.convert_mapping_to_xml(
pdefhip, hipchat, mapping, fail_required=True
)
publishers = xml_parent.find('publishers')
publishers = xml_parent.find("publishers")
if publishers is None:
publishers = XML.SubElement(xml_parent, 'publishers')
hippub = XML.SubElement(publishers,
'jenkins.plugins.hipchat.HipChatNotifier')
publishers = XML.SubElement(xml_parent, "publishers")
hippub = XML.SubElement(publishers, "jenkins.plugins.hipchat.HipChatNotifier")
if version >= pkg_resources.parse_version("0.1.8"):
XML.SubElement(hippub, 'buildServerUrl').text = self.jenkinsUrl
XML.SubElement(hippub, 'sendAs').text = self.sendAs
XML.SubElement(hippub, "buildServerUrl").text = self.jenkinsUrl
XML.SubElement(hippub, "sendAs").text = self.sendAs
else:
XML.SubElement(hippub, 'jenkinsUrl').text = self.jenkinsUrl
XML.SubElement(hippub, "jenkinsUrl").text = self.jenkinsUrl
XML.SubElement(hippub, 'authToken').text = self.authToken
XML.SubElement(hippub, "authToken").text = self.authToken
# The room specified here is the default room. The default is
# redundant in this case since a room must be specified. Leave empty.
XML.SubElement(hippub, 'room').text = ''
XML.SubElement(hippub, "room").text = ""

View File

@@ -12,45 +12,20 @@
# Representation of the hudson.model.Result class
SUCCESS = {
'name': 'SUCCESS',
'ordinal': '0',
'color': 'BLUE',
'complete': True
}
SUCCESS = {"name": "SUCCESS", "ordinal": "0", "color": "BLUE", "complete": True}
UNSTABLE = {
'name': 'UNSTABLE',
'ordinal': '1',
'color': 'YELLOW',
'complete': True
}
UNSTABLE = {"name": "UNSTABLE", "ordinal": "1", "color": "YELLOW", "complete": True}
FAILURE = {
'name': 'FAILURE',
'ordinal': '2',
'color': 'RED',
'complete': True
}
FAILURE = {"name": "FAILURE", "ordinal": "2", "color": "RED", "complete": True}
NOTBUILD = {
'name': 'NOT_BUILD',
'ordinal': '3',
'color': 'NOTBUILD',
'complete': False
}
NOTBUILD = {"name": "NOT_BUILD", "ordinal": "3", "color": "NOTBUILD", "complete": False}
ABORTED = {
'name': 'ABORTED',
'ordinal': '4',
'color': 'ABORTED',
'complete': False
}
ABORTED = {"name": "ABORTED", "ordinal": "4", "color": "ABORTED", "complete": False}
THRESHOLDS = {
'SUCCESS': SUCCESS,
'UNSTABLE': UNSTABLE,
'FAILURE': FAILURE,
'NOT_BUILD': NOTBUILD,
'ABORTED': ABORTED
"SUCCESS": SUCCESS,
"UNSTABLE": UNSTABLE,
"FAILURE": FAILURE,
"NOT_BUILD": NOTBUILD,
"ABORTED": ABORTED,
}

View File

@@ -38,13 +38,14 @@ import jenkins_jobs.modules.base
def base_metadata(registry, xml_parent, data, mtype):
pdef = XML.SubElement(xml_parent, mtype)
XML.SubElement(pdef, 'name').text = data['name']
XML.SubElement(pdef, 'generated').text = 'false'
XML.SubElement(pdef, 'parent', attrib={"class": "job-metadata",
"reference": "../../.."})
XML.SubElement(pdef, "name").text = data["name"]
XML.SubElement(pdef, "generated").text = "false"
XML.SubElement(
pdef, "parent", attrib={"class": "job-metadata", "reference": "../../.."}
)
exposed_to_env = XML.SubElement(pdef, 'exposedToEnvironment')
exposed_to_env.text = str(data.get('expose-to-env', False)).lower()
exposed_to_env = XML.SubElement(pdef, "exposedToEnvironment")
exposed_to_env.text = str(data.get("expose-to-env", False)).lower()
return pdef
@@ -64,10 +65,9 @@ def string_metadata(registry, xml_parent, data):
value: bar
expose-to-env: true
"""
pdef = base_metadata(registry, xml_parent, data,
'metadata-string')
value = data.get('value', '')
XML.SubElement(pdef, 'value').text = value
pdef = base_metadata(registry, xml_parent, data, "metadata-string")
value = data.get("value", "")
XML.SubElement(pdef, "value").text = value
def number_metadata(registry, xml_parent, data):
@@ -86,10 +86,9 @@ def number_metadata(registry, xml_parent, data):
value: 1
expose-to-env: true
"""
pdef = base_metadata(registry, xml_parent, data,
'metadata-number')
value = data.get('value', '')
XML.SubElement(pdef, 'value').text = value
pdef = base_metadata(registry, xml_parent, data, "metadata-number")
value = data.get("value", "")
XML.SubElement(pdef, "value").text = value
def date_metadata(registry, xml_parent, data):
@@ -110,30 +109,28 @@ def date_metadata(registry, xml_parent, data):
timezone: Australia/Melbourne
expose-to-env: true
"""
pdef = base_metadata(registry, xml_parent, data,
'metadata-date')
pdef = base_metadata(registry, xml_parent, data, "metadata-date")
# TODO: convert time from any reasonable format into epoch
mval = XML.SubElement(pdef, 'value')
XML.SubElement(mval, 'time').text = data['time']
XML.SubElement(mval, 'timezone').text = data['timezone']
XML.SubElement(pdef, 'checked').text = 'true'
mval = XML.SubElement(pdef, "value")
XML.SubElement(mval, "time").text = data["time"]
XML.SubElement(mval, "timezone").text = data["timezone"]
XML.SubElement(pdef, "checked").text = "true"
class Metadata(jenkins_jobs.modules.base.Base):
sequence = 21
component_type = 'metadata'
component_list_type = 'metadata'
component_type = "metadata"
component_list_type = "metadata"
def gen_xml(self, xml_parent, data):
properties = xml_parent.find('properties')
properties = xml_parent.find("properties")
if properties is None:
properties = XML.SubElement(xml_parent, 'properties')
properties = XML.SubElement(xml_parent, "properties")
metadata = data.get('metadata', [])
metadata = data.get("metadata", [])
if metadata:
pdefp = XML.SubElement(properties,
'job-metadata', plugin="metadata@1.0b")
pdefs = XML.SubElement(pdefp, 'values')
pdefp = XML.SubElement(properties, "job-metadata", plugin="metadata@1.0b")
pdefs = XML.SubElement(pdefp, "values")
for mdata in metadata:
self.registry.dispatch('metadata', pdefs, mdata)
self.registry.dispatch("metadata", pdefs, mdata)

View File

@@ -52,44 +52,44 @@ def http_endpoint(registry, xml_parent, data):
:language: yaml
"""
endpoint_element = XML.SubElement(xml_parent,
'com.tikal.hudson.plugins.notification.'
'Endpoint')
supported_formats = ['JSON', 'XML']
supported_events = ['started', 'completed', 'finalized', 'all']
fmt = data.get('format', 'JSON').upper()
event = data.get('event', 'all').lower()
endpoint_element = XML.SubElement(
xml_parent, "com.tikal.hudson.plugins.notification." "Endpoint"
)
supported_formats = ["JSON", "XML"]
supported_events = ["started", "completed", "finalized", "all"]
fmt = data.get("format", "JSON").upper()
event = data.get("event", "all").lower()
mapping = [
('', 'format', fmt, supported_formats),
('', 'protocol', 'HTTP'),
('', 'event', event, supported_events),
('timeout', 'timeout', 30000),
('url', 'url', None),
('log', 'loglines', 0),
("", "format", fmt, supported_formats),
("", "protocol", "HTTP"),
("", "event", event, supported_events),
("timeout", "timeout", 30000),
("url", "url", None),
("log", "loglines", 0),
]
helpers.convert_mapping_to_xml(
endpoint_element, data, mapping, fail_required=True)
helpers.convert_mapping_to_xml(endpoint_element, data, mapping, fail_required=True)
class Notifications(jenkins_jobs.modules.base.Base):
sequence = 22
component_type = 'notification'
component_list_type = 'notifications'
component_type = "notification"
component_list_type = "notifications"
def gen_xml(self, xml_parent, data):
properties = xml_parent.find('properties')
properties = xml_parent.find("properties")
if properties is None:
properties = XML.SubElement(xml_parent, 'properties')
properties = XML.SubElement(xml_parent, "properties")
notifications = data.get('notifications', [])
notifications = data.get("notifications", [])
if notifications:
notify_element = XML.SubElement(properties,
'com.tikal.hudson.plugins.'
'notification.'
'HudsonNotificationProperty')
endpoints_element = XML.SubElement(notify_element, 'endpoints')
notify_element = XML.SubElement(
properties,
"com.tikal.hudson.plugins."
"notification."
"HudsonNotificationProperty",
)
endpoints_element = XML.SubElement(notify_element, "endpoints")
for endpoint in notifications:
self.registry.dispatch('notification',
endpoints_element, endpoint)
self.registry.dispatch("notification", endpoints_element, endpoint)

View File

@@ -43,14 +43,14 @@ import jenkins_jobs.modules.helpers as helpers
def base_param(registry, xml_parent, data, do_default, ptype):
pdef = XML.SubElement(xml_parent, ptype)
XML.SubElement(pdef, 'name').text = data['name']
XML.SubElement(pdef, 'description').text = data.get('description', '')
XML.SubElement(pdef, "name").text = data["name"]
XML.SubElement(pdef, "description").text = data.get("description", "")
if do_default:
default = data.get('default', None)
default = data.get("default", None)
if default is not None:
XML.SubElement(pdef, 'defaultValue').text = str(default)
XML.SubElement(pdef, "defaultValue").text = str(default)
else:
XML.SubElement(pdef, 'defaultValue')
XML.SubElement(pdef, "defaultValue")
return pdef
@@ -70,8 +70,9 @@ def string_param(registry, xml_parent, data):
default: bar
description: "A parameter named FOO, defaults to 'bar'."
"""
base_param(registry, xml_parent, data, True,
'hudson.model.StringParameterDefinition')
base_param(
registry, xml_parent, data, True, "hudson.model.StringParameterDefinition"
)
def promoted_param(registry, xml_parent, data):
@@ -92,16 +93,20 @@ def promoted_param(registry, xml_parent, data):
:language: yaml
"""
pdef = base_param(registry, xml_parent, data, False,
'hudson.plugins.promoted__builds.parameters.'
'PromotedBuildParameterDefinition')
pdef = base_param(
registry,
xml_parent,
data,
False,
"hudson.plugins.promoted__builds.parameters."
"PromotedBuildParameterDefinition",
)
try:
XML.SubElement(pdef, 'projectName').text = data['project-name']
XML.SubElement(pdef, "projectName").text = data["project-name"]
except KeyError:
raise MissingAttributeError('project-name')
raise MissingAttributeError("project-name")
XML.SubElement(pdef, 'promotionProcessName').text = data.get(
'promotion-name', None)
XML.SubElement(pdef, "promotionProcessName").text = data.get("promotion-name", None)
def password_param(registry, xml_parent, data):
@@ -120,8 +125,9 @@ def password_param(registry, xml_parent, data):
default: 1HSC0Ts6E161FysGf+e1xasgsHkgleLh09JUTYnipPvw=
description: "A parameter named FOO."
"""
base_param(registry, xml_parent, data, True,
'hudson.model.PasswordParameterDefinition')
base_param(
registry, xml_parent, data, True, "hudson.model.PasswordParameterDefinition"
)
def bool_param(registry, xml_parent, data):
@@ -140,9 +146,10 @@ def bool_param(registry, xml_parent, data):
default: false
description: "A parameter named FOO, defaults to 'false'."
"""
data['default'] = str(data.get('default', False)).lower()
base_param(registry, xml_parent, data, True,
'hudson.model.BooleanParameterDefinition')
data["default"] = str(data.get("default", False)).lower()
base_param(
registry, xml_parent, data, True, "hudson.model.BooleanParameterDefinition"
)
def file_param(registry, xml_parent, data):
@@ -159,8 +166,9 @@ def file_param(registry, xml_parent, data):
name: test.txt
description: "Upload test.txt."
"""
base_param(registry, xml_parent, data, False,
'hudson.model.FileParameterDefinition')
base_param(
registry, xml_parent, data, False, "hudson.model.FileParameterDefinition"
)
def text_param(registry, xml_parent, data):
@@ -179,8 +187,7 @@ def text_param(registry, xml_parent, data):
default: bar
description: "A parameter named FOO, defaults to 'bar'."
"""
base_param(registry, xml_parent, data, True,
'hudson.model.TextParameterDefinition')
base_param(registry, xml_parent, data, True, "hudson.model.TextParameterDefinition")
def label_param(registry, xml_parent, data):
@@ -204,35 +211,41 @@ def label_param(registry, xml_parent, data):
"""
pdef = base_param(registry, xml_parent, data, True,
'org.jvnet.jenkins.plugins.nodelabelparameter.'
'LabelParameterDefinition')
pdef = base_param(
registry,
xml_parent,
data,
True,
"org.jvnet.jenkins.plugins.nodelabelparameter." "LabelParameterDefinition",
)
valid_types = ['allCases', 'success', 'unstable']
valid_types = ["allCases", "success", "unstable"]
mapping = [
('all-nodes', 'allNodesMatchingLabel', False),
('matching-label', 'triggerIfResult', 'allCases', valid_types),
("all-nodes", "allNodesMatchingLabel", False),
("matching-label", "triggerIfResult", "allCases", valid_types),
]
helpers.convert_mapping_to_xml(pdef, data, mapping, fail_required=True)
eligibility_label = data.get('node-eligibility', 'all').lower()
eligibility_label = data.get("node-eligibility", "all").lower()
eligibility_label_dict = {
'all': 'org.jvnet.jenkins.plugins.'
'nodelabelparameter.node.'
'AllNodeEligibility',
'ignore-offline': 'org.jvnet.jenkins.plugins.'
'nodelabelparameter.node.'
'IgnoreOfflineNodeEligibility',
'ignore-temp-offline': 'org.jvnet.jenkins.plugins.'
'nodelabelparameter.node.'
'IgnoreTempOfflineNodeEligibility',
"all": "org.jvnet.jenkins.plugins."
"nodelabelparameter.node."
"AllNodeEligibility",
"ignore-offline": "org.jvnet.jenkins.plugins."
"nodelabelparameter.node."
"IgnoreOfflineNodeEligibility",
"ignore-temp-offline": "org.jvnet.jenkins.plugins."
"nodelabelparameter.node."
"IgnoreTempOfflineNodeEligibility",
}
if eligibility_label not in eligibility_label_dict:
raise InvalidAttributeError(eligibility_label, eligibility_label,
eligibility_label_dict.keys())
raise InvalidAttributeError(
eligibility_label, eligibility_label, eligibility_label_dict.keys()
)
XML.SubElement(pdef, 'nodeEligibility').set(
"class", eligibility_label_dict[eligibility_label])
XML.SubElement(pdef, "nodeEligibility").set(
"class", eligibility_label_dict[eligibility_label]
)
def node_param(registry, xml_parent, data):
@@ -263,30 +276,37 @@ def node_param(registry, xml_parent, data):
:language: yaml
"""
pdef = base_param(registry, xml_parent, data, False,
'org.jvnet.jenkins.plugins.nodelabelparameter.'
'NodeParameterDefinition')
default = XML.SubElement(pdef, 'defaultSlaves')
if 'default-slaves' in data:
for slave in data['default-slaves']:
XML.SubElement(default, 'string').text = slave
allowed = XML.SubElement(pdef, 'allowedSlaves')
if 'allowed-slaves' in data:
for slave in data['allowed-slaves']:
XML.SubElement(allowed, 'string').text = slave
XML.SubElement(pdef, 'ignoreOfflineNodes').text = str(
data.get('ignore-offline-nodes', False)).lower()
pdef = base_param(
registry,
xml_parent,
data,
False,
"org.jvnet.jenkins.plugins.nodelabelparameter." "NodeParameterDefinition",
)
default = XML.SubElement(pdef, "defaultSlaves")
if "default-slaves" in data:
for slave in data["default-slaves"]:
XML.SubElement(default, "string").text = slave
allowed = XML.SubElement(pdef, "allowedSlaves")
if "allowed-slaves" in data:
for slave in data["allowed-slaves"]:
XML.SubElement(allowed, "string").text = slave
XML.SubElement(pdef, "ignoreOfflineNodes").text = str(
data.get("ignore-offline-nodes", False)
).lower()
if data.get('allowed-multiselect', False):
XML.SubElement(pdef, 'triggerIfResult').text = \
'allowMultiSelectionForConcurrentBuilds'
if data.get("allowed-multiselect", False):
XML.SubElement(
pdef, "triggerIfResult"
).text = "allowMultiSelectionForConcurrentBuilds"
else:
XML.SubElement(pdef, 'triggerIfResult').text = \
'multiSelectionDisallowed'
XML.SubElement(pdef, 'allowMultiNodeSelection').text = str(
data.get('allowed-multiselect', False)).lower()
XML.SubElement(pdef, 'triggerConcurrentBuilds').text = str(
data.get('allowed-multiselect', False)).lower()
XML.SubElement(pdef, "triggerIfResult").text = "multiSelectionDisallowed"
XML.SubElement(pdef, "allowMultiNodeSelection").text = str(
data.get("allowed-multiselect", False)
).lower()
XML.SubElement(pdef, "triggerConcurrentBuilds").text = str(
data.get("allowed-multiselect", False)
).lower()
def choice_param(registry, xml_parent, data):
@@ -307,13 +327,13 @@ def choice_param(registry, xml_parent, data):
- glance
description: "On which project to run?"
"""
pdef = base_param(registry, xml_parent, data, False,
'hudson.model.ChoiceParameterDefinition')
choices = XML.SubElement(pdef, 'choices',
{'class': 'java.util.Arrays$ArrayList'})
a = XML.SubElement(choices, 'a', {'class': 'string-array'})
for choice in data['choices']:
XML.SubElement(a, 'string').text = choice
pdef = base_param(
registry, xml_parent, data, False, "hudson.model.ChoiceParameterDefinition"
)
choices = XML.SubElement(pdef, "choices", {"class": "java.util.Arrays$ArrayList"})
a = XML.SubElement(choices, "a", {"class": "string-array"})
for choice in data["choices"]:
XML.SubElement(a, "string").text = choice
def credentials_param(registry, xml_parent, data):
@@ -345,30 +365,33 @@ def credentials_param(registry, xml_parent, data):
"""
cred_impl_types = {
'any': 'com.cloudbees.plugins.credentials.common.StandardCredentials',
'usernamepassword': 'com.cloudbees.plugins.credentials.impl.' +
'UsernamePasswordCredentialsImpl',
'sshkey': 'com.cloudbees.jenkins.plugins.sshcredentials.impl.' +
'BasicSSHUserPrivateKey',
'secretfile': 'org.jenkinsci.plugins.plaincredentials.impl.' +
'FileCredentialsImpl',
'secrettext': 'org.jenkinsci.plugins.plaincredentials.impl.' +
'StringCredentialsImpl',
'certificate': 'com.cloudbees.plugins.credentials.impl.' +
'CertificateCredentialsImpl'
"any": "com.cloudbees.plugins.credentials.common.StandardCredentials",
"usernamepassword": "com.cloudbees.plugins.credentials.impl."
+ "UsernamePasswordCredentialsImpl",
"sshkey": "com.cloudbees.jenkins.plugins.sshcredentials.impl."
+ "BasicSSHUserPrivateKey",
"secretfile": "org.jenkinsci.plugins.plaincredentials.impl."
+ "FileCredentialsImpl",
"secrettext": "org.jenkinsci.plugins.plaincredentials.impl."
+ "StringCredentialsImpl",
"certificate": "com.cloudbees.plugins.credentials.impl."
+ "CertificateCredentialsImpl",
}
cred_type = data.get('type', 'any').lower()
cred_type = data.get("type", "any").lower()
if cred_type not in cred_impl_types:
raise InvalidAttributeError('type', cred_type, cred_impl_types.keys())
raise InvalidAttributeError("type", cred_type, cred_impl_types.keys())
pdef = base_param(registry, xml_parent, data, False,
'com.cloudbees.plugins.credentials.' +
'CredentialsParameterDefinition')
XML.SubElement(pdef, 'defaultValue').text = data.get('default', '')
XML.SubElement(pdef, 'credentialType').text = cred_impl_types[cred_type]
XML.SubElement(pdef, 'required').text = str(data.get('required',
False)).lower()
pdef = base_param(
registry,
xml_parent,
data,
False,
"com.cloudbees.plugins.credentials." + "CredentialsParameterDefinition",
)
XML.SubElement(pdef, "defaultValue").text = data.get("default", "")
XML.SubElement(pdef, "credentialType").text = cred_impl_types[cred_type]
XML.SubElement(pdef, "required").text = str(data.get("required", False)).lower()
def run_param(registry, xml_parent, data):
@@ -385,11 +408,10 @@ def run_param(registry, xml_parent, data):
:language: yaml
"""
pdef = base_param(registry, xml_parent, data, False,
'hudson.model.RunParameterDefinition')
mapping = [
('project-name', 'projectName', None),
]
pdef = base_param(
registry, xml_parent, data, False, "hudson.model.RunParameterDefinition"
)
mapping = [("project-name", "projectName", None)]
helpers.convert_mapping_to_xml(pdef, data, mapping, fail_required=True)
@@ -456,43 +478,50 @@ def extended_choice_param(registry, xml_parent, data):
/../../tests/parameters/fixtures/extended-choice-param-full.yaml
:language: yaml
"""
pdef = base_param(registry, xml_parent, data, False,
'com.cwctravel.hudson.plugins.'
'extended__choice__parameter.'
'ExtendedChoiceParameterDefinition')
pdef = base_param(
registry,
xml_parent,
data,
False,
"com.cwctravel.hudson.plugins."
"extended__choice__parameter."
"ExtendedChoiceParameterDefinition",
)
choicedict = {'single-select': 'PT_SINGLE_SELECT',
'multi-select': 'PT_MULTI_SELECT',
'radio': 'PT_RADIO',
'checkbox': 'PT_CHECKBOX',
'textbox': 'PT_TEXTBOX',
'PT_SINGLE_SELECT': 'PT_SINGLE_SELECT',
'PT_MULTI_SELECT': 'PT_MULTI_SELECT',
'PT_RADIO': 'PT_RADIO',
'PT_CHECKBOX': 'PT_CHECKBOX',
'PT_TEXTBOX': 'PT_TEXTBOX'}
choicedict = {
"single-select": "PT_SINGLE_SELECT",
"multi-select": "PT_MULTI_SELECT",
"radio": "PT_RADIO",
"checkbox": "PT_CHECKBOX",
"textbox": "PT_TEXTBOX",
"PT_SINGLE_SELECT": "PT_SINGLE_SELECT",
"PT_MULTI_SELECT": "PT_MULTI_SELECT",
"PT_RADIO": "PT_RADIO",
"PT_CHECKBOX": "PT_CHECKBOX",
"PT_TEXTBOX": "PT_TEXTBOX",
}
mapping = [
('value', 'value', ''),
('visible-items', 'visibleItemCount', 5),
('multi-select-delimiter', 'multiSelectDelimiter', ','),
('quote-value', 'quoteValue', False),
('default-value', 'defaultValue', ''),
('value-description', 'descriptionPropertyValue', ''),
('type', 'type', 'single-select', choicedict),
('property-file', 'propertyFile', ''),
('property-key', 'propertyKey', ''),
('default-property-file', 'defaultPropertyFile', ''),
('default-property-key', 'defaultPropertyKey', ''),
('description-property-file', 'descriptionPropertyFile', ''),
('description-property-key', 'descriptionPropertyKey', ''),
('bindings', 'bindings', ''),
('groovy-script', 'groovyScript', ''),
('groovy-script-file', 'groovyScriptFile', ''),
('classpath', 'groovyClasspath', ''),
('default-groovy-script', 'defaultGroovyScript', ''),
('default-groovy-classpath', 'defaultGroovyClasspath', ''),
('description-groovy-script', 'descriptionGroovyScript', ''),
('description-groovy-classpath', 'descriptionGroovyClasspath', ''),
("value", "value", ""),
("visible-items", "visibleItemCount", 5),
("multi-select-delimiter", "multiSelectDelimiter", ","),
("quote-value", "quoteValue", False),
("default-value", "defaultValue", ""),
("value-description", "descriptionPropertyValue", ""),
("type", "type", "single-select", choicedict),
("property-file", "propertyFile", ""),
("property-key", "propertyKey", ""),
("default-property-file", "defaultPropertyFile", ""),
("default-property-key", "defaultPropertyKey", ""),
("description-property-file", "descriptionPropertyFile", ""),
("description-property-key", "descriptionPropertyKey", ""),
("bindings", "bindings", ""),
("groovy-script", "groovyScript", ""),
("groovy-script-file", "groovyScriptFile", ""),
("classpath", "groovyClasspath", ""),
("default-groovy-script", "defaultGroovyScript", ""),
("default-groovy-classpath", "defaultGroovyClasspath", ""),
("description-groovy-script", "descriptionGroovyScript", ""),
("description-groovy-classpath", "descriptionGroovyClasspath", ""),
]
helpers.convert_mapping_to_xml(pdef, data, mapping, fail_required=True)
@@ -519,13 +548,15 @@ def validating_string_param(registry, xml_parent, data):
regex: [A-Za-z]*
msg: Your entered value failed validation
"""
pdef = base_param(registry, xml_parent, data, True,
'hudson.plugins.validating__string__parameter.'
'ValidatingStringParameterDefinition')
mapping = [
('regex', 'regex', None),
('msg', 'failedValidationMessage', None),
]
pdef = base_param(
registry,
xml_parent,
data,
True,
"hudson.plugins.validating__string__parameter."
"ValidatingStringParameterDefinition",
)
mapping = [("regex", "regex", None), ("msg", "failedValidationMessage", None)]
helpers.convert_mapping_to_xml(pdef, data, mapping, fail_required=True)
@@ -557,17 +588,21 @@ def svn_tags_param(registry, xml_parent, data):
url: http://svn.example.com/repo
filter: [A-za-z0-9]*
"""
pdef = base_param(registry, xml_parent, data, True,
'hudson.scm.listtagsparameter.'
'ListSubversionTagsParameterDefinition')
pdef = base_param(
registry,
xml_parent,
data,
True,
"hudson.scm.listtagsparameter." "ListSubversionTagsParameterDefinition",
)
mapping = [
('url', 'tagsDir', None),
('credentials-id', 'credentialsId', ''),
('filter', 'tagsFilter', ''),
('max-tags', 'maxTags', '100'),
('sort-newest-first', 'reverseByDate', True),
('sort-z-to-a', 'reverseByName', False),
('', 'uuid', "1-1-1-1-1"),
("url", "tagsDir", None),
("credentials-id", "credentialsId", ""),
("filter", "tagsFilter", ""),
("max-tags", "maxTags", "100"),
("sort-newest-first", "reverseByDate", True),
("sort-z-to-a", "reverseByName", False),
("", "uuid", "1-1-1-1-1"),
]
helpers.convert_mapping_to_xml(pdef, data, mapping, fail_required=True)
@@ -597,8 +632,7 @@ def dynamic_choice_param(registry, xml_parent, data):
remote: false
read-only: false
"""
dynamic_param_common(registry, xml_parent, data,
'ChoiceParameterDefinition')
dynamic_param_common(registry, xml_parent, data, "ChoiceParameterDefinition")
def dynamic_string_param(registry, xml_parent, data):
@@ -626,8 +660,7 @@ def dynamic_string_param(registry, xml_parent, data):
remote: false
read-only: false
"""
dynamic_param_common(registry, xml_parent, data,
'StringParameterDefinition')
dynamic_param_common(registry, xml_parent, data, "StringParameterDefinition")
def dynamic_choice_scriptler_param(registry, xml_parent, data):
@@ -663,8 +696,9 @@ def dynamic_choice_scriptler_param(registry, xml_parent, data):
remote: false
read-only: false
"""
dynamic_scriptler_param_common(registry, xml_parent, data,
'ScriptlerChoiceParameterDefinition')
dynamic_scriptler_param_common(
registry, xml_parent, data, "ScriptlerChoiceParameterDefinition"
)
def dynamic_string_scriptler_param(registry, xml_parent, data):
@@ -700,54 +734,64 @@ def dynamic_string_scriptler_param(registry, xml_parent, data):
remote: false
read-only: false
"""
dynamic_scriptler_param_common(registry, xml_parent, data,
'ScriptlerStringParameterDefinition')
dynamic_scriptler_param_common(
registry, xml_parent, data, "ScriptlerStringParameterDefinition"
)
def dynamic_param_common(registry, xml_parent, data, ptype):
pdef = base_param(registry, xml_parent, data, False,
'com.seitenbau.jenkins.plugins.dynamicparameter.' +
ptype)
XML.SubElement(pdef, '__remote').text = str(
data.get('remote', False)).lower()
XML.SubElement(pdef, '__script').text = data.get('script', None)
localBaseDir = XML.SubElement(pdef, '__localBaseDirectory',
{'serialization': 'custom'})
filePath = XML.SubElement(localBaseDir, 'hudson.FilePath')
default = XML.SubElement(filePath, 'default')
XML.SubElement(filePath, 'boolean').text = "true"
XML.SubElement(default, 'remote').text = \
"/var/lib/jenkins/dynamic_parameter/classpath"
XML.SubElement(pdef, '__remoteBaseDirectory').text = \
"dynamic_parameter_classpath"
XML.SubElement(pdef, '__classPath').text = data.get('classpath', None)
XML.SubElement(pdef, 'readonlyInputField').text = str(
data.get('read-only', False)).lower()
pdef = base_param(
registry,
xml_parent,
data,
False,
"com.seitenbau.jenkins.plugins.dynamicparameter." + ptype,
)
XML.SubElement(pdef, "__remote").text = str(data.get("remote", False)).lower()
XML.SubElement(pdef, "__script").text = data.get("script", None)
localBaseDir = XML.SubElement(
pdef, "__localBaseDirectory", {"serialization": "custom"}
)
filePath = XML.SubElement(localBaseDir, "hudson.FilePath")
default = XML.SubElement(filePath, "default")
XML.SubElement(filePath, "boolean").text = "true"
XML.SubElement(
default, "remote"
).text = "/var/lib/jenkins/dynamic_parameter/classpath"
XML.SubElement(pdef, "__remoteBaseDirectory").text = "dynamic_parameter_classpath"
XML.SubElement(pdef, "__classPath").text = data.get("classpath", None)
XML.SubElement(pdef, "readonlyInputField").text = str(
data.get("read-only", False)
).lower()
def dynamic_scriptler_param_common(registry, xml_parent, data, ptype):
pdef = base_param(registry, xml_parent, data, False,
'com.seitenbau.jenkins.plugins.dynamicparameter.'
'scriptler.' + ptype)
parametersXML = XML.SubElement(pdef, '__parameters')
parameters = data.get('parameters', [])
pdef = base_param(
registry,
xml_parent,
data,
False,
"com.seitenbau.jenkins.plugins.dynamicparameter." "scriptler." + ptype,
)
parametersXML = XML.SubElement(pdef, "__parameters")
parameters = data.get("parameters", [])
if parameters:
mapping = [
('name', 'name', None),
('value', 'value', None),
]
mapping = [("name", "name", None), ("value", "value", None)]
for parameter in parameters:
parameterXML = XML.SubElement(parametersXML,
'com.seitenbau.jenkins.plugins.'
'dynamicparameter.scriptler.'
'ScriptlerParameterDefinition_'
'-ScriptParameter')
parameterXML = XML.SubElement(
parametersXML,
"com.seitenbau.jenkins.plugins."
"dynamicparameter.scriptler."
"ScriptlerParameterDefinition_"
"-ScriptParameter",
)
helpers.convert_mapping_to_xml(
parameterXML, parameter, mapping, fail_required=True)
parameterXML, parameter, mapping, fail_required=True
)
mapping = [
('script-id', '__scriptlerScriptId', None),
('remote', '__remote', False),
('read-only', 'readonlyInputField', False),
("script-id", "__scriptlerScriptId", None),
("remote", "__remote", False),
("read-only", "readonlyInputField", False),
]
helpers.convert_mapping_to_xml(pdef, data, mapping, fail_required=True)
@@ -770,14 +814,16 @@ def matrix_combinations_param(registry, xml_parent, data):
:language: yaml
"""
element_name = 'hudson.plugins.matrix__configuration__parameter.' \
'MatrixCombinationsParameterDefinition'
element_name = (
"hudson.plugins.matrix__configuration__parameter."
"MatrixCombinationsParameterDefinition"
)
pdef = XML.SubElement(xml_parent, element_name)
mapping = [
('name', 'name', None),
('description', 'description', ''),
('filter', 'defaultCombinationFilter', ''),
("name", "name", None),
("description", "description", ""),
("filter", "defaultCombinationFilter", ""),
]
helpers.convert_mapping_to_xml(pdef, data, mapping, fail_required=True)
@@ -806,15 +852,13 @@ def copyartifact_build_selector_param(registry, xml_parent, data):
"""
t = XML.SubElement(xml_parent, 'hudson.plugins.copyartifact.'
'BuildSelectorParameter')
mapping = [
('name', 'name', None),
('description', 'description', ''),
]
t = XML.SubElement(
xml_parent, "hudson.plugins.copyartifact." "BuildSelectorParameter"
)
mapping = [("name", "name", None), ("description", "description", "")]
helpers.convert_mapping_to_xml(t, data, mapping, fail_required=True)
helpers.copyartifact_build_selector(t, data, 'defaultSelector')
helpers.copyartifact_build_selector(t, data, "defaultSelector")
def maven_metadata_param(registry, xml_parent, data):
@@ -855,31 +899,34 @@ def maven_metadata_param(registry, xml_parent, data):
:language: yaml
"""
pdef = base_param(registry, xml_parent, data, False,
'eu.markov.jenkins.plugin.mvnmeta.'
'MavenMetadataParameterDefinition')
pdef = base_param(
registry,
xml_parent,
data,
False,
"eu.markov.jenkins.plugin.mvnmeta." "MavenMetadataParameterDefinition",
)
mapping = [
('repository-base-url', 'repoBaseUrl', ''),
('artifact-group-id', 'groupId', ''),
('artifact-id', 'artifactId', ''),
('packaging', 'packaging', ''),
('default-value', 'defaultValue', ''),
('versions-filter', 'versionFilter', ''),
("repository-base-url", "repoBaseUrl", ""),
("artifact-group-id", "groupId", ""),
("artifact-id", "artifactId", ""),
("packaging", "packaging", ""),
("default-value", "defaultValue", ""),
("versions-filter", "versionFilter", ""),
]
helpers.convert_mapping_to_xml(pdef, data, mapping, fail_required=True)
sort_order = data.get('sorting-order', 'descending').lower()
sort_dict = {'descending': 'DESC',
'ascending': 'ASC'}
sort_order = data.get("sorting-order", "descending").lower()
sort_dict = {"descending": "DESC", "ascending": "ASC"}
if sort_order not in sort_dict:
raise InvalidAttributeError(sort_order, sort_order, sort_dict.keys())
XML.SubElement(pdef, 'sortOrder').text = sort_dict[sort_order]
XML.SubElement(pdef, "sortOrder").text = sort_dict[sort_order]
mapping = [
('maximum-versions-to-display', 'maxVersions', 10),
('repository-username', 'username', ''),
('repository-password', 'password', ''),
("maximum-versions-to-display", "maxVersions", 10),
("repository-username", "username", ""),
("repository-password", "password", ""),
]
helpers.convert_mapping_to_xml(pdef, data, mapping, fail_required=True)
@@ -901,8 +948,9 @@ def hidden_param(parser, xml_parent, data):
:language: yaml
"""
base_param(parser, xml_parent, data, True,
'com.wangyin.parameter.WHideParameterDefinition')
base_param(
parser, xml_parent, data, True, "com.wangyin.parameter.WHideParameterDefinition"
)
def random_string_param(registry, xml_parent, data):
@@ -923,16 +971,17 @@ def random_string_param(registry, xml_parent, data):
/../../tests/parameters/fixtures/random-string-param001.yaml
:language: yaml
"""
pdef = XML.SubElement(xml_parent,
'hudson.plugins.random__string__parameter.'
'RandomStringParameterDefinition')
if 'name' not in data:
raise JenkinsJobsException('random-string must have a name parameter.')
pdef = XML.SubElement(
xml_parent,
"hudson.plugins.random__string__parameter." "RandomStringParameterDefinition",
)
if "name" not in data:
raise JenkinsJobsException("random-string must have a name parameter.")
mapping = [
('name', 'name', None),
('description', 'description', ''),
('failed-validation-message', 'failedValidationMessage', ''),
("name", "name", None),
("description", "description", ""),
("failed-validation-message", "failedValidationMessage", ""),
]
helpers.convert_mapping_to_xml(pdef, data, mapping, fail_required=True)
@@ -1005,40 +1054,41 @@ def git_parameter_param(registry, xml_parent, data):
/../../tests/parameters/fixtures/git-parameter-param-full.yaml
:language: yaml
"""
pdef = XML.SubElement(xml_parent,
'net.uaznia.lukanus.hudson.plugins.gitparameter.'
'GitParameterDefinition')
pdef = XML.SubElement(
xml_parent,
"net.uaznia.lukanus.hudson.plugins.gitparameter." "GitParameterDefinition",
)
valid_types = [
'PT_TAG',
'PT_BRANCH',
'PT_BRANCH_TAG',
'PT_REVISION',
'PT_PULL_REQUEST',
"PT_TAG",
"PT_BRANCH",
"PT_BRANCH_TAG",
"PT_REVISION",
"PT_PULL_REQUEST",
]
valid_sort_modes = [
'NONE',
'ASCENDING',
'ASCENDING_SMART',
'DESCENDING',
'DESCENDING_SMART',
"NONE",
"ASCENDING",
"ASCENDING_SMART",
"DESCENDING",
"DESCENDING_SMART",
]
valid_selected_values = ['NONE', 'TOP', 'DEFAULT']
valid_selected_values = ["NONE", "TOP", "DEFAULT"]
mapping = [
('name', 'name', None),
('description', 'description', ''),
('type', 'type', 'PT_TAG', valid_types),
('branch', 'branch', ''),
('tagFilter', 'tagFilter', '*'),
('branchFilter', 'branchFilter', '.*'),
('sortMode', 'sortMode', 'NONE', valid_sort_modes),
('defaultValue', 'defaultValue', ''),
('selectedValue', 'selectedValue', 'NONE', valid_selected_values),
('useRepository', 'useRepository', ''),
('quickFilterEnabled', 'quickFilterEnabled', False),
("name", "name", None),
("description", "description", ""),
("type", "type", "PT_TAG", valid_types),
("branch", "branch", ""),
("tagFilter", "tagFilter", "*"),
("branchFilter", "branchFilter", ".*"),
("sortMode", "sortMode", "NONE", valid_sort_modes),
("defaultValue", "defaultValue", ""),
("selectedValue", "selectedValue", "NONE", valid_selected_values),
("useRepository", "useRepository", ""),
("quickFilterEnabled", "quickFilterEnabled", False),
]
helpers.convert_mapping_to_xml(pdef, data, mapping, fail_required=True)
@@ -1046,28 +1096,29 @@ def git_parameter_param(registry, xml_parent, data):
class Parameters(jenkins_jobs.modules.base.Base):
sequence = 21
component_type = 'parameter'
component_list_type = 'parameters'
component_type = "parameter"
component_list_type = "parameters"
def gen_xml(self, xml_parent, data):
properties = xml_parent.find('properties')
properties = xml_parent.find("properties")
if properties is None:
properties = XML.SubElement(xml_parent, 'properties')
properties = XML.SubElement(xml_parent, "properties")
parameters = data.get('parameters', [])
hmodel = 'hudson.model.'
parameters = data.get("parameters", [])
hmodel = "hudson.model."
if parameters:
# The conditionals here are to work around the extended_choice
# parameter also being definable in the properties module. This
# usage has been deprecated but not removed. Because it may have
# added these elements before us, we need to check if they already
# exist, and only add them if they're missing.
pdefp = properties.find(hmodel + 'ParametersDefinitionProperty')
pdefp = properties.find(hmodel + "ParametersDefinitionProperty")
if pdefp is None:
pdefp = XML.SubElement(properties,
hmodel + 'ParametersDefinitionProperty')
pdefs = pdefp.find('parameterDefinitions')
pdefp = XML.SubElement(
properties, hmodel + "ParametersDefinitionProperty"
)
pdefs = pdefp.find("parameterDefinitions")
if pdefs is None:
pdefs = XML.SubElement(pdefp, 'parameterDefinitions')
pdefs = XML.SubElement(pdefp, "parameterDefinitions")
for param in parameters:
self.registry.dispatch('parameter', pdefs, param)
self.registry.dispatch("parameter", pdefs, param)

View File

@@ -40,5 +40,5 @@ class ExternalJob(jenkins_jobs.modules.base.Base):
sequence = 0
def root_xml(self, data):
xml_parent = XML.Element('hudson.model.ExternalJob')
xml_parent = XML.Element("hudson.model.ExternalJob")
return xml_parent

View File

@@ -59,15 +59,15 @@ class Flow(jenkins_jobs.modules.base.Base):
sequence = 0
def root_xml(self, data):
xml_parent = XML.Element('com.cloudbees.plugins.flow.BuildFlow')
xml_parent = XML.Element("com.cloudbees.plugins.flow.BuildFlow")
needs_workspace = data.get('needs-workspace', False)
needs_workspace = data.get("needs-workspace", False)
mapping = [
('dsl', 'dsl', ''),
('needs-workspace', 'buildNeedsWorkspace', False),
("dsl", "dsl", ""),
("needs-workspace", "buildNeedsWorkspace", False),
]
convert_mapping_to_xml(xml_parent, data, mapping, fail_required=True)
if needs_workspace and 'dsl-file' in data:
XML.SubElement(xml_parent, 'dslFile').text = data['dsl-file']
if needs_workspace and "dsl-file" in data:
XML.SubElement(xml_parent, "dslFile").text = data["dsl-file"]
return xml_parent

View File

@@ -43,19 +43,18 @@ class Folder(jenkins_jobs.modules.base.Base):
sequence = 0
def root_xml(self, data):
xml_parent = XML.Element('com.cloudbees.hudson.plugins.folder.Folder',
plugin="cloudbees-folder")
attributes = {"class": "com.cloudbees.hudson.plugins.folder."
"icons.StockFolderIcon"}
XML.SubElement(xml_parent, 'icon', attrib=attributes)
XML.SubElement(xml_parent, 'views')
xml_parent = XML.Element(
"com.cloudbees.hudson.plugins.folder.Folder", plugin="cloudbees-folder"
)
attributes = {
"class": "com.cloudbees.hudson.plugins.folder." "icons.StockFolderIcon"
}
XML.SubElement(xml_parent, "icon", attrib=attributes)
XML.SubElement(xml_parent, "views")
attributes = {"class": "hudson.views.DefaultViewsTabBar"}
XML.SubElement(xml_parent, 'viewsTabBar', attrib=attributes)
XML.SubElement(xml_parent, "viewsTabBar", attrib=attributes)
mappings = [
('', 'primaryView', 'All'),
('', 'healthMetrics', ''),
]
mappings = [("", "primaryView", "All"), ("", "healthMetrics", "")]
convert_mapping_to_xml(xml_parent, data, mappings, True)
return xml_parent

View File

@@ -36,5 +36,5 @@ class Freestyle(jenkins_jobs.modules.base.Base):
sequence = 0
def root_xml(self, data):
xml_parent = XML.Element('project')
xml_parent = XML.Element("project")
return xml_parent

View File

@@ -113,139 +113,144 @@ class Matrix(jenkins_jobs.modules.base.Base):
# List the supported Axis names in our configuration
# and map them to the Jenkins XML element name.
supported_axis = {
'label-expression': 'hudson.matrix.LabelExpAxis',
'user-defined': 'hudson.matrix.TextAxis',
'slave': 'hudson.matrix.LabelAxis',
'jdk': 'hudson.matrix.JDKAxis',
'dynamic': 'ca.silvermaplesolutions.jenkins.plugins.daxis.DynamicAxis',
'python': 'jenkins.plugins.shiningpanda.matrix.PythonAxis',
'tox': 'jenkins.plugins.shiningpanda.matrix.ToxAxis',
'groovy': 'org.jenkinsci.plugins.GroovyAxis',
'yaml': 'org.jenkinsci.plugins.yamlaxis.YamlAxis',
"label-expression": "hudson.matrix.LabelExpAxis",
"user-defined": "hudson.matrix.TextAxis",
"slave": "hudson.matrix.LabelAxis",
"jdk": "hudson.matrix.JDKAxis",
"dynamic": "ca.silvermaplesolutions.jenkins.plugins.daxis.DynamicAxis",
"python": "jenkins.plugins.shiningpanda.matrix.PythonAxis",
"tox": "jenkins.plugins.shiningpanda.matrix.ToxAxis",
"groovy": "org.jenkinsci.plugins.GroovyAxis",
"yaml": "org.jenkinsci.plugins.yamlaxis.YamlAxis",
}
supported_strategies = {
# Jenkins built-in, default
'execution-strategy':
'hudson.matrix.DefaultMatrixExecutionStrategyImpl',
'yaml-strategy':
'org.jenkinsci.plugins.yamlaxis.YamlMatrixExecutionStrategy',
'p4-strategy':
'org.jenkinsci.plugins.p4.matrix.MatrixOptions'
"execution-strategy": "hudson.matrix.DefaultMatrixExecutionStrategyImpl",
"yaml-strategy": "org.jenkinsci.plugins.yamlaxis.YamlMatrixExecutionStrategy",
"p4-strategy": "org.jenkinsci.plugins.p4.matrix.MatrixOptions",
}
def root_xml(self, data):
root = XML.Element('matrix-project')
root = XML.Element("matrix-project")
# Default to 'execution-strategy'
strategies = ([s for s in data.keys() if s.endswith('-strategy')] or
['execution-strategy'])
strategies = [s for s in data.keys() if s.endswith("-strategy")] or [
"execution-strategy"
]
# Job can not have multiple strategies
if len(strategies) > 1:
raise ValueError(
'matrix-project does not support multiple strategies. '
'Given %s: %s' % (len(strategies), ', '.join(strategies)))
"matrix-project does not support multiple strategies. "
"Given %s: %s" % (len(strategies), ", ".join(strategies))
)
strategy_name = strategies[0]
if strategy_name not in self.supported_strategies:
raise ValueError(
'Given strategy %s. Only %s strategies are supported'
% (strategy_name, self.supported_strategies.keys()))
"Given strategy %s. Only %s strategies are supported"
% (strategy_name, self.supported_strategies.keys())
)
ex_r = XML.SubElement(
root, 'executionStrategy',
{'class': self.supported_strategies[strategy_name]})
root,
"executionStrategy",
{"class": self.supported_strategies[strategy_name]},
)
strategy = data.get(strategy_name, {})
if strategy_name == 'execution-strategy':
XML.SubElement(root, 'combinationFilter').text = (
str(strategy.get('combination-filter', '')).rstrip()
)
XML.SubElement(ex_r, 'runSequentially').text = (
str(strategy.get('sequential', False)).lower()
)
if 'touchstone' in strategy:
XML.SubElement(ex_r, 'touchStoneCombinationFilter').text = (
str(strategy['touchstone'].get('expr', ''))
if strategy_name == "execution-strategy":
XML.SubElement(root, "combinationFilter").text = str(
strategy.get("combination-filter", "")
).rstrip()
XML.SubElement(ex_r, "runSequentially").text = str(
strategy.get("sequential", False)
).lower()
if "touchstone" in strategy:
XML.SubElement(ex_r, "touchStoneCombinationFilter").text = str(
strategy["touchstone"].get("expr", "")
)
threshold = strategy['touchstone'].get(
'result', 'stable').upper()
supported_thresholds = ('STABLE', 'UNSTABLE')
threshold = strategy["touchstone"].get("result", "stable").upper()
supported_thresholds = ("STABLE", "UNSTABLE")
if threshold not in supported_thresholds:
raise InvalidAttributeError(
'touchstone', threshold, supported_thresholds)
"touchstone", threshold, supported_thresholds
)
# Web ui uses Stable but hudson.model.Result has Success
if threshold == 'STABLE':
threshold = 'SUCCESS'
if threshold == "STABLE":
threshold = "SUCCESS"
t_r = XML.SubElement(ex_r, 'touchStoneResultCondition')
for sub_elem in ('name', 'ordinal', 'color'):
XML.SubElement(t_r, sub_elem).text = (
hudson_model.THRESHOLDS[threshold][sub_elem])
t_r = XML.SubElement(ex_r, "touchStoneResultCondition")
for sub_elem in ("name", "ordinal", "color"):
XML.SubElement(t_r, sub_elem).text = hudson_model.THRESHOLDS[
threshold
][sub_elem]
elif strategy_name == 'yaml-strategy':
filename = str(strategy.get('filename', ''))
text = str(strategy.get('text', ''))
exclude_key = str(strategy.get('exclude-key', ''))
elif strategy_name == "yaml-strategy":
filename = str(strategy.get("filename", ""))
text = str(strategy.get("text", ""))
exclude_key = str(strategy.get("exclude-key", ""))
if bool(filename) == bool(text): # xor with str
raise ValueError('yaml-strategy must be given '
'either "filename" or "text"')
raise ValueError(
"yaml-strategy must be given " 'either "filename" or "text"'
)
yamlType = (filename and 'file') or (text and 'text')
XML.SubElement(ex_r, 'yamlType').text = yamlType
yamlType = (filename and "file") or (text and "text")
XML.SubElement(ex_r, "yamlType").text = yamlType
XML.SubElement(ex_r, 'yamlFile').text = filename
XML.SubElement(ex_r, 'yamlText').text = text
XML.SubElement(ex_r, "yamlFile").text = filename
XML.SubElement(ex_r, "yamlText").text = text
XML.SubElement(ex_r, 'excludeKey').text = exclude_key
XML.SubElement(ex_r, "excludeKey").text = exclude_key
elif strategy_name == 'p4-strategy':
XML.SubElement(ex_r, 'runSequentially').text = (
str(strategy.get('sequential', False)).lower()
)
elif strategy_name == "p4-strategy":
XML.SubElement(ex_r, "runSequentially").text = str(
strategy.get("sequential", False)
).lower()
XML.SubElement(ex_r, 'buildParent').text = (
str(strategy.get('build-parent', False)).lower()
)
XML.SubElement(ex_r, "buildParent").text = str(
strategy.get("build-parent", False)
).lower()
ax_root = XML.SubElement(root, 'axes')
for axis_ in data.get('axes', []):
axis = axis_['axis']
axis_type = axis['type']
ax_root = XML.SubElement(root, "axes")
for axis_ in data.get("axes", []):
axis = axis_["axis"]
axis_type = axis["type"]
if axis_type not in self.supported_axis:
raise ValueError('Only %s axes types are supported'
% self.supported_axis.keys())
raise ValueError(
"Only %s axes types are supported" % self.supported_axis.keys()
)
axis_name = self.supported_axis.get(axis_type)
lbl_root = XML.SubElement(ax_root, axis_name)
name, values = axis.get('name', ''), axis.get('values', [''])
if axis_type == 'jdk':
XML.SubElement(lbl_root, 'name').text = 'jdk'
elif axis_type == 'python':
XML.SubElement(lbl_root, 'name').text = 'PYTHON'
elif axis_type == 'tox':
XML.SubElement(lbl_root, 'name').text = 'TOXENV'
name, values = axis.get("name", ""), axis.get("values", [""])
if axis_type == "jdk":
XML.SubElement(lbl_root, "name").text = "jdk"
elif axis_type == "python":
XML.SubElement(lbl_root, "name").text = "PYTHON"
elif axis_type == "tox":
XML.SubElement(lbl_root, "name").text = "TOXENV"
else:
XML.SubElement(lbl_root, 'name').text = str(name)
XML.SubElement(lbl_root, "name").text = str(name)
if axis_type != "groovy":
v_root = XML.SubElement(lbl_root, 'values')
v_root = XML.SubElement(lbl_root, "values")
if axis_type == "dynamic":
XML.SubElement(v_root, 'string').text = str(values[0])
XML.SubElement(lbl_root, 'varName').text = str(values[0])
v_root = XML.SubElement(lbl_root, 'axisValues')
XML.SubElement(v_root, 'string').text = 'default'
XML.SubElement(v_root, "string").text = str(values[0])
XML.SubElement(lbl_root, "varName").text = str(values[0])
v_root = XML.SubElement(lbl_root, "axisValues")
XML.SubElement(v_root, "string").text = "default"
elif axis_type == "groovy":
command = XML.SubElement(lbl_root, 'groovyString')
command.text = axis.get('command')
XML.SubElement(lbl_root, 'computedValues').text = ''
command = XML.SubElement(lbl_root, "groovyString")
command.text = axis.get("command")
XML.SubElement(lbl_root, "computedValues").text = ""
elif axis_type == "yaml":
XML.SubElement(v_root, 'string').text = axis.get('filename')
XML.SubElement(v_root, "string").text = axis.get("filename")
else:
for v in values:
XML.SubElement(v_root, 'string').text = str(v)
XML.SubElement(v_root, "string").text = str(v)
return root

View File

@@ -95,93 +95,109 @@ class Maven(jenkins_jobs.modules.base.Base):
sequence = 0
choices_private_repo = {
'default':
'hudson.maven.local_repo.DefaultLocalRepositoryLocator',
'local-to-workspace':
'hudson.maven.local_repo.PerJobLocalRepositoryLocator',
'local-to-executor':
'hudson.maven.local_repo.PerExecutorLocalRepositoryLocator',
"default": "hudson.maven.local_repo.DefaultLocalRepositoryLocator",
"local-to-workspace": "hudson.maven.local_repo.PerJobLocalRepositoryLocator",
"local-to-executor": "hudson.maven.local_repo.PerExecutorLocalRepositoryLocator",
}
def root_xml(self, data):
xml_parent = XML.Element('maven2-moduleset')
if 'maven' not in data:
xml_parent = XML.Element("maven2-moduleset")
if "maven" not in data:
return xml_parent
# determine version of plugin
plugin_info = self.registry.get_plugin_info("Maven Integration plugin")
version = pkg_resources.parse_version(plugin_info.get('version', '0'))
version = pkg_resources.parse_version(plugin_info.get("version", "0"))
if 'root-module' in data['maven']:
root_module = XML.SubElement(xml_parent, 'rootModule')
XML.SubElement(root_module, 'groupId').text = \
data['maven']['root-module']['group-id']
XML.SubElement(root_module, 'artifactId').text = \
data['maven']['root-module']['artifact-id']
XML.SubElement(xml_parent, 'goals').text = data['maven']['goals']
if "root-module" in data["maven"]:
root_module = XML.SubElement(xml_parent, "rootModule")
XML.SubElement(root_module, "groupId").text = data["maven"]["root-module"][
"group-id"
]
XML.SubElement(root_module, "artifactId").text = data["maven"][
"root-module"
]["artifact-id"]
XML.SubElement(xml_parent, "goals").text = data["maven"]["goals"]
maven_opts = data['maven'].get('maven-opts')
maven_opts = data["maven"].get("maven-opts")
if maven_opts:
XML.SubElement(xml_parent, 'mavenOpts').text = maven_opts
XML.SubElement(xml_parent, "mavenOpts").text = maven_opts
maven_name = data['maven'].get('maven-name')
maven_name = data["maven"].get("maven-name")
if maven_name:
XML.SubElement(xml_parent, 'mavenName').text = maven_name
XML.SubElement(xml_parent, "mavenName").text = maven_name
private_repo = data['maven'].get('private-repository')
private_repo = data["maven"].get("private-repository")
if private_repo:
if private_repo not in self.choices_private_repo.keys():
raise ValueError('Not a valid private-repository "%s", '
'must be one of "%s"' %
(private_repo,
", ".join(self.choices_private_repo.keys())))
XML.SubElement(xml_parent,
'localRepository',
attrib={'class':
self.choices_private_repo[private_repo]})
raise ValueError(
'Not a valid private-repository "%s", '
'must be one of "%s"'
% (private_repo, ", ".join(self.choices_private_repo.keys()))
)
XML.SubElement(
xml_parent,
"localRepository",
attrib={"class": self.choices_private_repo[private_repo]},
)
XML.SubElement(xml_parent, 'ignoreUpstremChanges').text = str(
data['maven'].get('ignore-upstream-changes', True)).lower()
XML.SubElement(xml_parent, "ignoreUpstremChanges").text = str(
data["maven"].get("ignore-upstream-changes", True)
).lower()
XML.SubElement(xml_parent, 'rootPOM').text = \
data['maven'].get('root-pom', 'pom.xml')
XML.SubElement(xml_parent, 'aggregatorStyleBuild').text = str(
not data['maven'].get('parallel-build-modules', False)).lower()
XML.SubElement(xml_parent, 'incrementalBuild').text = str(
data['maven'].get('incremental-build', False)).lower()
XML.SubElement(xml_parent, 'siteArchivingDisabled').text = str(
not data['maven'].get('automatic-site-archiving', True)).lower()
XML.SubElement(xml_parent, 'fingerprintingDisabled').text = str(
not data['maven'].get('automatic-fingerprinting', True)).lower()
if (version > pkg_resources.parse_version('0') and
version < pkg_resources.parse_version('2.0.1')):
XML.SubElement(xml_parent, 'perModuleEmail').text = str(
data.get('per-module-email', True)).lower()
XML.SubElement(xml_parent, 'archivingDisabled').text = str(
not data['maven'].get('automatic-archiving', True)).lower()
XML.SubElement(xml_parent, 'resolveDependencies').text = str(
data['maven'].get('resolve-dependencies', False)).lower()
XML.SubElement(xml_parent, 'processPlugins').text = str(
data['maven'].get('process-plugins', False)).lower()
XML.SubElement(xml_parent, 'mavenValidationLevel').text = '-1'
XML.SubElement(xml_parent, 'runHeadless').text = str(
data['maven'].get('run-headless', False)).lower()
XML.SubElement(xml_parent, 'disableTriggerDownstreamProjects').text = \
str(data['maven'].get('disable-downstream', False)).lower()
if 'custom-workspace' in data['maven']:
XML.SubElement(xml_parent, 'customWorkspace').text = str(
data['maven'].get('custom-workspace'))
helpers.config_file_provider_settings(xml_parent, data['maven'])
XML.SubElement(xml_parent, "rootPOM").text = data["maven"].get(
"root-pom", "pom.xml"
)
XML.SubElement(xml_parent, "aggregatorStyleBuild").text = str(
not data["maven"].get("parallel-build-modules", False)
).lower()
XML.SubElement(xml_parent, "incrementalBuild").text = str(
data["maven"].get("incremental-build", False)
).lower()
XML.SubElement(xml_parent, "siteArchivingDisabled").text = str(
not data["maven"].get("automatic-site-archiving", True)
).lower()
XML.SubElement(xml_parent, "fingerprintingDisabled").text = str(
not data["maven"].get("automatic-fingerprinting", True)
).lower()
if version > pkg_resources.parse_version(
"0"
) and version < pkg_resources.parse_version("2.0.1"):
XML.SubElement(xml_parent, "perModuleEmail").text = str(
data.get("per-module-email", True)
).lower()
XML.SubElement(xml_parent, "archivingDisabled").text = str(
not data["maven"].get("automatic-archiving", True)
).lower()
XML.SubElement(xml_parent, "resolveDependencies").text = str(
data["maven"].get("resolve-dependencies", False)
).lower()
XML.SubElement(xml_parent, "processPlugins").text = str(
data["maven"].get("process-plugins", False)
).lower()
XML.SubElement(xml_parent, "mavenValidationLevel").text = "-1"
XML.SubElement(xml_parent, "runHeadless").text = str(
data["maven"].get("run-headless", False)
).lower()
XML.SubElement(xml_parent, "disableTriggerDownstreamProjects").text = str(
data["maven"].get("disable-downstream", False)
).lower()
if "custom-workspace" in data["maven"]:
XML.SubElement(xml_parent, "customWorkspace").text = str(
data["maven"].get("custom-workspace")
)
helpers.config_file_provider_settings(xml_parent, data["maven"])
run_post_steps = XML.SubElement(xml_parent, 'runPostStepsIfResult')
run_conditions = ['SUCCESS', 'UNSTABLE', 'FAILURE']
run_condition = data['maven'].get('post-step-run-condition', 'FAILURE')
run_post_steps = XML.SubElement(xml_parent, "runPostStepsIfResult")
run_conditions = ["SUCCESS", "UNSTABLE", "FAILURE"]
run_condition = data["maven"].get("post-step-run-condition", "FAILURE")
if run_condition not in run_conditions:
raise InvalidAttributeError('post-step-run-condition',
run_condition, run_conditions)
raise InvalidAttributeError(
"post-step-run-condition", run_condition, run_conditions
)
cond_dict = hudson_model.THRESHOLDS[run_condition]
XML.SubElement(run_post_steps, 'name').text = cond_dict['name']
XML.SubElement(run_post_steps, 'ordinal').text = cond_dict['ordinal']
XML.SubElement(run_post_steps, 'color').text = cond_dict['color']
XML.SubElement(run_post_steps, "name").text = cond_dict["name"]
XML.SubElement(run_post_steps, "ordinal").text = cond_dict["ordinal"]
XML.SubElement(run_post_steps, "color").text = cond_dict["color"]
return xml_parent

File diff suppressed because it is too large Load Diff

View File

@@ -59,6 +59,7 @@ class MultiJob(jenkins_jobs.modules.base.Base):
sequence = 0
def root_xml(self, data):
xml_parent = XML.Element('com.tikal.jenkins.plugins.multijob.'
'MultiJobProject')
xml_parent = XML.Element(
"com.tikal.jenkins.plugins.multijob." "MultiJobProject"
)
return xml_parent

View File

@@ -82,31 +82,38 @@ import jenkins_jobs.modules.base
class Pipeline(jenkins_jobs.modules.base.Base):
sequence = 0
error_msg = ("You cannot declare both 'dsl' and 'pipeline-scm' on a "
"pipeline job")
error_msg = "You cannot declare both 'dsl' and 'pipeline-scm' on a " "pipeline job"
def root_xml(self, data):
xml_parent = XML.Element('flow-definition',
{'plugin': 'workflow-job'})
if 'dsl' in data and 'pipeline-scm' in data:
xml_parent = XML.Element("flow-definition", {"plugin": "workflow-job"})
if "dsl" in data and "pipeline-scm" in data:
raise JenkinsJobsException(self.error_msg)
if 'dsl' in data:
xml_definition = XML.SubElement(xml_parent, 'definition',
{'plugin': 'workflow-cps',
'class': 'org.jenkinsci.plugins.'
'workflow.cps.CpsFlowDefinition'})
XML.SubElement(xml_definition, 'script').text = data['dsl']
elif 'pipeline-scm' in data:
xml_definition = XML.SubElement(xml_parent, 'definition', {
'plugin': 'workflow-cps',
'class': 'org.jenkinsci.plugins.workflow.cps.'
'CpsScmFlowDefinition'})
if "dsl" in data:
xml_definition = XML.SubElement(
xml_parent,
"definition",
{
"plugin": "workflow-cps",
"class": "org.jenkinsci.plugins." "workflow.cps.CpsFlowDefinition",
},
)
XML.SubElement(xml_definition, "script").text = data["dsl"]
elif "pipeline-scm" in data:
xml_definition = XML.SubElement(
xml_parent,
"definition",
{
"plugin": "workflow-cps",
"class": "org.jenkinsci.plugins.workflow.cps."
"CpsScmFlowDefinition",
},
)
else:
raise JenkinsJobsException("Either 'dsl' or 'pipeline-scm' "
"is required for pipeline job")
raise JenkinsJobsException(
"Either 'dsl' or 'pipeline-scm' " "is required for pipeline job"
)
needs_workspace = data.get('sandbox', False)
XML.SubElement(xml_definition, 'sandbox').text = str(
needs_workspace).lower()
needs_workspace = data.get("sandbox", False)
XML.SubElement(xml_definition, "sandbox").text = str(needs_workspace).lower()
return xml_parent

View File

@@ -59,22 +59,21 @@ class Workflow(jenkins_jobs.modules.base.Base):
def root_xml(self, data):
logger = logging.getLogger(__name__)
logger.warning(
"Workflow job type is deprecated, please use Pipeline job type"
logger.warning("Workflow job type is deprecated, please use Pipeline job type")
xml_parent = XML.Element("flow-definition", {"plugin": "workflow-job"})
xml_definition = XML.SubElement(
xml_parent,
"definition",
{
"plugin": "workflow-cps",
"class": "org.jenkinsci.plugins." "workflow.cps.CpsFlowDefinition",
},
)
xml_parent = XML.Element('flow-definition',
{'plugin': 'workflow-job'})
xml_definition = XML.SubElement(xml_parent, 'definition',
{'plugin': 'workflow-cps',
'class': 'org.jenkinsci.plugins.'
'workflow.cps.CpsFlowDefinition'})
mapping = [
('dsl', 'script', None),
('sandbox', 'sandbox', False),
]
mapping = [("dsl", "script", None), ("sandbox", "sandbox", False)]
helpers.convert_mapping_to_xml(
xml_definition, data, mapping, fail_required=True)
xml_definition, data, mapping, fail_required=True
)
return xml_parent

View File

@@ -59,16 +59,17 @@ def builds_chain_fingerprinter(registry, xml_parent, data):
.. literalinclude:: /../../tests/properties/fixtures/fingerprinter.yaml
:language: yaml
"""
fingerprinter = XML.SubElement(xml_parent,
'org.jenkinsci.plugins.'
'buildschainfingerprinter.'
'AutomaticFingerprintJobProperty')
fingerprinter = XML.SubElement(
xml_parent,
"org.jenkinsci.plugins."
"buildschainfingerprinter."
"AutomaticFingerprintJobProperty",
)
mapping = [
('per-builds-chain', 'isPerBuildsChainEnabled', False),
('per-job-chain', 'isPerJobsChainEnabled', False),
("per-builds-chain", "isPerBuildsChainEnabled", False),
("per-job-chain", "isPerJobsChainEnabled", False),
]
helpers.convert_mapping_to_xml(
fingerprinter, data, mapping, fail_required=True)
helpers.convert_mapping_to_xml(fingerprinter, data, mapping, fail_required=True)
def ownership(registry, xml_parent, data):
@@ -87,16 +88,17 @@ def ownership(registry, xml_parent, data):
"""
ownership_plugin = XML.SubElement(
xml_parent,
'com.synopsys.arc.jenkins.plugins.ownership.jobs.JobOwnerJobProperty')
ownership = XML.SubElement(ownership_plugin, 'ownership')
owner = str(data.get('enabled', True)).lower()
XML.SubElement(ownership, 'ownershipEnabled').text = owner
"com.synopsys.arc.jenkins.plugins.ownership.jobs.JobOwnerJobProperty",
)
ownership = XML.SubElement(ownership_plugin, "ownership")
owner = str(data.get("enabled", True)).lower()
XML.SubElement(ownership, "ownershipEnabled").text = owner
XML.SubElement(ownership, 'primaryOwnerId').text = data.get('owner')
XML.SubElement(ownership, "primaryOwnerId").text = data.get("owner")
coownersIds = XML.SubElement(ownership, 'coownersIds')
for coowner in data.get('co-owners', []):
XML.SubElement(coownersIds, 'string').text = coowner
coownersIds = XML.SubElement(ownership, "coownersIds")
for coowner in data.get("co-owners", []):
XML.SubElement(coownersIds, "string").text = coowner
def promoted_build(registry, xml_parent, data):
@@ -115,13 +117,14 @@ def promoted_build(registry, xml_parent, data):
.. literalinclude:: /../../tests/properties/fixtures/promoted_build.yaml
:language: yaml
"""
promoted = XML.SubElement(xml_parent, 'hudson.plugins.promoted__builds.'
'JobPropertyImpl')
names = data.get('names', [])
promoted = XML.SubElement(
xml_parent, "hudson.plugins.promoted__builds." "JobPropertyImpl"
)
names = data.get("names", [])
if names:
active_processes = XML.SubElement(promoted, 'activeProcessNames')
active_processes = XML.SubElement(promoted, "activeProcessNames")
for n in names:
XML.SubElement(active_processes, 'string').text = str(n)
XML.SubElement(active_processes, "string").text = str(n)
def gitbucket(parser, xml_parent, data):
@@ -143,15 +146,12 @@ def gitbucket(parser, xml_parent, data):
:language: yaml
"""
gitbucket = XML.SubElement(
xml_parent, 'org.jenkinsci.plugins.gitbucket.GitBucketProjectProperty')
gitbucket.set('plugin', 'gitbucket')
xml_parent, "org.jenkinsci.plugins.gitbucket.GitBucketProjectProperty"
)
gitbucket.set("plugin", "gitbucket")
mapping = [
('url', 'url', None),
('link-enabled', 'linkEnabled', False),
]
helpers.convert_mapping_to_xml(
gitbucket, data, mapping, fail_required=True)
mapping = [("url", "url", None), ("link-enabled", "linkEnabled", False)]
helpers.convert_mapping_to_xml(gitbucket, data, mapping, fail_required=True)
def github(registry, xml_parent, data):
@@ -174,13 +174,11 @@ def github(registry, xml_parent, data):
:language: yaml
"""
github = XML.SubElement(
xml_parent, 'com.coravy.hudson.plugins.github.GithubProjectProperty')
github.set('plugin', 'github')
xml_parent, "com.coravy.hudson.plugins.github.GithubProjectProperty"
)
github.set("plugin", "github")
mapping = [
('url', 'projectUrl', None),
('display-name', 'displayName', ''),
]
mapping = [("url", "projectUrl", None), ("display-name", "displayName", "")]
helpers.convert_mapping_to_xml(github, data, mapping, fail_required=True)
@@ -197,12 +195,11 @@ def gitlab(registry, xml_parent, data):
.. literalinclude:: /../../tests/properties/fixtures/gitlab.yaml
:language: yaml
"""
gitlab = XML.SubElement(xml_parent,
'com.dabsquared.gitlabjenkins.connection.'
'GitLabConnectionProperty')
mapping = [
('connection', 'gitLabConnection', None),
]
gitlab = XML.SubElement(
xml_parent,
"com.dabsquared.gitlabjenkins.connection." "GitLabConnectionProperty",
)
mapping = [("connection", "gitLabConnection", None)]
helpers.convert_mapping_to_xml(gitlab, data, mapping, fail_required=True)
@@ -219,12 +216,10 @@ def gitlab_logo(registry, xml_parent, data):
.. literalinclude:: /../../tests/properties/fixtures/gitlab-logo.yaml
:language: yaml
"""
logo = XML.SubElement(xml_parent,
'org.jenkinsci.plugins.gitlablogo.'
'GitlabLogoProperty')
mapping = [
('repository-name', 'repositoryName', None)
]
logo = XML.SubElement(
xml_parent, "org.jenkinsci.plugins.gitlablogo." "GitlabLogoProperty"
)
mapping = [("repository-name", "repositoryName", None)]
helpers.convert_mapping_to_xml(logo, data, mapping, fail_required=True)
@@ -238,9 +233,7 @@ def disk_usage(registry, xml_parent, data):
.. literalinclude:: /../../tests/properties/fixtures/disk-usage.yaml
:language: yaml
"""
XML.SubElement(xml_parent,
'hudson.plugins.disk__usage.'
'DiskUsageProperty')
XML.SubElement(xml_parent, "hudson.plugins.disk__usage." "DiskUsageProperty")
def least_load(registry, xml_parent, data):
@@ -255,12 +248,11 @@ def least_load(registry, xml_parent, data):
.. literalinclude:: /../../tests/properties/fixtures/least-load002.yaml
:language: yaml
"""
least = XML.SubElement(xml_parent,
'org.bstick12.jenkinsci.plugins.leastload.'
'LeastLoadDisabledProperty')
mapping = [
('disabled', 'leastLoadDisabled', True),
]
least = XML.SubElement(
xml_parent,
"org.bstick12.jenkinsci.plugins.leastload." "LeastLoadDisabledProperty",
)
mapping = [("disabled", "leastLoadDisabled", True)]
helpers.convert_mapping_to_xml(least, data, mapping, fail_required=True)
@@ -288,43 +280,41 @@ def throttle(registry, xml_parent, data):
.. literalinclude:: /../../tests/properties/fixtures/throttle001.yaml
:language: yaml
"""
throttle = XML.SubElement(xml_parent,
'hudson.plugins.throttleconcurrents.'
'ThrottleJobProperty')
throttle = XML.SubElement(
xml_parent, "hudson.plugins.throttleconcurrents." "ThrottleJobProperty"
)
mapping = [
('max-per-node', 'maxConcurrentPerNode', '0'),
('max-total', 'maxConcurrentTotal', '0'),
('enabled', 'throttleEnabled', True),
("max-per-node", "maxConcurrentPerNode", "0"),
("max-total", "maxConcurrentTotal", "0"),
("enabled", "throttleEnabled", True),
]
helpers.convert_mapping_to_xml(throttle, data, mapping, fail_required=True)
cat = data.get('categories', [])
cat = data.get("categories", [])
if cat:
cn = XML.SubElement(throttle, 'categories')
cn = XML.SubElement(throttle, "categories")
for c in cat:
XML.SubElement(cn, 'string').text = str(c)
XML.SubElement(cn, "string").text = str(c)
options_list = ('category', 'project')
option = data.get('option')
options_list = ("category", "project")
option = data.get("option")
if option not in options_list:
raise InvalidAttributeError('option', option, options_list)
raise InvalidAttributeError("option", option, options_list)
mapping = [
('', 'throttleOption', option),
('', 'configVersion', '1'),
('parameters-limit', 'limitOneJobWithMatchingParams', False),
("", "throttleOption", option),
("", "configVersion", "1"),
("parameters-limit", "limitOneJobWithMatchingParams", False),
]
helpers.convert_mapping_to_xml(throttle, data, mapping, fail_required=True)
matrixopt = XML.SubElement(throttle, 'matrixOptions')
matrixopt = XML.SubElement(throttle, "matrixOptions")
mapping = [
('matrix-builds', 'throttleMatrixBuilds', True),
('matrix-configs', 'throttleMatrixConfigurations', False),
("matrix-builds", "throttleMatrixBuilds", True),
("matrix-configs", "throttleMatrixConfigurations", False),
]
helpers.convert_mapping_to_xml(
matrixopt, data, mapping, fail_required=True)
helpers.convert_mapping_to_xml(matrixopt, data, mapping, fail_required=True)
params_to_use = data.get('parameters-check-list', [])
XML.SubElement(throttle, 'paramsToUseForLimit').text = ",".join(
params_to_use)
params_to_use = data.get("parameters-check-list", [])
XML.SubElement(throttle, "paramsToUseForLimit").text = ",".join(params_to_use)
def branch_api(registry, xml_parent, data):
@@ -354,16 +344,17 @@ def branch_api(registry, xml_parent, data):
/../../tests/properties/fixtures/branch-api-full.yaml
:language: yaml
"""
branch = XML.SubElement(xml_parent, 'jenkins.branch.'
'RateLimitBranchProperty_-JobPropertyImpl')
branch.set('plugin', 'branch-api')
branch = XML.SubElement(
xml_parent, "jenkins.branch." "RateLimitBranchProperty_-JobPropertyImpl"
)
branch.set("plugin", "branch-api")
valid_time_periods = ['Hour', 'Day', 'Week', 'Month', 'Year']
valid_time_periods = ["Hour", "Day", "Week", "Month", "Year"]
mapping = [
('time-period', 'durationName', 'Hour', valid_time_periods),
('number-of-builds', 'count', 1),
('skip-rate-limit', 'userBoost', False),
("time-period", "durationName", "Hour", valid_time_periods),
("number-of-builds", "count", 1),
("skip-rate-limit", "userBoost", False),
]
helpers.convert_mapping_to_xml(branch, data, mapping, fail_required=True)
@@ -383,19 +374,16 @@ def sidebar(registry, xml_parent, data):
.. literalinclude:: /../../tests/properties/fixtures/sidebar02.yaml
:language: yaml
"""
sidebar = xml_parent.find('hudson.plugins.sidebar__link.ProjectLinks')
sidebar = xml_parent.find("hudson.plugins.sidebar__link.ProjectLinks")
if sidebar is None:
sidebar = XML.SubElement(xml_parent,
'hudson.plugins.sidebar__link.ProjectLinks')
links = XML.SubElement(sidebar, 'links')
sidebar = XML.SubElement(
xml_parent, "hudson.plugins.sidebar__link.ProjectLinks"
)
links = XML.SubElement(sidebar, "links")
else:
links = sidebar.find('links')
action = XML.SubElement(links, 'hudson.plugins.sidebar__link.LinkAction')
mapping = [
('url', 'url', ''),
('text', 'text', ''),
('icon', 'icon', ''),
]
links = sidebar.find("links")
action = XML.SubElement(links, "hudson.plugins.sidebar__link.LinkAction")
mapping = [("url", "url", ""), ("text", "text", ""), ("icon", "icon", "")]
helpers.convert_mapping_to_xml(action, data, mapping, fail_required=True)
@@ -423,43 +411,40 @@ def inject(registry, xml_parent, data):
:language: yaml
"""
inject = XML.SubElement(xml_parent,
'EnvInjectJobProperty')
info = XML.SubElement(inject, 'info')
inject = XML.SubElement(xml_parent, "EnvInjectJobProperty")
info = XML.SubElement(inject, "info")
mapping = [
('properties-file', 'propertiesFilePath', None),
('properties-content', 'propertiesContent', None),
('script-file', 'scriptFilePath', None),
('script-content', 'scriptContent', None),
('load-from-master', 'loadFilesFromMaster', False),
("properties-file", "propertiesFilePath", None),
("properties-content", "propertiesContent", None),
("script-file", "scriptFilePath", None),
("script-content", "scriptContent", None),
("load-from-master", "loadFilesFromMaster", False),
]
helpers.convert_mapping_to_xml(info, data, mapping, fail_required=False)
# determine version of plugin
plugin_info = registry.get_plugin_info("Groovy")
version = pkg_resources.parse_version(plugin_info.get('version', '0'))
version = pkg_resources.parse_version(plugin_info.get("version", "0"))
if version >= pkg_resources.parse_version("2.0.0"):
secure_groovy_script = XML.SubElement(info, 'secureGroovyScript')
secure_groovy_script = XML.SubElement(info, "secureGroovyScript")
mapping = [
('groovy-content', 'script', None),
('groovy-sandbox', 'sandbox', False),
("groovy-content", "script", None),
("groovy-sandbox", "sandbox", False),
]
helpers.convert_mapping_to_xml(secure_groovy_script, data, mapping,
fail_required=False)
helpers.convert_mapping_to_xml(
secure_groovy_script, data, mapping, fail_required=False
)
else:
mapping = [
('groovy-content', 'groovyScriptContent', None),
]
helpers.convert_mapping_to_xml(info, data, mapping,
fail_required=False)
mapping = [("groovy-content", "groovyScriptContent", None)]
helpers.convert_mapping_to_xml(info, data, mapping, fail_required=False)
mapping = [
('enabled', 'on', True),
('keep-system-variables', 'keepJenkinsSystemVariables', True),
('keep-build-variables', 'keepBuildVariables', True),
('override-build-parameters', 'overrideBuildParameters', False),
("enabled", "on", True),
("keep-system-variables", "keepJenkinsSystemVariables", True),
("keep-build-variables", "keepBuildVariables", True),
("override-build-parameters", "overrideBuildParameters", False),
]
helpers.convert_mapping_to_xml(inject, data, mapping, fail_required=True)
@@ -479,11 +464,12 @@ def authenticated_build(registry, xml_parent, data):
"""
# TODO: generalize this
security = XML.SubElement(xml_parent,
'hudson.security.'
'AuthorizationMatrixProperty')
XML.SubElement(security, 'permission').text = (
'hudson.model.Item.Build:authenticated')
security = XML.SubElement(
xml_parent, "hudson.security." "AuthorizationMatrixProperty"
)
XML.SubElement(
security, "permission"
).text = "hudson.model.Item.Build:authenticated"
def authorization(registry, xml_parent, data):
@@ -523,38 +509,39 @@ def authorization(registry, xml_parent, data):
:language: yaml
"""
credentials = 'com.cloudbees.plugins.credentials.CredentialsProvider.'
ownership = 'com.synopsys.arc.jenkins.plugins.ownership.OwnershipPlugin.'
credentials = "com.cloudbees.plugins.credentials.CredentialsProvider."
ownership = "com.synopsys.arc.jenkins.plugins.ownership.OwnershipPlugin."
mapping = {
'credentials-create': ''.join((credentials, 'Create')),
'credentials-delete': ''.join((credentials, 'Delete')),
'credentials-manage-domains': ''.join((credentials, 'ManageDomains')),
'credentials-update': ''.join((credentials, 'Update')),
'credentials-view': ''.join((credentials, 'View')),
'job-build': 'hudson.model.Item.Build',
'job-cancel': 'hudson.model.Item.Cancel',
'job-configure': 'hudson.model.Item.Configure',
'job-delete': 'hudson.model.Item.Delete',
'job-discover': 'hudson.model.Item.Discover',
'job-extended-read': 'hudson.model.Item.ExtendedRead',
'job-move': 'hudson.model.Item.Move',
'job-read': 'hudson.model.Item.Read',
'job-status': 'hudson.model.Item.ViewStatus',
'job-workspace': 'hudson.model.Item.Workspace',
'ownership-jobs': ''.join((ownership, 'Jobs')),
'run-delete': 'hudson.model.Run.Delete',
'run-replay': 'hudson.model.Run.Replay',
'run-update': 'hudson.model.Run.Update',
'scm-tag': 'hudson.scm.SCM.Tag',
"credentials-create": "".join((credentials, "Create")),
"credentials-delete": "".join((credentials, "Delete")),
"credentials-manage-domains": "".join((credentials, "ManageDomains")),
"credentials-update": "".join((credentials, "Update")),
"credentials-view": "".join((credentials, "View")),
"job-build": "hudson.model.Item.Build",
"job-cancel": "hudson.model.Item.Cancel",
"job-configure": "hudson.model.Item.Configure",
"job-delete": "hudson.model.Item.Delete",
"job-discover": "hudson.model.Item.Discover",
"job-extended-read": "hudson.model.Item.ExtendedRead",
"job-move": "hudson.model.Item.Move",
"job-read": "hudson.model.Item.Read",
"job-status": "hudson.model.Item.ViewStatus",
"job-workspace": "hudson.model.Item.Workspace",
"ownership-jobs": "".join((ownership, "Jobs")),
"run-delete": "hudson.model.Run.Delete",
"run-replay": "hudson.model.Run.Replay",
"run-update": "hudson.model.Run.Update",
"scm-tag": "hudson.scm.SCM.Tag",
}
if data:
matrix = XML.SubElement(xml_parent,
'hudson.security.AuthorizationMatrixProperty')
matrix = XML.SubElement(
xml_parent, "hudson.security.AuthorizationMatrixProperty"
)
for (username, perms) in data.items():
for perm in perms:
pe = XML.SubElement(matrix, 'permission')
pe = XML.SubElement(matrix, "permission")
try:
pe.text = "{0}:{1}".format(mapping[perm], username)
except KeyError:
@@ -577,39 +564,32 @@ def priority_sorter(registry, xml_parent, data):
/../../tests/properties/fixtures/priority_sorter002.yaml
:language: yaml
"""
plugin_info = registry.get_plugin_info('PrioritySorter')
version = pkg_resources.parse_version(plugin_info.get('version', '0'))
plugin_info = registry.get_plugin_info("PrioritySorter")
version = pkg_resources.parse_version(plugin_info.get("version", "0"))
if version >= pkg_resources.parse_version("3.0"):
priority_sorter_tag = XML.SubElement(
xml_parent,
'jenkins.advancedqueue.jobinclusion.'
'strategy.JobInclusionJobProperty')
"jenkins.advancedqueue.jobinclusion." "strategy.JobInclusionJobProperty",
)
mapping = [
('use', 'useJobGroup', True),
('priority', 'jobGroupName', None)
]
mapping = [("use", "useJobGroup", True), ("priority", "jobGroupName", None)]
elif version >= pkg_resources.parse_version("2.0"):
priority_sorter_tag = XML.SubElement(xml_parent,
'jenkins.advancedqueue.priority.'
'strategy.PriorityJobProperty')
priority_sorter_tag = XML.SubElement(
xml_parent, "jenkins.advancedqueue.priority." "strategy.PriorityJobProperty"
)
mapping = [
('use', 'useJobPriority', True),
('priority', 'priority', None)
]
mapping = [("use", "useJobPriority", True), ("priority", "priority", None)]
else:
priority_sorter_tag = XML.SubElement(xml_parent,
'hudson.queueSorter.'
'PrioritySorterJobProperty')
priority_sorter_tag = XML.SubElement(
xml_parent, "hudson.queueSorter." "PrioritySorterJobProperty"
)
mapping = [
('priority', 'priority', None),
]
mapping = [("priority", "priority", None)]
helpers.convert_mapping_to_xml(
priority_sorter_tag, data, mapping, fail_required=True)
priority_sorter_tag, data, mapping, fail_required=True
)
def build_blocker(registry, xml_parent, data):
@@ -643,25 +623,25 @@ def build_blocker(registry, xml_parent, data):
/../../tests/properties/fixtures/build-blocker-full.yaml
:language: yaml
"""
blocker = XML.SubElement(xml_parent,
'hudson.plugins.'
'buildblocker.BuildBlockerProperty')
if data is None or 'blocking-jobs' not in data:
raise JenkinsJobsException('blocking-jobs field is missing')
elif data.get('blocking-jobs', None) is None:
raise JenkinsJobsException('blocking-jobs list must not be empty')
blocker = XML.SubElement(
xml_parent, "hudson.plugins." "buildblocker.BuildBlockerProperty"
)
if data is None or "blocking-jobs" not in data:
raise JenkinsJobsException("blocking-jobs field is missing")
elif data.get("blocking-jobs", None) is None:
raise JenkinsJobsException("blocking-jobs list must not be empty")
jobs = ''
jobs = ""
for setting, value in data.items():
if setting == 'blocking-jobs':
jobs = '\n'.join(value)
block_level_types = ['GLOBAL', 'NODE']
queue_scan_types = ['DISABLED', 'ALL', 'BUILDABLE']
if setting == "blocking-jobs":
jobs = "\n".join(value)
block_level_types = ["GLOBAL", "NODE"]
queue_scan_types = ["DISABLED", "ALL", "BUILDABLE"]
mapping = [
('use-build-blocker', 'useBuildBlocker', True),
('', 'blockingJobs', jobs),
('block-level', 'blockLevel', 'GLOBAL', block_level_types),
('queue-scanning', 'scanQueueFor', 'DISABLED', queue_scan_types),
("use-build-blocker", "useBuildBlocker", True),
("", "blockingJobs", jobs),
("block-level", "blockLevel", "GLOBAL", block_level_types),
("queue-scanning", "scanQueueFor", "DISABLED", queue_scan_types),
]
helpers.convert_mapping_to_xml(blocker, data, mapping, fail_required=True)
@@ -684,17 +664,16 @@ def copyartifact(registry, xml_parent, data):
:language: yaml
"""
copyartifact = XML.SubElement(xml_parent,
'hudson.plugins.'
'copyartifact.'
'CopyArtifactPermissionProperty',
plugin='copyartifact')
if not data or not data.get('projects', None):
raise JenkinsJobsException("projects string must exist and "
"not be empty")
projectlist = XML.SubElement(copyartifact, 'projectNameList')
for project in str(data.get('projects')).split(','):
XML.SubElement(projectlist, 'string').text = project
copyartifact = XML.SubElement(
xml_parent,
"hudson.plugins." "copyartifact." "CopyArtifactPermissionProperty",
plugin="copyartifact",
)
if not data or not data.get("projects", None):
raise JenkinsJobsException("projects string must exist and " "not be empty")
projectlist = XML.SubElement(copyartifact, "projectNameList")
for project in str(data.get("projects")).split(","):
XML.SubElement(projectlist, "string").text = project
def batch_tasks(registry, xml_parent, data):
@@ -722,18 +701,12 @@ def batch_tasks(registry, xml_parent, data):
:language: yaml
"""
pdef = XML.SubElement(xml_parent,
'hudson.plugins.batch__task.BatchTaskProperty')
tasks = XML.SubElement(pdef, 'tasks')
pdef = XML.SubElement(xml_parent, "hudson.plugins.batch__task.BatchTaskProperty")
tasks = XML.SubElement(pdef, "tasks")
for task in data:
batch_task = XML.SubElement(tasks,
'hudson.plugins.batch__task.BatchTask')
mapping = [
('name', 'name', None),
('script', 'script', None),
]
helpers.convert_mapping_to_xml(
batch_task, task, mapping, fail_required=True)
batch_task = XML.SubElement(tasks, "hudson.plugins.batch__task.BatchTask")
mapping = [("name", "name", None), ("script", "script", None)]
helpers.convert_mapping_to_xml(batch_task, task, mapping, fail_required=True)
def heavy_job(registry, xml_parent, data):
@@ -752,12 +725,10 @@ def heavy_job(registry, xml_parent, data):
:language: yaml
"""
heavyjob = XML.SubElement(xml_parent,
'hudson.plugins.'
'heavy__job.HeavyJobProperty')
mapping = [
('weight', 'weight', 1),
]
heavyjob = XML.SubElement(
xml_parent, "hudson.plugins." "heavy__job.HeavyJobProperty"
)
mapping = [("weight", "weight", 1)]
helpers.convert_mapping_to_xml(heavyjob, data, mapping, fail_required=True)
@@ -782,18 +753,18 @@ def slave_utilization(registry, xml_parent, data):
:language: yaml
"""
utilization = XML.SubElement(
xml_parent, 'com.suryagaddipati.jenkins.SlaveUtilizationProperty')
xml_parent, "com.suryagaddipati.jenkins.SlaveUtilizationProperty"
)
percent = int(data.get('slave-percentage', 0))
percent = int(data.get("slave-percentage", 0))
exclusive_node_access = True if percent else False
mapping = [
('', 'needsExclusiveAccessToNode', exclusive_node_access),
('', 'slaveUtilizationPercentage', percent),
('single-instance-per-slave', 'singleInstancePerSlave', False),
("", "needsExclusiveAccessToNode", exclusive_node_access),
("", "slaveUtilizationPercentage", percent),
("single-instance-per-slave", "singleInstancePerSlave", False),
]
helpers.convert_mapping_to_xml(
utilization, data, mapping, fail_required=True)
helpers.convert_mapping_to_xml(utilization, data, mapping, fail_required=True)
def delivery_pipeline(registry, xml_parent, data):
@@ -818,14 +789,13 @@ def delivery_pipeline(registry, xml_parent, data):
/../../tests/properties/fixtures/delivery-pipeline-full.yaml
:language: yaml
"""
pipeline = XML.SubElement(
xml_parent, 'se.diabol.jenkins.pipeline.PipelineProperty')
pipeline.set('plugin', 'delivery-pipeline-plugin')
pipeline = XML.SubElement(xml_parent, "se.diabol.jenkins.pipeline.PipelineProperty")
pipeline.set("plugin", "delivery-pipeline-plugin")
mapping = [
('stage', 'stageName', ''),
('task', 'taskName', ''),
('description', 'descriptionTemplate', ''),
("stage", "stageName", ""),
("task", "taskName", ""),
("description", "descriptionTemplate", ""),
]
helpers.convert_mapping_to_xml(pipeline, data, mapping, fail_required=True)