launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #01690
[Merge] lp:~julian-edwards/launchpad/api-expose-builders into lp:launchpad/devel
Julian Edwards has proposed merging lp:~julian-edwards/launchpad/api-expose-builders into lp:launchpad/devel.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
= Summary =
Expose IBuilder in the webservice
== Implementation details ==
The usual trivial-ish interface changes. /builders is a top-level collection.
== Tests ==
bin/test -cvvt xx-builders.txt
--
https://code.launchpad.net/~julian-edwards/launchpad/api-expose-builders/+merge/39379
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~julian-edwards/launchpad/api-expose-builders into lp:launchpad/devel.
=== modified file 'lib/lp/buildmaster/interfaces/builder.py'
--- lib/lp/buildmaster/interfaces/builder.py 2010-09-23 18:17:21 +0000
+++ lib/lp/buildmaster/interfaces/builder.py 2010-10-26 15:26:45 +0000
@@ -19,6 +19,16 @@
'ProtocolVersionMismatch',
]
+from lazr.restful.declarations import (
+ collection_default_content,
+ export_as_webservice_collection,
+ export_as_webservice_entry,
+ export_read_operation,
+ exported,
+ operation_parameters,
+ operation_returns_entry,
+ )
+
from zope.interface import (
Attribute,
Interface,
@@ -38,6 +48,7 @@
from lp.registry.interfaces.role import IHasOwner
from lp.services.fields import (
Description,
+ PersonChoice,
Title,
)
@@ -92,63 +103,66 @@
machine status representation, including the field/properties:
virtualized, builderok, status, failnotes and currentjob.
"""
+ export_as_webservice_entry()
+
id = Attribute("Builder identifier")
+
processor = Choice(
title=_('Processor'), required=True, vocabulary='Processor',
description=_('Build Slave Processor, used to identify '
'which jobs can be built by this device.'))
- owner = Choice(
+ owner = exported(PersonChoice(
title=_('Owner'), required=True, vocabulary='ValidOwner',
description=_('Builder owner, a Launchpad member which '
- 'will be responsible for this device.'))
+ 'will be responsible for this device.')))
- url = TextLine(
+ url = exported(TextLine(
title=_('URL'), required=True, constraint=builder_url_validator,
description=_('The URL to the build machine, used as a unique '
'identifier. Includes protocol, host and port only, '
- 'e.g.: http://farm.com:8221/'))
+ 'e.g.: http://farm.com:8221/')))
- name = TextLine(
+ name = exported(TextLine(
title=_('Name'), required=True, constraint=name_validator,
- description=_('Builder Slave Name used for reference proposes'))
+ description=_('Builder Slave Name used for reference proposes')))
- title = Title(
+ title = exported(Title(
title=_('Title'), required=True,
- description=_('The builder slave title. Should be just a few words.'))
+ description=_('The builder slave title. Should be just a few words.')))
- description = Description(
+ description = exported(Description(
title=_('Description'), required=False,
description=_('The builder slave description, may be several '
'paragraphs of text, giving the highlights and '
- 'details.'))
+ 'details.')))
- virtualized = Bool(
+ virtualized = exported(Bool(
title=_('Virtualized'), required=True, default=False,
description=_('Whether or not the builder is a virtual Xen '
- 'instance.'))
+ 'instance.')))
- manual = Bool(
+ manual = exported(Bool(
title=_('Manual Mode'), required=False, default=False,
description=_('The auto-build system does not dispatch '
- 'jobs automatically for slaves in manual mode.'))
+ 'jobs automatically for slaves in manual mode.')))
- builderok = Bool(
+ builderok = exported(Bool(
title=_('Builder State OK'), required=True, default=True,
- description=_('Whether or not the builder is ok'))
+ description=_('Whether or not the builder is ok')))
- failnotes = Text(
+ failnotes = exported(Text(
title=_('Failure Notes'), required=False,
- description=_('The reason for a builder not being ok'))
+ description=_('The reason for a builder not being ok')))
- vm_host = TextLine(
+ vm_host = exported(TextLine(
title=_('Virtual Machine Host'), required=False,
description=_('The machine hostname hosting the virtual '
- 'buildd-slave, e.g.: foobar-host.ppa'))
+ 'buildd-slave, e.g.: foobar-host.ppa')))
- active = Bool(
+ active = exported(Bool(
title=_('Publicly Visible'), required=True, default=True,
- description=_('Whether or not to present the builder publicly.'))
+ description=_('Whether or not to present the builder publicly.')))
slave = Attribute("xmlrpclib.Server instance corresponding to builder.")
@@ -159,9 +173,9 @@
"new jobs. "),
required=False)
- failure_count = Int(
+ failure_count = exported(Int(
title=_('Failure Count'), required=False, default=0,
- description=_("Number of consecutive failures for this builder."))
+ description=_("Number of consecutive failures for this builder.")))
current_build_behavior = Field(
title=u"The current behavior of the builder for the current job.",
@@ -312,6 +326,7 @@
Methods on this interface should deal with the set of Builders:
methods that affect a single Builder should be on IBuilder.
"""
+ export_as_webservice_collection(IBuilder)
title = Attribute('Title')
@@ -321,6 +336,13 @@
def __getitem__(name):
"""Retrieve a builder by name"""
+ @operation_parameters(
+ name=TextLine(title=_("Builder name"), required=True))
+ @operation_returns_entry(IBuilder)
+ @export_read_operation()
+ def getByName(name):
+ """Retrieve a builder by name"""
+
def new(processor, url, name, title, description, owner,
active=True, virtualized=False, vm_host=None):
"""Create a new Builder entry.
@@ -339,6 +361,7 @@
def get(builder_id):
"""Return the IBuilder with the given builderid."""
+ @collection_default_content()
def getBuilders():
"""Return all active configured builders."""
=== modified file 'lib/lp/buildmaster/model/builder.py'
--- lib/lp/buildmaster/model/builder.py 2010-09-24 13:39:27 +0000
+++ lib/lp/buildmaster/model/builder.py 2010-10-26 15:26:45 +0000
@@ -775,12 +775,16 @@
def __iter__(self):
return iter(Builder.select())
- def __getitem__(self, name):
+ def getByName(self, name):
+ """See IBuilderSet."""
try:
return Builder.selectOneBy(name=name)
except SQLObjectNotFound:
raise NotFoundError(name)
+ def __getitem__(self, name):
+ return self.getByName(name)
+
def new(self, processor, url, name, title, description, owner,
active=True, virtualized=False, vm_host=None, manual=True):
"""See IBuilderSet."""
=== added file 'lib/lp/soyuz/stories/webservice/xx-builders.txt'
--- lib/lp/soyuz/stories/webservice/xx-builders.txt 1970-01-01 00:00:00 +0000
+++ lib/lp/soyuz/stories/webservice/xx-builders.txt 2010-10-26 15:26:45 +0000
@@ -0,0 +1,68 @@
+========
+Builders
+========
+
+The webservice exposes a top-level collection called "builders" which
+contains all the registered builders in the Launchpad build farm.
+
+ >>> launchpad = launchpadlib_for(
+ ... 'builders test', 'no-priv', version='devel')
+ >>> builders = launchpad.builders
+
+Iterating over the collection is possible:
+
+ >>> for builder in builders:
+ ... print builder
+ http://api.launchpad.dev/devel/builders/bob
+ http://api.launchpad.dev/devel/builders/frog
+
+An individual builder can be retrieved by name by using the getByName()
+method on "builders":
+
+ >>> bob = builders.getByName(name="bob")
+
+Each builder has a number of properties exposed:
+
+ >>> for attribute in bob.lp_attributes:
+ ... print attribute
+ self_link
+ ...
+ active
+ builderok
+ description
+ failnotes
+ failure_count
+ manual
+ name
+ title
+ url
+ virtualized
+ vm_host
+
+
+Changing builder properties
+===========================
+
+If an authorized person (usually a member of the buildd-admins team)
+wishes to amend some property of a builder, the usual webservice 'lp_save'
+operation is used.
+
+Our "bob" builder was retrieved using the no-priv user, and he does not
+have permission to save changes:
+
+ >>> print bob.active
+ True
+ >>> bob.active = False
+ >>> bob.lp_save()
+ Traceback (most recent call last):
+ ...
+ Unauthorized:...
+
+'cprov', who is a buildd-admin, is able to change the data:
+
+ >>> launchpad = launchpadlib_for(
+ ... 'builders test', 'cprov', version='devel')
+ >>> bob = launchpad.builders.getByName(name="bob")
+ >>> bob.active = False
+ >>> bob.lp_save()
+
Follow ups