Adding hipchat notification capability.

Tweaks the Builder and YamlParser classes to accept a config object
which is passed to the parser's ModuleRegistry object. This makes it
available to the HipChat object.

Change-Id: I3017658336b949c0fda7c82945e7014dbcf6e152
Reviewed-on: https://review.openstack.org/12794
Reviewed-by: James E. Blair <corvus@inaugust.com>
Reviewed-by: Clark Boylan <clark.boylan@gmail.com>
Approved: James E. Blair <corvus@inaugust.com>
Tested-by: Jenkins
This commit is contained in:
Manuel Desbonnet 2012-09-19 08:52:35 +01:00 committed by Jenkins
parent b6af0f0060
commit 5465ab6d4f
6 changed files with 125 additions and 6 deletions

View File

@ -184,6 +184,7 @@ The bulk of the job definitions come from the following modules.
project_maven
general
builders
hipchat
notifications
parameters
properties

7
doc/source/hipchat.rst Normal file
View File

@ -0,0 +1,7 @@
.. _hipchat:
Hipchat
==========
.. automodule:: hipchat_notif
:members:

View File

@ -45,7 +45,8 @@ def main():
logger.debug("Config: {0}".format(config))
builder = jenkins_jobs.builder.Builder(config.get('jenkins', 'url'),
config.get('jenkins', 'user'),
config.get('jenkins', 'password'))
config.get('jenkins', 'password'),
config)
if options.command == 'delete':
for job in options.name:

View File

@ -29,8 +29,8 @@ logger = logging.getLogger(__name__)
class YamlParser(object):
def __init__(self):
self.registry = ModuleRegistry()
def __init__(self, config=None):
self.registry = ModuleRegistry(config)
self.data = {}
self.jobs = []
@ -150,9 +150,10 @@ class YamlParser(object):
class ModuleRegistry(object):
def __init__(self):
def __init__(self, config):
self.modules = []
self.handlers = {}
self.global_config = config
for entrypoint in pkg_resources.iter_entry_points(
group='jenkins_jobs.modules'):
@ -242,9 +243,11 @@ class Jenkins(object):
class Builder(object):
def __init__(self, jenkins_url, jenkins_user, jenkins_password):
def __init__(self, jenkins_url, jenkins_user, jenkins_password,
config=None):
self.jenkins = Jenkins(jenkins_url, jenkins_user, jenkins_password)
self.cache = CacheStorage()
self.global_config = config
def delete_job(self, name):
self.jenkins.delete_job(name)
@ -258,7 +261,7 @@ class Builder(object):
if (f.endswith('.yml') or f.endswith('.yaml'))]
else:
files_to_process = [fn]
parser = YamlParser()
parser = YamlParser(self.global_config)
for in_file in files_to_process:
logger.debug("Parsing YAML file {0}".format(in_file))
parser.parse(in_file)

View File

@ -0,0 +1,106 @@
# Copyright 2012 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Enable hipchat notification of build execution.
Example::
- job:
name: test_job
hipchat:
enabled: true
room: Testjob Build Notifications
start-notify: true
In the jenkins UI specification, the hipchat plugin must be explicitly
selected as a publisher. This is not required (or supported) here - use the
``enabled`` parameter to enable/disable the publisher action.
If you set ``enabled: false``, no hipchat parameters are written to XML.
"""
# Enabling hipchat notifications on a job requires specifying the hipchat
# config in job properties, and adding the hipchat notifier to the job's
# publishers list.
# The publisher configuration contains extra details not specified per job:
# - the hipchat authorisation token.
# - the jenkins server url.
# - a default room name/id.
# This complicates matters somewhat since the sensible place to store these
# details is in the global config file.
# The global config object is therefore passed down to the registry object,
# and this object is passed to the HipChat() class initialiser.
import xml.etree.ElementTree as XML
import jenkins_jobs.modules.base
import jenkins_jobs.errors
import logging
import ConfigParser
logger = logging.getLogger(__name__)
class HipChat(jenkins_jobs.modules.base.Base):
sequence = 80
def __init__(self, registry):
self.authToken = None
self.jenkinsUrl = None
self.registry = registry
def _load_global_data(self):
"""Load data from the global config object.
This is done lazily to avoid looking up the '[hipchat]' section
unless actually required.
"""
if(not self.authToken):
# Verify that the config object in the registry is of type
# ConfigParser (it could possibly be a regular 'dict' object which
# doesn't have the right get() method).
if(not isinstance(self.registry.global_config,
ConfigParser.ConfigParser)):
raise jenkins_jobs.errors.JenkinsJobsException(
'HipChat requires a config object in the registry.')
self.authToken = self.registry.global_config.get(
'hipchat', 'authtoken')
self.jenkinsUrl = self.registry.global_config.get('jenkins', 'url')
def gen_xml(self, parser, xml_parent, data):
hipchat = data.get('hipchat')
if not hipchat or not hipchat.get('enabled', True):
return
if('room' not in hipchat):
raise jenkins_jobs.errors.YAMLFormatError(
"Missing hipchat 'room' specifier")
self._load_global_data()
properties = xml_parent.find('properties')
if properties is None:
properties = XML.SubElement(xml_parent, 'properties')
pdefhip = XML.SubElement(properties,
'jenkins.plugins.hipchat.HipChatNotifier_-HipChatJobProperty')
XML.SubElement(pdefhip, 'room').text = hipchat['room']
XML.SubElement(pdefhip, 'startNotification').text = str(
hipchat.get('start-notify', 'false')).lower()
publishers = xml_parent.find('publishers')
if publishers is None:
publishers = XML.SubElement(xml_parent, 'publishers')
hippub = XML.SubElement(publishers,
'jenkins.plugins.hipchat.HipChatNotifier')
XML.SubElement(hippub, 'jenkinsUrl').text = self.jenkinsUrl
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 = ''

View File

@ -95,6 +95,7 @@ setup(name='jenkins_job_builder',
'triggers=jenkins_jobs.modules.triggers:Triggers',
'wrappers=jenkins_jobs.modules.wrappers:Wrappers',
'zuul=jenkins_jobs.modules.zuul:Zuul',
'hipchat=jenkins_jobs.modules.hipchat_notif:HipChat',
]
}