Support sectioned views
Change-Id: Iaf352e8cc62644fb05afaae21630b9bec2cd30c0
This commit is contained in:
parent
587740ec75
commit
35d4da29d3
@ -310,18 +310,27 @@ DEFAULT_COLUMNS = [
|
|||||||
class List(jenkins_jobs.modules.base.Base):
|
class List(jenkins_jobs.modules.base.Base):
|
||||||
sequence = 0
|
sequence = 0
|
||||||
|
|
||||||
def root_xml(self, data):
|
def root_xml(self, data, sectioned=False):
|
||||||
root = XML.Element("hudson.model.ListView")
|
name = "hudson.model.ListView"
|
||||||
|
if sectioned:
|
||||||
|
name = "hudson.plugins.sectioned__view.ListViewSection"
|
||||||
|
root = XML.Element(name)
|
||||||
|
|
||||||
mapping = [
|
mapping = [("name", "name", None)]
|
||||||
("name", "name", None),
|
if not sectioned:
|
||||||
("description", "description", ""),
|
mapping.extend(
|
||||||
("filter-executors", "filterExecutors", False),
|
[
|
||||||
("filter-queue", "filterQueue", False),
|
("description", "description", ""),
|
||||||
]
|
("filter-executors", "filterExecutors", False),
|
||||||
|
("filter-queue", "filterQueue", False),
|
||||||
|
]
|
||||||
|
)
|
||||||
helpers.convert_mapping_to_xml(root, data, mapping, fail_required=True)
|
helpers.convert_mapping_to_xml(root, data, mapping, fail_required=True)
|
||||||
|
|
||||||
XML.SubElement(root, "properties", {"class": "hudson.model.View$PropertyList"})
|
if not sectioned:
|
||||||
|
XML.SubElement(
|
||||||
|
root, "properties", {"class": "hudson.model.View$PropertyList"}
|
||||||
|
)
|
||||||
|
|
||||||
jn_xml = XML.SubElement(root, "jobNames")
|
jn_xml = XML.SubElement(root, "jobNames")
|
||||||
jobnames = data.get("job-name", None)
|
jobnames = data.get("job-name", None)
|
||||||
@ -341,6 +350,13 @@ class List(jenkins_jobs.modules.base.Base):
|
|||||||
filter = getattr(view_jobfilters, jobfilter.replace("-", "_"))
|
filter = getattr(view_jobfilters, jobfilter.replace("-", "_"))
|
||||||
filter(job_filter_xml, jobfilters.get(jobfilter))
|
filter(job_filter_xml, jobfilters.get(jobfilter))
|
||||||
|
|
||||||
|
if sectioned:
|
||||||
|
mapping = [
|
||||||
|
("width", "width", "FULL", ["FULL", "HALF", "THIRD", "TWO_THIRDS"]),
|
||||||
|
("alignment", "alignment", "CENTER", ["CENTER", "LEFT", "RIGHT"]),
|
||||||
|
]
|
||||||
|
helpers.convert_mapping_to_xml(root, data, mapping, fail_required=True)
|
||||||
|
|
||||||
c_xml = XML.SubElement(root, "columns")
|
c_xml = XML.SubElement(root, "columns")
|
||||||
columns = data.get("columns", DEFAULT_COLUMNS)
|
columns = data.get("columns", DEFAULT_COLUMNS)
|
||||||
|
|
||||||
@ -369,11 +385,11 @@ class List(jenkins_jobs.modules.base.Base):
|
|||||||
x.append(XML.fromstring(tag))
|
x.append(XML.fromstring(tag))
|
||||||
else:
|
else:
|
||||||
XML.SubElement(c_xml, COLUMN_DICT[column])
|
XML.SubElement(c_xml, COLUMN_DICT[column])
|
||||||
mapping = [
|
mapping = [("regex", "includeRegex", None)]
|
||||||
("regex", "includeRegex", None),
|
if not sectioned:
|
||||||
("recurse", "recurse", False),
|
mapping.extend(
|
||||||
("status-filter", "statusFilter", None),
|
[("recurse", "recurse", False), ("status-filter", "statusFilter", None)]
|
||||||
]
|
)
|
||||||
helpers.convert_mapping_to_xml(root, data, mapping, fail_required=False)
|
helpers.convert_mapping_to_xml(root, data, mapping, fail_required=False)
|
||||||
|
|
||||||
return root
|
return root
|
||||||
|
102
jenkins_jobs/modules/view_sectioned.py
Normal file
102
jenkins_jobs/modules/view_sectioned.py
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
# Copyright 2019 Openstack Foundation
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""
|
||||||
|
The view sectioned module handles creating Jenkins Sectioned views.
|
||||||
|
|
||||||
|
To create a sectioned view specify ``sectioned`` in the ``view-type`` attribute
|
||||||
|
to the :ref:`view_sectioned` definition.
|
||||||
|
|
||||||
|
:View Parameters:
|
||||||
|
* **name** (`str`): The name of the view.
|
||||||
|
* **view-type** (`str`): The type of view.
|
||||||
|
* **description** (`str`): A description of the view. (default '')
|
||||||
|
* **filter-executors** (`bool`): Show only executors that can
|
||||||
|
execute the included views. (default false)
|
||||||
|
* **filter-queue** (`bool`): Show only included jobs in builder
|
||||||
|
queue. (default false)
|
||||||
|
* **sections** (`list`): The views to show in sections.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. literalinclude::
|
||||||
|
/../../tests/views/fixtures/view_sectioned.yaml
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import xml.etree.ElementTree as XML
|
||||||
|
import jenkins_jobs.modules.base
|
||||||
|
import jenkins_jobs.modules.helpers as helpers
|
||||||
|
from jenkins_jobs.modules import view_list
|
||||||
|
|
||||||
|
|
||||||
|
class Sectioned(jenkins_jobs.modules.base.Base):
|
||||||
|
def root_xml(self, data):
|
||||||
|
root = XML.Element("hudson.plugins.sectioned__view.SectionedView")
|
||||||
|
|
||||||
|
mapping = [
|
||||||
|
("name", "name", None),
|
||||||
|
("description", "description", ""),
|
||||||
|
("filter-executors", "filterExecutors", False),
|
||||||
|
("filter-queue", "filterQueue", False),
|
||||||
|
]
|
||||||
|
helpers.convert_mapping_to_xml(root, data, mapping, fail_required=True)
|
||||||
|
|
||||||
|
XML.SubElement(root, "properties", {"class": "hudson.model.View$PropertyList"})
|
||||||
|
|
||||||
|
s_xml = XML.SubElement(root, "sections")
|
||||||
|
sections = data.get("sections", [])
|
||||||
|
|
||||||
|
for section in sections:
|
||||||
|
if "view-type" not in section:
|
||||||
|
raise KeyError("This sectioned view is missing a view-type.", section)
|
||||||
|
if section["view-type"] == "list":
|
||||||
|
project = view_list.List(self.registry)
|
||||||
|
elif section["view-type"] == "text":
|
||||||
|
project = SectionedText(self.registry)
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
"Nested view-type %s is not known. Supported types: list, text."
|
||||||
|
% section["view-type"]
|
||||||
|
)
|
||||||
|
xml_project = project.root_xml(section, sectioned=True)
|
||||||
|
s_xml.append(xml_project)
|
||||||
|
|
||||||
|
return root
|
||||||
|
|
||||||
|
|
||||||
|
class SectionedText(jenkins_jobs.modules.base.Base):
|
||||||
|
def root_xml(self, data, sectioned=False):
|
||||||
|
assert sectioned
|
||||||
|
|
||||||
|
root = XML.Element("hudson.plugins.sectioned__view.TextSection")
|
||||||
|
|
||||||
|
# these are in the XML and look like from view_list,
|
||||||
|
# but the UI has no controls for them
|
||||||
|
jn_xml = XML.SubElement(root, "jobNames")
|
||||||
|
XML.SubElement(
|
||||||
|
jn_xml, "comparator", {"class": "hudson.util.CaseInsensitiveComparator"}
|
||||||
|
)
|
||||||
|
XML.SubElement(root, "jobFilters")
|
||||||
|
|
||||||
|
mapping = [
|
||||||
|
("name", "name", ""),
|
||||||
|
("width", "width", "FULL", ["FULL", "HALF", "THIRD", "TWO_THIRDS"]),
|
||||||
|
("alignment", "alignment", "CENTER", ["CENTER", "LEFT", "RIGHT"]),
|
||||||
|
("text", "text", None),
|
||||||
|
("style", "style", "NONE", ["NONE", "NOTE", "INFO", "WARNING", "TIP"]),
|
||||||
|
]
|
||||||
|
helpers.convert_mapping_to_xml(root, data, mapping, fail_required=True)
|
||||||
|
|
||||||
|
return root
|
@ -66,6 +66,7 @@ jenkins_jobs.views =
|
|||||||
list=jenkins_jobs.modules.view_list:List
|
list=jenkins_jobs.modules.view_list:List
|
||||||
nested=jenkins_jobs.modules.view_nested:Nested
|
nested=jenkins_jobs.modules.view_nested:Nested
|
||||||
pipeline=jenkins_jobs.modules.view_pipeline:Pipeline
|
pipeline=jenkins_jobs.modules.view_pipeline:Pipeline
|
||||||
|
sectioned=jenkins_jobs.modules.view_sectioned:Sectioned
|
||||||
jenkins_jobs.builders =
|
jenkins_jobs.builders =
|
||||||
raw=jenkins_jobs.modules.general:raw
|
raw=jenkins_jobs.modules.general:raw
|
||||||
jenkins_jobs.reporters =
|
jenkins_jobs.reporters =
|
||||||
|
@ -49,6 +49,7 @@ from jenkins_jobs.modules import view_all
|
|||||||
from jenkins_jobs.modules import view_list
|
from jenkins_jobs.modules import view_list
|
||||||
from jenkins_jobs.modules import view_nested
|
from jenkins_jobs.modules import view_nested
|
||||||
from jenkins_jobs.modules import view_pipeline
|
from jenkins_jobs.modules import view_pipeline
|
||||||
|
from jenkins_jobs.modules import view_sectioned
|
||||||
from jenkins_jobs.parser import YamlParser
|
from jenkins_jobs.parser import YamlParser
|
||||||
from jenkins_jobs.registry import ModuleRegistry
|
from jenkins_jobs.registry import ModuleRegistry
|
||||||
from jenkins_jobs.xml_config import XmlJob
|
from jenkins_jobs.xml_config import XmlJob
|
||||||
@ -242,6 +243,8 @@ class BaseScenariosTestCase(testscenarios.TestWithScenarios, BaseTestCase):
|
|||||||
project = view_nested.Nested(registry)
|
project = view_nested.Nested(registry)
|
||||||
elif yaml_content["view-type"] == "pipeline":
|
elif yaml_content["view-type"] == "pipeline":
|
||||||
project = view_pipeline.Pipeline(registry)
|
project = view_pipeline.Pipeline(registry)
|
||||||
|
elif yaml_content["view-type"] == "sectioned":
|
||||||
|
project = view_sectioned.Sectioned(registry)
|
||||||
else:
|
else:
|
||||||
raise InvalidAttributeError("view-type", yaml_content["view-type"])
|
raise InvalidAttributeError("view-type", yaml_content["view-type"])
|
||||||
|
|
||||||
|
34
tests/views/fixtures/view_sectioned.xml
Normal file
34
tests/views/fixtures/view_sectioned.xml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<hudson.plugins.sectioned__view.SectionedView>
|
||||||
|
<name>SectionedViewTest</name>
|
||||||
|
<description/>
|
||||||
|
<filterExecutors>false</filterExecutors>
|
||||||
|
<filterQueue>false</filterQueue>
|
||||||
|
<properties class="hudson.model.View$PropertyList"/>
|
||||||
|
<sections>
|
||||||
|
<hudson.plugins.sectioned__view.ListViewSection>
|
||||||
|
<name>testName</name>
|
||||||
|
<jobNames>
|
||||||
|
<comparator class="hudson.util.CaseInsensitiveComparator"/>
|
||||||
|
<string>testJobName</string>
|
||||||
|
</jobNames>
|
||||||
|
<jobFilters/>
|
||||||
|
<width>HALF</width>
|
||||||
|
<alignment>LEFT</alignment>
|
||||||
|
<columns>
|
||||||
|
<hudson.views.JobColumn/>
|
||||||
|
</columns>
|
||||||
|
</hudson.plugins.sectioned__view.ListViewSection>
|
||||||
|
<hudson.plugins.sectioned__view.TextSection>
|
||||||
|
<jobNames>
|
||||||
|
<comparator class="hudson.util.CaseInsensitiveComparator"/>
|
||||||
|
</jobNames>
|
||||||
|
<jobFilters/>
|
||||||
|
<name/>
|
||||||
|
<width>FULL</width>
|
||||||
|
<alignment>CENTER</alignment>
|
||||||
|
<text>test text</text>
|
||||||
|
<style>INFO</style>
|
||||||
|
</hudson.plugins.sectioned__view.TextSection>
|
||||||
|
</sections>
|
||||||
|
</hudson.plugins.sectioned__view.SectionedView>
|
14
tests/views/fixtures/view_sectioned.yaml
Normal file
14
tests/views/fixtures/view_sectioned.yaml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
name: SectionedViewTest
|
||||||
|
view-type: sectioned
|
||||||
|
sections:
|
||||||
|
- name: testName
|
||||||
|
job-name:
|
||||||
|
- testJobName
|
||||||
|
columns:
|
||||||
|
- job
|
||||||
|
view-type: list
|
||||||
|
width: HALF
|
||||||
|
alignment: LEFT
|
||||||
|
- text: test text
|
||||||
|
style: INFO
|
||||||
|
view-type: text
|
@ -17,6 +17,7 @@ from jenkins_jobs.modules import view_all
|
|||||||
from jenkins_jobs.modules import view_list
|
from jenkins_jobs.modules import view_list
|
||||||
from jenkins_jobs.modules import view_nested
|
from jenkins_jobs.modules import view_nested
|
||||||
from jenkins_jobs.modules import view_pipeline
|
from jenkins_jobs.modules import view_pipeline
|
||||||
|
from jenkins_jobs.modules import view_sectioned
|
||||||
from tests import base
|
from tests import base
|
||||||
|
|
||||||
|
|
||||||
@ -42,3 +43,9 @@ class TestCaseModuleViewPipeline(base.BaseScenariosTestCase):
|
|||||||
fixtures_path = os.path.join(os.path.dirname(__file__), "fixtures")
|
fixtures_path = os.path.join(os.path.dirname(__file__), "fixtures")
|
||||||
scenarios = base.get_scenarios(fixtures_path)
|
scenarios = base.get_scenarios(fixtures_path)
|
||||||
klass = view_pipeline.Pipeline
|
klass = view_pipeline.Pipeline
|
||||||
|
|
||||||
|
|
||||||
|
class TestCaseModuleViewSectioned(base.BaseScenariosTestCase):
|
||||||
|
fixtures_path = os.path.join(os.path.dirname(__file__), "fixtures")
|
||||||
|
scenarios = base.get_scenarios(fixtures_path)
|
||||||
|
klass = view_sectioned.Sectioned
|
||||||
|
Loading…
Reference in New Issue
Block a user