Merge lp:~wgrant/launchpad/builderset-new-api into lp:launchpad

Proposed by William Grant
Status: Merged
Merged at revision: 16986
Proposed branch: lp:~wgrant/launchpad/builderset-new-api
Merge into: lp:launchpad
Diff against target: 189 lines (+64/-21)
5 files modified
lib/lp/buildmaster/configure.zcml (+3/-0)
lib/lp/buildmaster/doc/builder.txt (+4/-2)
lib/lp/buildmaster/interfaces/builder.py (+23/-15)
lib/lp/buildmaster/tests/test_webservice.py (+30/-1)
lib/lp/testing/factory.py (+4/-3)
To merge this branch: bzr merge lp:~wgrant/launchpad/builderset-new-api
Reviewer Review Type Date Requested Status
Celso Providelo (community) Approve
Review via email: mp+216861@code.launchpad.net

Commit message

Export BuilderSet.new() on the webservice.

Description of the change

Export BuilderSet.new() on the webservice. All pretty trivial, except for moving BuilderSet.new to a new interface restricted by launchpad.Admin like the view.

To post a comment you must log in.
Revision history for this message
Celso Providelo (cprov) wrote :

Looks good!

It seems to be a good compromise before re-thinking the buildmaster component for the Cloud(tm). However, since we do not have a remove() builders should be created with caution, even by Administrators.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/buildmaster/configure.zcml'
2--- lib/lp/buildmaster/configure.zcml 2013-11-20 17:10:19 +0000
3+++ lib/lp/buildmaster/configure.zcml 2014-04-23 11:07:46 +0000
4@@ -29,6 +29,9 @@
5 provides="lp.buildmaster.interfaces.builder.IBuilderSet">
6 <allow
7 interface="lp.buildmaster.interfaces.builder.IBuilderSet"/>
8+ <require
9+ permission="launchpad.Admin"
10+ interface="lp.buildmaster.interfaces.builder.IBuilderSetAdmin"/>
11 </securedutility>
12 <adapter
13 provides="lp.services.webapp.interfaces.IBreadcrumb"
14
15=== modified file 'lib/lp/buildmaster/doc/builder.txt'
16--- lib/lp/buildmaster/doc/builder.txt 2013-11-28 12:23:01 +0000
17+++ lib/lp/buildmaster/doc/builder.txt 2014-04-23 11:07:46 +0000
18@@ -69,8 +69,10 @@
19
20 The 'new' method will create a new builder in the database.
21
22- >>> bnew = builderset.new(
23- ... [1], 'http://dummy.com:8221/', 'dummy', 'Dummy Title', 1)
24+ >>> from lp.testing import admin_logged_in
25+ >>> with admin_logged_in():
26+ ... bnew = builderset.new(
27+ ... [1], 'http://dummy.com:8221/', 'dummy', 'Dummy Title', 1)
28 >>> bnew.name
29 u'dummy'
30
31
32=== modified file 'lib/lp/buildmaster/interfaces/builder.py'
33--- lib/lp/buildmaster/interfaces/builder.py 2013-11-28 08:51:32 +0000
34+++ lib/lp/buildmaster/interfaces/builder.py 2014-04-23 11:07:46 +0000
35@@ -17,15 +17,18 @@
36 ]
37
38 from lazr.restful.declarations import (
39+ call_with,
40 collection_default_content,
41 export_as_webservice_collection,
42 export_as_webservice_entry,
43+ export_factory_operation,
44 export_read_operation,
45 exported,
46 operation_for_version,
47 operation_parameters,
48 operation_returns_collection_of,
49 operation_returns_entry,
50+ REQUEST_USER,
51 )
52 from lazr.restful.fields import (
53 Reference,
54@@ -165,7 +168,7 @@
55 'buildd-slave, e.g.: foobar-host.ppa')))
56
57 active = exported(Bool(
58- title=_('Publicly Visible'), required=True, default=True,
59+ title=_('Publicly Visible'), required=False, default=True,
60 description=_('Whether or not to present the builder publicly.')))
61
62 currentjob = Attribute("BuildQueue instance for job being processed.")
63@@ -210,7 +213,25 @@
64 """
65
66
67-class IBuilderSet(Interface):
68+class IBuilderSetAdmin(Interface):
69+
70+ @call_with(owner=REQUEST_USER)
71+ @export_factory_operation(
72+ IBuilder,
73+ ['processors', 'url', 'name', 'title', 'active', 'virtualized',
74+ 'vm_host'])
75+ @operation_for_version('devel')
76+ def new(processors, url, name, title, owner, active=True,
77+ virtualized=False, vm_host=None):
78+ """Create a new builder.
79+
80+ The builder will be set to manual. An admin needs to verify its
81+ configuration and set it to automatic before jobs will be
82+ dispatched.
83+ """
84+
85+
86+class IBuilderSet(IBuilderSetAdmin):
87 """Collections of builders.
88
89 IBuilderSet provides access to all Builders in the system,
90@@ -219,7 +240,6 @@
91 methods that affect a single Builder should be on IBuilder.
92 """
93 export_as_webservice_collection(IBuilder)
94-
95 title = Attribute('Title')
96
97 def __iter__():
98@@ -235,18 +255,6 @@
99 def getByName(name):
100 """Retrieve a builder by name"""
101
102- def new(processors, url, name, title, owner, active=True,
103- virtualized=False, vm_host=None):
104- """Create a new Builder entry.
105-
106- Additionally to the given arguments, builder are created with
107- 'builderok' and 'manual' set to True.
108-
109- It means that, once created, they will be presented as 'functional'
110- in the UI but will not receive any job until an administrator move
111- it to the automatic mode.
112- """
113-
114 def count():
115 """Return the number of builders in the system."""
116
117
118=== modified file 'lib/lp/buildmaster/tests/test_webservice.py'
119--- lib/lp/buildmaster/tests/test_webservice.py 2013-11-28 08:51:32 +0000
120+++ lib/lp/buildmaster/tests/test_webservice.py 2014-04-23 11:07:46 +0000
121@@ -5,13 +5,21 @@
122
123 __metaclass__ = type
124
125+from zope.component import getUtility
126+
127+from lp.registry.interfaces.person import IPersonSet
128+from lp.services.webapp.interfaces import OAuthPermission
129 from lp.testing import (
130+ admin_logged_in,
131 api_url,
132 logout,
133 TestCaseWithFactory,
134 )
135 from lp.testing.layers import DatabaseFunctionalLayer
136-from lp.testing.pages import LaunchpadWebServiceCaller
137+from lp.testing.pages import (
138+ LaunchpadWebServiceCaller,
139+ webservice_for_person,
140+ )
141
142
143 class TestBuildersCollection(TestCaseWithFactory):
144@@ -49,6 +57,27 @@
145 ['quantum_builder1', 'quantum_builder2'],
146 sorted(builder['name'] for builder in results['entries']))
147
148+ def test_new(self):
149+ person = self.factory.makePerson()
150+ badmins = getUtility(IPersonSet).getByName('launchpad-buildd-admins')
151+ webservice = webservice_for_person(
152+ person, permission=OAuthPermission.WRITE_PRIVATE)
153+ args = dict(
154+ name='foo', processors=['/+processors/386'], title='foobar',
155+ url='http://foo.buildd:8221/', virtualized=False,
156+ api_version='devel')
157+
158+ response = webservice.named_post('/builders', 'new', **args)
159+ self.assertEqual(401, response.status)
160+
161+ with admin_logged_in():
162+ badmins.addMember(person, badmins)
163+ response = webservice.named_post('/builders', 'new', **args)
164+ self.assertEqual(201, response.status)
165+
166+ self.assertEqual(
167+ 'foobar', webservice.get('/builders/foo').jsonBody()['title'])
168+
169
170 class TestBuilderEntry(TestCaseWithFactory):
171 layer = DatabaseFunctionalLayer
172
173=== modified file 'lib/lp/testing/factory.py'
174--- lib/lp/testing/factory.py 2014-02-24 07:19:52 +0000
175+++ lib/lp/testing/factory.py 2014-04-23 11:07:46 +0000
176@@ -2760,9 +2760,10 @@
177 if owner is None:
178 owner = self.makePerson()
179
180- return getUtility(IBuilderSet).new(
181- processors, url, name, title, owner, active, virtualized, vm_host,
182- manual=manual)
183+ with admin_logged_in():
184+ return getUtility(IBuilderSet).new(
185+ processors, url, name, title, owner, active,
186+ virtualized, vm_host, manual=manual)
187
188 def makeRecipeText(self, *branches):
189 if len(branches) == 0: