Merge lp:~fabricematrat/charmworld/redirect-interfaces into lp:charmworld

Proposed by Fabrice Matrat
Status: Merged
Approved by: Fabrice Matrat
Approved revision: 521
Merged at revision: 522
Proposed branch: lp:~fabricematrat/charmworld/redirect-interfaces
Merge into: lp:charmworld
Diff against target: 317 lines (+62/-104)
2 files modified
charmworld/views/charms.py (+45/-21)
charmworld/views/tests/test_charms.py (+17/-83)
To merge this branch: bzr merge lp:~fabricematrat/charmworld/redirect-interfaces
Reviewer Review Type Date Requested Status
Juju Gui Bot continuous-integration Approve
Francesco Banconi Approve
Brad Crittenden (community) code + qa Approve
Review via email: mp+249681@code.launchpad.net

Commit message

Added redirection for interface, config, hook
R=bac, frankban

Description of the change

Added redirection for interface, config, hook

To post a comment you must log in.
Revision history for this message
Brad Crittenden (bac) wrote :

Code looks good.
QA OK

review: Approve (code + qa)
Revision history for this message
Francesco Banconi (frankban) wrote :

Looks good.

review: Approve
Revision history for this message
Juju Gui Bot (juju-gui-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'charmworld/views/charms.py'
--- charmworld/views/charms.py 2015-02-09 18:46:13 +0000
+++ charmworld/views/charms.py 2015-02-13 16:29:40 +0000
@@ -35,7 +35,6 @@
35 format_change,35 format_change,
36 format_proof,36 format_proof,
37 found,37 found,
38 interfaces,
39 name_filter,38 name_filter,
40)39)
4140
@@ -356,30 +355,62 @@
356 route_name="hook",355 route_name="hook",
357 renderer="charmworld:templates/hook.pt")356 renderer="charmworld:templates/hook.pt")
358def hook(request):357def hook(request):
359 charm = Charm(find_charm(request, promulgated=True))358 _reconcile_revision(request)
360 return _hook_view(request, charm, request.matchdict["hook"])359 redirect_url = request.registry.settings.get('redirect_jujucharms')
360 match = request.matchdict
361 location = '{url}/{charm}/{series}'.format(
362 url=redirect_url,
363 charm=match['charm'],
364 series=match['series']
365 )
366 raise HTTPMovedPermanently(location=location)
361367
362368
363@cached_view_config(369@cached_view_config(
364 route_name="personal-hook",370 route_name="personal-hook",
365 renderer="charmworld:templates/hook.pt")371 renderer="charmworld:templates/hook.pt")
366def personal_hook(request):372def personal_hook(request):
367 charm = Charm(find_charm(request))373 _reconcile_revision(request)
368 return _hook_view(request, charm, request.matchdict["hook"])374 redirect_url = request.registry.settings.get('redirect_jujucharms')
375 match = request.matchdict
376 location = '{url}/u/{owner}/{charm}/{series}'.format(
377 url=redirect_url,
378 owner=match['owner'],
379 charm=match['charm'],
380 series=match['series']
381 )
382 raise HTTPMovedPermanently(location=location)
369383
370384
371@cached_view_config(385@cached_view_config(
372 route_name="config",386 route_name="config",
373 renderer="charmworld:templates/config.pt")387 renderer="charmworld:templates/config.pt")
374def config(request):388def config(request):
375 return _config_view(find_charm(request, promulgated=True))389 _reconcile_revision(request)
390 redirect_url = request.registry.settings.get('redirect_jujucharms')
391 match = request.matchdict
392 location = '{url}/{charm}/{series}#configuration'.format(
393 url=redirect_url,
394 charm=match['charm'],
395 series=match['series']
396 )
397 raise HTTPMovedPermanently(location=location)
376398
377399
378@cached_view_config(400@cached_view_config(
379 route_name="personal-config",401 route_name="personal-config",
380 renderer="charmworld:templates/config.pt")402 renderer="charmworld:templates/config.pt")
381def personal_config(request):403def personal_config(request):
382 return _config_view(find_charm(request))404 _reconcile_revision(request)
405 redirect_url = request.registry.settings.get('redirect_jujucharms')
406 match = request.matchdict
407 location = '{url}/u/{owner}/{charm}/{series}#configuration'.format(
408 url=redirect_url,
409 owner=match['owner'],
410 charm=match['charm'],
411 series=match['series']
412 )
413 raise HTTPMovedPermanently(location=location)
383414
384415
385@cached_view_config(416@cached_view_config(
@@ -389,10 +420,8 @@
389 route_name="interface-collection",420 route_name="interface-collection",
390 renderer="charmworld:templates/interface-collection-redux.pt")421 renderer="charmworld:templates/interface-collection-redux.pt")
391def interface_collection(request):422def interface_collection(request):
392 return {423 redirect_url = request.registry.settings.get('redirect_jujucharms')
393 "interfaces": interfaces(request.db),424 raise HTTPMovedPermanently(location='{}/solutions'.format(redirect_url))
394 "project": request.registry.settings.get('project_name', 'Not Set.'),
395 }
396425
397426
398@cached_view_config(427@cached_view_config(
@@ -400,16 +429,11 @@
400 renderer="charmworld:templates/interface.pt")429 renderer="charmworld:templates/interface.pt")
401def interface(request):430def interface(request):
402 iface = request.matchdict["interface"]431 iface = request.matchdict["interface"]
403 return {432 redirect_url = request.registry.settings.get('redirect_jujucharms')
404 "interface": iface,433 raise HTTPMovedPermanently(
405 "providers": [434 location='{url}/q/{interface}'.format(url=redirect_url,
406 Charm(charm)435 interface=iface)
407 for charm in find_charms(request.db, {"i_provides": iface},436 )
408 sort=[("name", pymongo.ASCENDING)])],
409 "requirers": [
410 Charm(charm)
411 for charm in find_charms(request.db, {"i_requires": iface},
412 sort=[("name", pymongo.ASCENDING)])]}
413437
414438
415@view_config(439@view_config(
416440
=== modified file 'charmworld/views/tests/test_charms.py'
--- charmworld/views/tests/test_charms.py 2015-02-09 14:16:33 +0000
+++ charmworld/views/tests/test_charms.py 2015-02-13 16:29:40 +0000
@@ -159,64 +159,29 @@
159 self.assertIn('/q/me/one', e.exception.location)159 self.assertIn('/q/me/one', e.exception.location)
160160
161 def test_interface(self):161 def test_interface(self):
162 # interface() returns all charms requiring or providing a given162 request = self.getRequest()
163 # interface.163 request.matchdict = {'interface': 'httpX'}
164 providing = Charm(factory.makeCharm(164 with self.assertRaises(HTTPMovedPermanently) as e:
165 self.db, provides={'foo': {'interface': 'httpX'}})[1])165 interface(request)
166 requiring = Charm(factory.makeCharm(166 self.assertIn('/q/httpX', e.exception.location)
167 self.db, requires={'bar': {'interface': 'httpX'}})[1])
168 ignore, other = factory.makeCharm(self.db)
169 request = self.getRequest()
170 request.matchdict = {'interface': 'httpX'}
171 response = interface(request)
172 self.assertEqual('httpX', response['interface'])
173 found_providing = response['providers']
174 self.assertEqual(1, len(found_providing))
175 self.assertEqual(providing, found_providing[0])
176 found_requiring = response['requirers']
177 self.assertEqual(1, len(found_requiring))
178 self.assertEqual(requiring, found_requiring[0])
179
180 def test_interface_charm_with_errors(self):
181 # Charms with errors are not returned by interface().
182 providing = Charm(factory.makeCharm(
183 self.db, provides={'foo': {'interface': 'httpX'}})[1])
184 Charm(factory.makeCharm(
185 self.db, requires={'bar': {'interface': 'httpX'}},
186 charm_error=True)[1])
187 request = self.getRequest()
188 request.matchdict = {'interface': 'httpX'}
189 response = interface(request)
190 self.assertEqual('httpX', response['interface'])
191 found_providing = response['providers']
192 self.assertEqual(1, len(found_providing))
193 self.assertEqual(providing, found_providing[0])
194 found_requiring = response['requirers']
195 self.assertEqual(0, len(found_requiring))
196167
197 def test_config(self):168 def test_config(self):
198 ignore, charm = factory.makeCharm(
199 self.db, name='foo', owner='bar', series='precise',
200 promulgated=True)
201 request = self.getRequest()169 request = self.getRequest()
202 request.matchdict = {'charm': 'foo', 'series': 'precise'}170 request.matchdict = {'charm': 'foo', 'series': 'precise'}
203 response = config(request)171 with self.assertRaises(HTTPMovedPermanently) as e:
204 expected = {"charm": Charm(charm), "onload": "prettyPrint()"}172 config(request)
205 self.assertEqual(expected, response)173 self.assertIn('/foo/precise#configuration', e.exception.location)
206174
207 def test_personal_config(self):175 def test_personal_config(self):
208 ignore, charm = factory.makeCharm(
209 self.db, name='foo', owner='bar', series='precise',
210 promulgated=False)
211 request = self.getRequest()176 request = self.getRequest()
212 request.matchdict = {177 request.matchdict = {
213 'charm': 'foo',178 'charm': 'foo',
214 'series': 'precise',179 'series': 'precise',
215 'owner': 'bar'180 'owner': 'bar'
216 }181 }
217 response = personal_config(request)182 with self.assertRaises(HTTPMovedPermanently) as e:
218 expected = {"charm": Charm(charm), "onload": "prettyPrint()"}183 personal_config(request)
219 self.assertEqual(expected, response)184 self.assertIn('/bar/foo/precise#configuration', e.exception.location)
220185
221 def make_charm_with_files(self, promulgated):186 def make_charm_with_files(self, promulgated):
222 ignore, charm = factory.makeCharm(187 ignore, charm = factory.makeCharm(
@@ -232,23 +197,17 @@
232 return charm197 return charm
233198
234 def test_hook(self):199 def test_hook(self):
235 charm = Charm(self.make_charm_with_files(promulgated=True))
236 request = self.getRequest()200 request = self.getRequest()
237 request.matchdict = {201 request.matchdict = {
238 'charm': 'sample_charm',202 'charm': 'sample_charm',
239 'series': 'precise',203 'series': 'precise',
240 'hook': 'install',204 'hook': 'install',
241 }205 }
242 response = hook(request)206 with self.assertRaises(HTTPMovedPermanently) as e:
243 self.assertEqual('Not Set.', response['project'])207 hook(request)
244 self.assertEqual('install', response['hook'])208 self.assertIn('/sample_charm/precise', e.exception.location)
245 self.assertTrue(response['hook_raw'].startswith(
246 '#!/bin/bash\nset -eux\n\n# This PPA is no longer required.'))
247 self.assertEqual(charm, response['charm'])
248 self.assertEqual('prettyPrint()', response['onload'])
249209
250 def test_personal_hook(self):210 def test_personal_hook(self):
251 charm = Charm(self.make_charm_with_files(promulgated=False))
252 request = self.getRequest()211 request = self.getRequest()
253 request.matchdict = {212 request.matchdict = {
254 'charm': 'sample_charm',213 'charm': 'sample_charm',
@@ -256,17 +215,11 @@
256 'hook': 'install',215 'hook': 'install',
257 'owner': 'bar',216 'owner': 'bar',
258 }217 }
259 response = personal_hook(request)218 with self.assertRaises(HTTPMovedPermanently) as e:
260 self.assertEqual('Not Set.', response['project'])219 personal_hook(request)
261 self.assertEqual('install', response['hook'])220 self.assertIn('/bar/sample_charm/precise', e.exception.location)
262 self.assertTrue(response['hook_raw'].startswith(
263 '#!/bin/bash\nset -eux\n\n# This PPA is no longer required.'))
264 self.assertEqual(charm, response['charm'])
265 self.assertEqual('prettyPrint()', response['onload'])
266221
267 def test_distro_charm(self):222 def test_distro_charm(self):
268 self.enable_routes()
269 self.make_charm_with_files(promulgated=True)
270 request = self.getRequest()223 request = self.getRequest()
271 request.matchdict = {224 request.matchdict = {
272 'charm': 'sample_charm',225 'charm': 'sample_charm',
@@ -377,10 +330,6 @@
377330
378 def test_charm_collection_with_missing_data(self):331 def test_charm_collection_with_missing_data(self):
379 """Charms with missing data are rendered."""332 """Charms with missing data are rendered."""
380 one_id, one = factory.makeCharm(self.db, promulgated=True)
381 two_id, two = factory.makeCharm(self.db, promulgated=True)
382 del two['summary']
383 self.db.charms.save(two)
384 response = self.app.get('/charms/precise', status=301)333 response = self.app.get('/charms/precise', status=301)
385 self.assertIn('/q/precise', response.body)334 self.assertIn('/q/precise', response.body)
386335
@@ -388,8 +337,6 @@
388 # The route /~owner/series/charm-1 finds charms using owner,337 # The route /~owner/series/charm-1 finds charms using owner,
389 # series, charm name, and revision. The deploy instruction338 # series, charm name, and revision. The deploy instruction
390 # does not include the revision.339 # does not include the revision.
391 ignore, charm = factory.makeCharm(
392 self.db, owner='owner', series='series', name='charm', files={})
393 response = self.app.get('/~owner/series/charm-1', status=301)340 response = self.app.get('/~owner/series/charm-1', status=301)
394 self.assertIn('/u/owner/charm/series/1', response.body)341 self.assertIn('/u/owner/charm/series/1', response.body)
395342
@@ -397,17 +344,12 @@
397 # /~owner/series/charm-name-1 route find the charm.344 # /~owner/series/charm-name-1 route find the charm.
398 # This is a corner-case where the revision and charm name are345 # This is a corner-case where the revision and charm name are
399 # ambigous because they are munged.346 # ambigous because they are munged.
400 ignore, charm = factory.makeCharm(
401 self.db, owner='owner', series='series', name='charm-name',
402 files={})
403 response = self.app.get('/~owner/series/charm-name-1', status=301)347 response = self.app.get('/~owner/series/charm-name-1', status=301)
404 self.assertIn('/u/owner/charm-name/series/1', response.body)348 self.assertIn('/u/owner/charm-name/series/1', response.body)
405349
406 def test_route_personal_charm_with_head_revision(self):350 def test_route_personal_charm_with_head_revision(self):
407 # the /~owner/series/charm-name-HEAD route finds the charm.351 # the /~owner/series/charm-name-HEAD route finds the charm.
408 # The juju-gui apache rewrite versionless charm urls to help the GUI.352 # The juju-gui apache rewrite versionless charm urls to help the GUI.
409 ignore, charm = factory.makeCharm(
410 self.db, owner='owner', series='series', name='charm', files={})
411 response = self.app.get('/~owner/series/charm-HEAD', status=301)353 response = self.app.get('/~owner/series/charm-HEAD', status=301)
412 self.assertIn('/u/owner/charm/series', response.body)354 self.assertIn('/u/owner/charm/series', response.body)
413 self.assertNotIn('HEAD', response.body)355 self.assertNotIn('HEAD', response.body)
@@ -416,8 +358,6 @@
416 # The route /~owner/series/charm route finds the charm using owner358 # The route /~owner/series/charm route finds the charm using owner
417 # series, and charm name. Revision is ignored. The deploy instruction359 # series, and charm name. Revision is ignored. The deploy instruction
418 # matches the route.360 # matches the route.
419 ignore, charm = factory.makeCharm(
420 self.db, owner='owner', series='series', name='charm', files={})
421 response = self.app.get('/~owner/series/charm', status=301)361 response = self.app.get('/~owner/series/charm', status=301)
422 self.assertIn('/u/owner/charm/series', response.body)362 self.assertIn('/u/owner/charm/series', response.body)
423363
@@ -443,8 +383,6 @@
443 # The route /series/charm-1 route finds promulgated charms using383 # The route /series/charm-1 route finds promulgated charms using
444 # The series, charm name and version. The deploy instruction does not384 # The series, charm name and version. The deploy instruction does not
445 # include the version.385 # include the version.
446 factory.makeCharm(
447 self.db, promulgated=True, series='series', name='charm', files={})
448 response = self.app.get('/series/charm-1', status=301)386 response = self.app.get('/series/charm-1', status=301)
449 self.assertIn('/charm/series/1', response.body)387 self.assertIn('/charm/series/1', response.body)
450388
@@ -452,8 +390,6 @@
452 # The route /series/charm-HEAD finds promulgated charms using390 # The route /series/charm-HEAD finds promulgated charms using
453 # series, charm name, and head revision. The revision is not included391 # series, charm name, and head revision. The revision is not included
454 # in the deploy instruction.392 # in the deploy instruction.
455 ignore, charm = factory.makeCharm(
456 self.db, promulgated=True, series='series', name='charm', files={})
457 response = self.app.get('/series/charm-HEAD', status=301)393 response = self.app.get('/series/charm-HEAD', status=301)
458 self.assertNotIn('HEAD', response.body)394 self.assertNotIn('HEAD', response.body)
459 self.assertIn('/charm/series', response.body)395 self.assertIn('/charm/series', response.body)
@@ -461,8 +397,6 @@
461 def test_route_promulgated_charm_without_revision(self):397 def test_route_promulgated_charm_without_revision(self):
462 # The route /series/charm finds the promulgated charms using just398 # The route /series/charm finds the promulgated charms using just
463 # the series and charm name. The deploy instruction matches the route.399 # the series and charm name. The deploy instruction matches the route.
464 factory.makeCharm(
465 self.db, promulgated=True, series='series', name='charm', files={})
466 self.app.get('/series/charm', status=301)400 self.app.get('/series/charm', status=301)
467401
468 def test_charm_short_url_route(self):402 def test_charm_short_url_route(self):

Subscribers

People subscribed via source and target branches

to all changes: