Fix plot plugin support

Based on the source code of the jenkins plot plugin
https://github.com/jenkinsci/plot-plugin/ the related publisher
has been updated to generate a working XML block and match the
behaviour for data persistency in CSV file with random generated
name.
Minor code adjustement to match coding covention (Hyphen and
capital letter usage)
Plot group now correctly handled.
All three type of plot with different option are covered in tests.

Change-Id: I6bd22ea19f397cf2123b924ff5517682a53177ed
Closes-Bug: #1223017
This commit is contained in:
Pierre Rognant 2013-09-09 16:36:46 -04:00
parent e8c09ea6c0
commit d31d4c345e
7 changed files with 231 additions and 65 deletions

View File

@ -39,6 +39,7 @@ import xml.etree.ElementTree as XML
import jenkins_jobs.modules.base
import logging
import sys
import random
def archive(parser, xml_parent, data):
@ -2535,10 +2536,23 @@ def plot(parser, xml_parent, data):
descriptions used as X-axis labels and the
build number and date used for tooltips.
(default: False)
:arg str csv-file-name: Use for choosing the file name in which the data
will be persisted. If none specified and random
name is generated as done in the Jenkins Plot
plugin.
(default: random generated .csv filename, same
behaviour as the Jenkins Plot plugin)
:arg list series: list data series definitions
:Serie: * **file** (`str`) : files to include
* **exclude** (`str`) : CSV files to exclude (default: empty)
* **inclusion-flag** filtering mode for CSV files. Possible
values are:
* **off** (default)
* **include-by-string**
* **exclude-by-string**
* **include-by-column**
* **exclude-by-column**
* **exclude** (`str`) : exclude pattern for CSV file.
* **url** (`str`) : for 'csv' and 'xml' file types
used when you click on a point (default: empty)
* **display-table** (`bool`) : for 'csv' file type
@ -2550,85 +2564,110 @@ def plot(parser, xml_parent, data):
Can be: properties, csv, xml
* **xpath-type** (`str`) : The result type of the expression must
be supplied due to limitations in the java.xml.xpath parsing.
The result can be: NODE, NODESET, BOOLEAN, STRING, or NUMBER.
The result can be: node, nodeset, boolean, string, or number.
Strings and numbers will be converted to double. Boolean will
be converted to 1 for true, and 0 for false. (default: 'NODE')
be converted to 1 for true, and 0 for false. (default: 'node')
* **xpath** (`str`) : used by 'xml' file type
Xpath which selects the values that should be plotted.
Example::
publishers:
- plot:
title: MyPlot
yaxis: Y
group: PlotGroup
num-builds: ''
style: line
use-description: false
series:
- file: graph-me-second.properties
label: MyLabel
format: properties
- file: graph-me-first.csv
exclude: exclude-me-1.csv
url: 'http://srv1'
display-table: true
format: csv
- file: graph-me-third.xml
exclude: exclude-me-2.xml
url: 'http://srv2'
format: xml
xpath-type: NODE
xpath: '/*'
- title: MyPlot
yaxis: Y
group: PlotGroup
num-builds: ''
style: line
use-description: false
series:
- file: graph-me-second.properties
label: MyLabel
format: properties
- file: graph-me-first.csv
url: 'http://srv1'
inclusion-flag: 'off'
display-table: true
format: csv
- title: MyPlot2
yaxis: Y
group: PlotGroup
style: line
use-description: false
series:
- file: graph-me-third.xml
url: 'http://srv2'
format: xml
xpath-type: 'node'
xpath: '/*'
"""
top = XML.SubElement(xml_parent, 'hudson.plugins.plot.PlotPublisher')
plots = XML.SubElement(top, 'plots')
plugin = XML.SubElement(plots, 'hudson.plugins.plot.Plot')
XML.SubElement(plugin, 'title').text = data.get('title', '')
XML.SubElement(plugin, 'yaxis').text = data['yaxis']
topseries = XML.SubElement(plugin, 'series')
series = data['series']
format_dict = {'properties': 'hudson.plugins.plot.PropertiesSeries',
'csv': 'hudson.plugins.plot.CSVSeries',
'xml': 'hudson.plugins.plot.XMLSeries'}
xpath_list = ['NODESET', 'NODE', 'STRING', 'BOOLEAN', 'NUMBER']
for serie in series:
format_data = serie.get('format')
if format_data not in format_dict:
raise Exception("format entered is not valid, must be one of: " +
", ".join(format_dict.keys()))
subserie = XML.SubElement(topseries, format_dict.get(format_data))
XML.SubElement(subserie, 'file').text = serie.get('file')
if format_data == 'properties':
XML.SubElement(subserie, 'label').text = serie.get('label', '')
if format_data == 'csv':
XML.SubElement(subserie, 'exclusionValues').text = \
serie.get('exclude', '')
XML.SubElement(subserie, 'url').text = serie.get('url', '')
XML.SubElement(subserie, 'displayTableFlag').text = \
str(data.get('display-table', False)).lower()
if format_data == 'xml':
XML.SubElement(subserie, 'url').text = serie.get('url', '')
XML.SubElement(subserie, 'xpathString').text = serie.get('xpath')
xpathtype = serie.get('xpath-type', 'NODE')
if xpathtype not in xpath_list:
raise Exception("XPath result entered is not valid, must be " +
"one of: " + ", ".join(xpath_list))
XML.SubElement(subserie, 'nodeTypeString').text = xpathtype
XML.SubElement(subserie, 'fileType').text = serie.get('format')
XML.SubElement(plugin, 'group').text = data['group']
XML.SubElement(plugin, 'useDescr').text = \
str(data.get('use-description', False)).lower()
XML.SubElement(plugin, 'numBuilds').text = data.get('num-builds', '')
style_list = ['area', 'bar', 'bar3d', 'line', 'line3d', 'stackedArea',
'stackedbar', 'stackedbar3d', 'waterfall']
style = data.get('style', 'line')
if style not in style_list:
raise Exception("style entered is not valid, must be one of: " +
", ".join(style_list))
XML.SubElement(plugin, 'style').text = style
xpath_dict = {'nodeset': 'NODESET', 'node': 'NODE', 'string': 'STRING',
'boolean': 'BOOLEAN', 'number': 'NUMBER'}
inclusion_dict = {'off': 'OFF',
'include-by-string': 'INCLUDE_BY_STRING',
'exclude-by-string': 'EXCLUDE_BY_STRING',
'include-by-column': 'INCLUDE_BY_COLUMN',
'exclude-by-column': 'EXCLUDE_BY_COLUMN'}
for plot in data:
plugin = XML.SubElement(plots, 'hudson.plugins.plot.Plot')
XML.SubElement(plugin, 'title').text = plot.get('title', '')
XML.SubElement(plugin, 'yaxis').text = plot['yaxis']
XML.SubElement(plugin, 'csvFileName').text = \
plot.get('csv-file-name', '%s.csv' % random.randrange(2 << 32))
topseries = XML.SubElement(plugin, 'series')
series = plot['series']
for serie in series:
format_data = serie.get('format')
if format_data not in format_dict:
raise Exception("format entered is not valid," +
"must be one of:" +
" , ".join(format_dict.keys()))
subserie = XML.SubElement(topseries, format_dict.get(format_data))
XML.SubElement(subserie, 'file').text = serie.get('file')
if format_data == 'properties':
XML.SubElement(subserie, 'label').text = serie.get('label', '')
if format_data == 'csv':
inclusion_flag = serie.get('inclusion-flag', 'off')
if inclusion_flag not in inclusion_dict:
raise Exception("Inclusion flag result entered is not " +
" valid, must be one of: " +
", ".join(inclusion_dict))
XML.SubElement(subserie, 'inclusionFlag').text = \
inclusion_dict.get(inclusion_flag)
XML.SubElement(subserie, 'exclusionValues').text = \
serie.get('exclude', '')
XML.SubElement(subserie, 'url').text = serie.get('url', '')
XML.SubElement(subserie, 'displayTableFlag').text = \
str(plot.get('display-table', False)).lower()
if format_data == 'xml':
XML.SubElement(subserie, 'url').text = serie.get('url', '')
XML.SubElement(subserie, 'xpathString').text = \
serie.get('xpath')
xpathtype = serie.get('xpath-type', 'node')
if xpathtype not in xpath_dict:
raise Exception("XPath result entered is not valid, must" +
" be one of: " + ", ".join(xpath_dict))
XML.SubElement(subserie, 'nodeTypeString').text = \
xpath_dict.get(xpathtype)
XML.SubElement(subserie, 'fileType').text = serie.get('format')
XML.SubElement(plugin, 'group').text = plot['group']
XML.SubElement(plugin, 'useDescr').text = \
str(plot.get('use-description', False)).lower()
XML.SubElement(plugin, 'numBuilds').text = plot.get('num-builds', '')
style_list = ['area', 'bar', 'bar3d', 'line', 'line3d', 'stackedArea',
'stackedbar', 'stackedbar3d', 'waterfall']
style = plot.get('style', 'line')
if style not in style_list:
raise Exception("style entered is not valid, must be one of: " +
", ".join(style_list))
XML.SubElement(plugin, 'style').text = style
class Publishers(jenkins_jobs.modules.base.Base):

View File

@ -0,0 +1,28 @@
<?xml version="1.0" ?>
<project>
<publishers>
<hudson.plugins.plot.PlotPublisher>
<plots>
<hudson.plugins.plot.Plot>
<title>Sample graph</title>
<yaxis/>
<csvFileName>persisted.csv</csvFileName>
<series>
<hudson.plugins.plot.CSVSeries>
<file>data.csv</file>
<inclusionFlag>OFF</inclusionFlag>
<exclusionValues/>
<url/>
<displayTableFlag>false</displayTableFlag>
<fileType>csv</fileType>
</hudson.plugins.plot.CSVSeries>
</series>
<group>bench</group>
<useDescr>false</useDescr>
<numBuilds/>
<style>line</style>
</hudson.plugins.plot.Plot>
</plots>
</hudson.plugins.plot.PlotPublisher>
</publishers>
</project>

View File

@ -0,0 +1,17 @@
# vim: sw=4 ts=4 et
publishers:
- plot:
- title: 'Sample graph'
yaxis: ''
csv-file-name: 'persisted.csv'
group: 'bench'
numbuilds: '1'
style: 'line'
use-description: false
series:
- file: 'data.csv'
label: ''
url: ''
format: 'csv'
display-table: false
inclusion-flag: 'off'

View File

@ -0,0 +1,25 @@
<?xml version="1.0" ?>
<project>
<publishers>
<hudson.plugins.plot.PlotPublisher>
<plots>
<hudson.plugins.plot.Plot>
<title>Sample graph</title>
<yaxis/>
<csvFileName>persisted.csv</csvFileName>
<series>
<hudson.plugins.plot.PropertiesSeries>
<file>data.properties</file>
<label/>
<fileType>properties</fileType>
</hudson.plugins.plot.PropertiesSeries>
</series>
<group>bench</group>
<useDescr>false</useDescr>
<numBuilds/>
<style>line</style>
</hudson.plugins.plot.Plot>
</plots>
</hudson.plugins.plot.PlotPublisher>
</publishers>
</project>

View File

@ -0,0 +1,14 @@
# vim: sw=4 ts=4 et
publishers:
- plot:
- title: 'Sample graph'
yaxis: ''
csv-file-name: 'persisted.csv'
group: 'bench'
numbuilds: '1'
style: 'line'
use-description: false
series:
- file: 'data.properties'
format: 'properties'
display-table: false

View File

@ -0,0 +1,27 @@
<?xml version="1.0" ?>
<project>
<publishers>
<hudson.plugins.plot.PlotPublisher>
<plots>
<hudson.plugins.plot.Plot>
<title>Sample graph</title>
<yaxis/>
<csvFileName>persisted.csv</csvFileName>
<series>
<hudson.plugins.plot.XMLSeries>
<file>data.xml</file>
<url/>
<xpathString>/data/set[1]/values/*</xpathString>
<nodeTypeString>NODE</nodeTypeString>
<fileType>xml</fileType>
</hudson.plugins.plot.XMLSeries>
</series>
<group>bench</group>
<useDescr>false</useDescr>
<numBuilds/>
<style>line</style>
</hudson.plugins.plot.Plot>
</plots>
</hudson.plugins.plot.PlotPublisher>
</publishers>
</project>

View File

@ -0,0 +1,16 @@
# vim: sw=4 ts=4 et
publishers:
- plot:
- title: 'Sample graph'
yaxis: ''
csv-file-name: 'persisted.csv'
group: 'bench'
numbuilds: '1'
style: 'line'
use-description: false
series:
- file: 'data.xml'
format: 'xml'
xpath: '/data/set[1]/values/*'
xpath-type: 'node'
display-table: false