Merge lp:~jacekn/charm-helpers/charm-helpers into lp:charm-helpers

Proposed by Jacek Nykis
Status: Merged
Merged at revision: 70
Proposed branch: lp:~jacekn/charm-helpers/charm-helpers
Merge into: lp:charm-helpers
Diff against target: 253 lines (+189/-2)
5 files modified
charmhelpers/fetch/__init__.py (+16/-0)
charmhelpers/fetch/bzrurl.py (+44/-0)
tests/core/test_host.py (+44/-0)
tests/fetch/test_bzrurl.py (+80/-0)
tests/fetch/test_fetch.py (+5/-2)
To merge this branch: bzr merge lp:~jacekn/charm-helpers/charm-helpers
Reviewer Review Type Date Requested Status
Charm Helper Maintainers Pending
Review via email: mp+181245@code.launchpad.net

Description of the change

Added apt_purge function and tests

To post a comment you must log in.
71. By Jacek Nykis

Added BzrUrlFetchHandler class and tests

Revision history for this message
Jacek Nykis (jacekn) wrote :

Now the proposal also includes new BzrUrlFetchHandler class and small bugfix in fetch/__init__.py

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'charmhelpers/fetch/__init__.py'
--- charmhelpers/fetch/__init__.py 2013-08-07 23:14:14 +0000
+++ charmhelpers/fetch/__init__.py 2013-08-21 11:46:14 +0000
@@ -65,6 +65,20 @@
65 subprocess.call(cmd)65 subprocess.call(cmd)
6666
6767
68def apt_purge(packages, fatal=False):
69 """Purge one or more packages"""
70 cmd = ['apt-get', '-y', 'purge']
71 if isinstance(packages, basestring):
72 cmd.append(packages)
73 else:
74 cmd.extend(packages)
75 log("Purging {}".format(packages))
76 if fatal:
77 subprocess.check_call(cmd)
78 else:
79 subprocess.call(cmd)
80
81
68def add_source(source, key=None):82def add_source(source, key=None):
69 if ((source.startswith('ppa:') or83 if ((source.startswith('ppa:') or
70 source.startswith('http:'))):84 source.startswith('http:'))):
@@ -120,6 +134,7 @@
120# least- to most-specific URL matching.134# least- to most-specific URL matching.
121FETCH_HANDLERS = (135FETCH_HANDLERS = (
122 'charmhelpers.fetch.archiveurl.ArchiveUrlFetchHandler',136 'charmhelpers.fetch.archiveurl.ArchiveUrlFetchHandler',
137 'charmhelpers.fetch.bzrurl.BzrUrlFetchHandler',
123)138)
124139
125140
@@ -139,6 +154,7 @@
139 # We ONLY check for True here because can_handle may return a string154 # We ONLY check for True here because can_handle may return a string
140 # explaining why it can't handle a given source.155 # explaining why it can't handle a given source.
141 handlers = [h for h in plugins() if h.can_handle(source) is True]156 handlers = [h for h in plugins() if h.can_handle(source) is True]
157 installed_to = None
142 for handler in handlers:158 for handler in handlers:
143 try:159 try:
144 installed_to = handler.install(source)160 installed_to = handler.install(source)
145161
=== added file 'charmhelpers/fetch/bzrurl.py'
--- charmhelpers/fetch/bzrurl.py 1970-01-01 00:00:00 +0000
+++ charmhelpers/fetch/bzrurl.py 2013-08-21 11:46:14 +0000
@@ -0,0 +1,44 @@
1import os
2from bzrlib.branch import Branch
3from charmhelpers.fetch import (
4 BaseFetchHandler,
5 UnhandledSource
6)
7from charmhelpers.core.host import mkdir
8
9
10class BzrUrlFetchHandler(BaseFetchHandler):
11 """Handler for bazaar branches via generic and lp URLs"""
12 def can_handle(self, source):
13 url_parts = self.parse_url(source)
14 if url_parts.scheme not in ('bzr+ssh', 'lp'):
15 return False
16 else:
17 return True
18
19 def branch(self, source, dest):
20 url_parts = self.parse_url(source)
21 # If we use lp:branchname scheme we need to load plugins
22 if not self.can_handle(source):
23 raise UnhandledSource("Cannot handle {}".format(source))
24 if url_parts.scheme == "lp":
25 from bzrlib.plugin import load_plugins
26 load_plugins()
27 try:
28 remote_branch = Branch.open(source)
29 remote_branch.bzrdir.sprout(dest).open_branch()
30 except Exception as e:
31 raise e
32
33 def install(self, source):
34 url_parts = self.parse_url(source)
35 branch_name = url_parts.path.strip("/").split("/")[-1]
36 dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched", branch_name)
37 if not os.path.exists(dest_dir):
38 mkdir(dest_dir, perms=0755)
39 try:
40 self.branch(source, dest_dir)
41 except OSError as e:
42 raise UnhandledSource(e.strerror)
43 return dest_dir
44
045
=== modified file 'tests/core/test_host.py'
--- tests/core/test_host.py 2013-08-07 23:14:14 +0000
+++ tests/core/test_host.py 2013-08-21 11:46:14 +0000
@@ -447,6 +447,50 @@
447 check_call.assert_called_with(['apt-get', '-y', '--foo', '--bar',447 check_call.assert_called_with(['apt-get', '-y', '--foo', '--bar',
448 'install', 'foo', 'bar'])448 'install', 'foo', 'bar'])
449449
450
451 @patch('subprocess.check_call')
452 @patch.object(host, 'log')
453 def test_purges_apt_packages_as_string_fatal(self, log, mock_call):
454 packages = 'irrelevant names'
455 mock_call.side_effect = OSError('fail')
456
457 mock_call.assertRaises(OSError, fetch.apt_purge, packages, fatal=True )
458 log.assert_called()
459
460
461 @patch('subprocess.check_call')
462 @patch.object(host, 'log')
463 def test_purges_apt_packages_fatal(self, log, mock_call):
464 packages = ['irrelevant', 'names']
465 mock_call.side_effect = OSError('fail')
466
467 mock_call.assertRaises(OSError, fetch.apt_purge, packages, fatal=True )
468 log.assert_called()
469
470
471 @patch('subprocess.call')
472 @patch.object(host, 'log')
473 def test_purges_apt_packages_as_string_nofatal(self, log, mock_call):
474 packages = 'foo bar'
475
476 fetch.apt_purge(packages)
477
478 log.assert_called()
479 mock_call.assert_called_with(['apt-get', '-y', 'purge', 'foo bar'])
480
481
482 @patch('subprocess.call')
483 @patch.object(host, 'log')
484 def test_purges_apt_packages_nofatal(self, log, mock_call):
485 packages = ['foo', 'bar']
486
487 fetch.apt_purge(packages)
488
489 log.assert_called()
490 mock_call.assert_called_with(['apt-get', '-y', 'purge', 'foo',
491 'bar'])
492
493
450 @patch('subprocess.check_call')494 @patch('subprocess.check_call')
451 def test_apt_update_fatal(self, check_call):495 def test_apt_update_fatal(self, check_call):
452 fetch.apt_update(fatal=True)496 fetch.apt_update(fatal=True)
453497
=== added file 'tests/fetch/test_bzrurl.py'
--- tests/fetch/test_bzrurl.py 1970-01-01 00:00:00 +0000
+++ tests/fetch/test_bzrurl.py 2013-08-21 11:46:14 +0000
@@ -0,0 +1,80 @@
1import os
2from testtools import TestCase
3from urlparse import urlparse
4from mock import (
5 MagicMock,
6 patch,
7)
8from charmhelpers.fetch import (
9 bzrurl,
10 UnhandledSource,
11)
12
13
14class BzrUrlFetchHandlerTest(TestCase):
15
16 def setUp(self):
17 super(BzrUrlFetchHandlerTest, self).setUp()
18 self.valid_urls = (
19 "bzr+ssh://example.com/branch-name",
20 "bzr+ssh://example.com/branch-name/",
21 "lp:lp-branch-name",
22 "lp:example/lp-branch-name",
23 )
24 self.invalid_urls = (
25 "http://example.com/foo.tar.gz",
26 "http://example.com/foo.tgz",
27 "http://example.com/foo.tar.bz2",
28 "http://example.com/foo.tbz2",
29 "http://example.com/foo.zip",
30 "http://example.com/foo.zip?bar=baz&x=y#whee",
31 "ftp://example.com/foo.tar.gz",
32 "https://example.com/foo.tgz",
33 "file://example.com/foo.tar.bz2",
34 "git://example.com/foo.tar.gz",
35 "http://example.com/foo",
36 "http://example.com/foobar=baz&x=y#tar.gz",
37 "http://example.com/foobar?h=baz.zip",
38 "abc:example",
39 "file//example.com/foo.tar.bz2",
40 "garbage",
41 )
42 self.fh = bzrurl.BzrUrlFetchHandler()
43
44
45 def test_handles_bzr_urls(self):
46 for url in self.valid_urls:
47 result = self.fh.can_handle(url)
48 self.assertEqual(result, True, url)
49 for url in self.invalid_urls:
50 result = self.fh.can_handle(url)
51 self.assertNotEqual(result, True, url)
52
53
54 @patch('bzrlib.branch.Branch.open')
55 def test_branch(self, _open):
56 dest_path = "/destination/path"
57 for url in self.valid_urls:
58 self.fh.remote_branch = MagicMock()
59 self.fh.load_plugins = MagicMock()
60 self.fh.branch(url, dest_path)
61
62 _open.assert_called_with(url)
63
64 for url in self.invalid_urls:
65 with patch.dict('os.environ', {'CHARM_DIR': 'foo'}):
66 self.assertRaises(UnhandledSource, self.fh.branch, url, dest_path)
67
68
69 @patch('charmhelpers.fetch.bzrurl.mkdir')
70 def test_installs(self, _mkdir):
71 self.fh.branch = MagicMock()
72
73 for url in self.valid_urls:
74 branch_name = urlparse(url).path.strip("/").split("/")[-1]
75 dest = os.path.join('foo', 'fetched', os.path.basename(branch_name))
76 with patch.dict('os.environ', {'CHARM_DIR': 'foo'}):
77 where = self.fh.install(url)
78 self.assertEqual(where, dest)
79 _mkdir.assert_called_with(where, perms=0755)
80
081
=== modified file 'tests/fetch/test_fetch.py'
--- tests/fetch/test_fetch.py 2013-08-07 23:14:14 +0000
+++ tests/fetch/test_fetch.py 2013-08-21 11:46:14 +0000
@@ -183,14 +183,17 @@
183 "ftp://example.com/foo.tar.gz",183 "ftp://example.com/foo.tar.gz",
184 "https://example.com/foo.tgz",184 "https://example.com/foo.tgz",
185 "file://example.com/foo.tar.bz2",185 "file://example.com/foo.tar.bz2",
186 "bzr+ssh://example.com/branch-name",
187 "bzr+ssh://example.com/branch-name/",
188 "lp:branch-name",
189 "lp:example/branch-name",
186 )190 )
187 self.invalid_urls = (191 self.invalid_urls = (
188 "git://example.com/foo.tar.gz",192 "git://example.com/foo.tar.gz",
189 "http://example.com/foo",193 "http://example.com/foo",
190 "http://example.com/foobar=baz&x=y#tar.gz",194 "http://example.com/foobar=baz&x=y#tar.gz",
191 "http://example.com/foobar?h=baz.zip",195 "http://example.com/foobar?h=baz.zip",
192 "bzr+ssh://example.com/foo.tar.gz",196 "abc:example",
193 "lp:example/foo.tgz",
194 "file//example.com/foo.tar.bz2",197 "file//example.com/foo.tar.bz2",
195 "garbage",198 "garbage",
196 )199 )

Subscribers

People subscribed via source and target branches