Skip to content

Commit

Permalink
data/forcescheduler docs and tests
Browse files Browse the repository at this point in the history
Signed-off-by: Pierre Tardy <pierre.tardy@intel.com>
  • Loading branch information
Pierre Tardy committed Nov 21, 2013
1 parent fa362cf commit 9ef7a38
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 14 deletions.
32 changes: 18 additions & 14 deletions master/buildbot/data/forceschedulers.py
Expand Up @@ -23,9 +23,9 @@

def forceScheduler2Data(sched):
ret = dict(all_fields=[],
name=sched.name,
label=sched.label,
builder_names=sched.builderNames)
name=unicode(sched.name),
label=unicode(sched.label),
builder_names=map(unicode, sched.builderNames))
ret["all_fields"] = [field.getSpec() for field in sched.all_fields]
return ret

Expand All @@ -40,17 +40,20 @@ class ForceSchedulerEndpoint(base.Endpoint):
def get(self, resultSpec, kwargs):
for sched in self.master.allSchedulers():
if sched.name == kwargs['schedulername'] and isinstance(sched, forcesched.ForceScheduler):
return forceScheduler2Data(sched)
return defer.succeed(forceScheduler2Data(sched))
return defer.succeed(None)

@defer.inlineCallbacks
def control(self, method, args, kwargs):
for sched in self.master.allSchedulers():
if sched.name == kwargs['schedulername'] and isinstance(sched, forcesched.ForceScheduler):
try:
res = yield sched.force("user", **args)
defer.returnValue(res)
except forcesched.CollectedValidationError as e:
raise BadJsonRpc2(e.errors, JSONRPC_CODES["invalid_params"])
def control(self, action, args, kwargs):
if action == "force":
for sched in self.master.allSchedulers():
if sched.name == kwargs['schedulername'] and isinstance(sched, forcesched.ForceScheduler):
try:
res = yield sched.force("user", **args)
defer.returnValue(res)
except forcesched.CollectedValidationError as e:
raise BadJsonRpc2(e.errors, JSONRPC_CODES["invalid_params"])
defer.returnValue(None)


class ForceSchedulersEndpoint(base.Endpoint):
Expand Down Expand Up @@ -84,7 +87,8 @@ class ForceScheduler(base.ResourceType):
keyFields = []

class EntityType(types.Entity):
name = types.String()
builder_names = types.List(of=types.Identifier())
name = types.Identifier(20)
label = types.String()
builder_names = types.List(of=types.Identifier(20))
all_fields = types.List(of=types.JsonObject())
entityType = EntityType(name)
2 changes: 2 additions & 0 deletions master/buildbot/schedulers/forcesched.py
Expand Up @@ -110,6 +110,8 @@ def __init__(self, name, label=None, tablabel=None, regex=None, **kw):
@type regex: unicode or regex
"""

if name in ["owner", "builderNames", "builderid"]:
config.error("%s cannot be used as a parameter name, because it is reserved" % (name,))
self.name = name
self.label = name if label is None else label
self.tablabel = self.label if tablabel is None else tablabel
Expand Down
165 changes: 165 additions & 0 deletions master/buildbot/test/unit/test_data_forceschedulers.py
@@ -0,0 +1,165 @@
# This file is part of Buildbot. Buildbot is free software: you can
# redistribute it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright Buildbot Team Members

from buildbot.data import forceschedulers
from buildbot.schedulers.forcesched import ForceScheduler
from buildbot.test.util import endpoint
from twisted.internet import defer
from twisted.trial import unittest


expected_default = {
'all_fields': [{'columns': 1,
'default': '',
'fields': [{'default': '',
'fullName': 'username',
'hide': False,
'label': 'Your name:',
'multiple': False,
'name': 'username',
'need_email': True,
'regex': None,
'required': False,
'size': 30,
'tablabel': 'Your name:',
'type': 'text'},
{'default': 'force build',
'fullName': 'reason',
'hide': False,
'label': 'reason',
'multiple': False,
'name': 'reason',
'regex': None,
'required': False,
'size': 20,
'tablabel': 'reason',
'type': 'text'}],
'fullName': None,
'hide': False,
'label': '',
'layout': 'vertical',
'multiple': False,
'name': '',
'regex': None,
'required': False,
'tablabel': '',
'type': 'nested'},
{'columns': 2,
'default': '',
'fields': [{'default': '',
'fullName': 'project',
'hide': False,
'label': 'Project:',
'multiple': False,
'name': 'project',
'regex': None,
'required': False,
'size': 10,
'tablabel': 'Project:',
'type': 'text'},
{'default': '',
'fullName': 'repository',
'hide': False,
'label': 'Repository:',
'multiple': False,
'name': 'repository',
'regex': None,
'required': False,
'size': 10,
'tablabel': 'Repository:',
'type': 'text'},
{'default': '',
'fullName': 'branch',
'hide': False,
'label': 'Branch:',
'multiple': False,
'name': 'branch',
'regex': None,
'required': False,
'size': 10,
'tablabel': 'Branch:',
'type': 'text'},
{'default': '',
'fullName': 'revision',
'hide': False,
'label': 'Revision:',
'multiple': False,
'name': 'revision',
'regex': None,
'required': False,
'size': 10,
'tablabel': 'Revision:',
'type': 'text'}],
'fullName': None,
'hide': False,
'label': '',
'layout': 'vertical',
'multiple': False,
'name': '',
'regex': None,
'required': False,
'tablabel': '',
'type': 'nested'}],
'builder_names': [u'builder'],
'label': u'defaultforce',
'name': u'defaultforce'}


class ForceschedulerEndpoint(endpoint.EndpointMixin, unittest.TestCase):

endpointClass = forceschedulers.ForceSchedulerEndpoint
resourceTypeClass = forceschedulers.ForceScheduler

def setUp(self):
self.setUpEndpoint()
scheds = [ForceScheduler(
name="defaultforce",
builderNames=["builder"])]
self.master.allSchedulers = lambda: scheds

def tearDown(self):
self.tearDownEndpoint()

@defer.inlineCallbacks
def test_get_existing(self):
res = yield self.callGet(('forceschedulers', "defaultforce"))
self.validateData(res)
self.assertEquals(res, expected_default)

@defer.inlineCallbacks
def test_get_missing(self):
res = yield self.callGet(('forceschedulers', 'foo'))
self.assertEquals(res, None)


class ForceSchedulersEndpoint(endpoint.EndpointMixin, unittest.TestCase):

endpointClass = forceschedulers.ForceSchedulersEndpoint
resourceTypeClass = forceschedulers.ForceScheduler

def setUp(self):
self.setUpEndpoint()
scheds = [ForceScheduler(
name="defaultforce",
builderNames=["builder"])]
self.master.allSchedulers = lambda: scheds

def tearDown(self):
self.tearDownEndpoint()

@defer.inlineCallbacks
def test_get_existing(self):
res = yield self.callGet(('forceschedulers', ))
self.assertEquals(res, [expected_default])
1 change: 1 addition & 0 deletions master/docs/developer/data.rst
Expand Up @@ -569,6 +569,7 @@ All strings in the data model are unicode strings.
rtype-sourcestamp
rtype-patch
rtype-scheduler
rtype-forcescheduler
rtype-build
rtype-step
rtype-log
Expand Down
34 changes: 34 additions & 0 deletions master/docs/developer/rtype-forcescheduler.rst
@@ -0,0 +1,34 @@
ForceScheduler
==============

.. bb:rtype:: forcescheduler
:attr string name: name of this scheduler
:attr string name: label of this scheduler to be displayed in the ui
:attr list if string buildername: names of the builders that this scheduler can trig
:attr jsonObject all_fields: description of the fields that will be displayed in the UI

A forcescheduler initiates builds, via a formular in the web UI.
At the moment, forceschedulers must be defined on all the masters where a web ui is configured. A particular forcescheduler runs on the master where the web request was sent.

.. bb:rpath:: /forceschedulers
This path selects all forceschedulers.

This endpoint has a control method with the following action:

* force:

create a buildrequest with this forcescheduler. It takes as parameters:

- owner: the username that requested this build.
- builderid: the builderid of the builder to force if builderNames is not specified
- builderNames: the buildername of the builder to force
- other params: other named params are the configured parameters of the forcescheduler

.. bb:rpath:: /forceschedulers/:schedulername
:pathkey string schedulername: the name of the scheduler

This path selects a specific scheduler, identified by name.

0 comments on commit 9ef7a38

Please sign in to comment.