Merge lp:~gmb/maas-test/fix-up-proxy-config-dir-for-tests into lp:maas-test

Proposed by Graham Binns
Status: Merged
Merged at revision: 78
Proposed branch: lp:~gmb/maas-test/fix-up-proxy-config-dir-for-tests
Merge into: lp:maas-test
Diff against target: 321 lines (+50/-42)
6 files modified
maastest/cases.py (+2/-1)
maastest/kvmfixture.py (+9/-2)
maastest/proxyfixture.py (+10/-9)
maastest/tests/test_kvmfixture.py (+3/-8)
maastest/tests/test_proxyfixture.py (+24/-22)
packages.txt (+2/-0)
To merge this branch: bzr merge lp:~gmb/maas-test/fix-up-proxy-config-dir-for-tests
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+196918@code.launchpad.net

Description of the change

This branch makes the config_dir of LocalProxyFixture, and the ssh_key_dir of KVMFixture configurable. It also adds a command-line option, --config-dir, which sets both of the above (there's an argument for having ssh_key_dir separate, I suppose; I'm happy to do that if it's a better fit).

To post a comment you must log in.
77. By Graham Binns

Fixed a typo.

78. By Graham Binns

Removed TODO that was TODONE.

Revision history for this message
Gavin Panella (allenap) wrote :

Looks good, but I'm concerned about punting everything to the user.

[1]

+    # maas-test config
+    parser.add_argument(
+        '--config-dir', type=text_type,
+        default="~/.maas-test",
+        help="The directory in which to store maas-test config and cache "
+        "files. Defaults to %(default)s")

I think we should use the xdg stuff I mentioned to rvb yesterday, and
not have yet another configuration option. Or is there a compelling
use-case for allowing this? This feels like getting the user to choose
because we can't make a decision.

review: Needs Information
Revision history for this message
Julian Edwards (julian-edwards) wrote :

On Wednesday 27 Nov 2013 16:28:29 you wrote:
> Review: Needs Information
>
> Looks good, but I'm concerned about punting everything to the user.
>
>
> [1]
>
> + # maas-test config
> + parser.add_argument(
> + '--config-dir', type=text_type,
> + default="~/.maas-test",
> + help="The directory in which to store maas-test config and cache "
> + "files. Defaults to %(default)s")
>
> I think we should use the xdg stuff I mentioned to rvb yesterday, and
> not have yet another configuration option. Or is there a compelling
> use-case for allowing this? This feels like getting the user to choose
> because we can't make a decision.

+1 to removing config where sane and and possible.

Revision history for this message
Graham Binns (gmb) wrote :

On 27 November 2013 22:51, Julian Edwards <email address hidden> wrote:
>> I think we should use the xdg stuff I mentioned to rvb yesterday, and
>> not have yet another configuration option. Or is there a compelling
>> use-case for allowing this? This feels like getting the user to choose
>> because we can't make a decision.

I saw that whizz past in a merge proposal and promptly forgot about
it. That makes perfect sense to me.

Revision history for this message
Julian Edwards (julian-edwards) wrote :

On Thursday 28 Nov 2013 07:21:34 you wrote:
> On 27 November 2013 22:51, Julian Edwards <email address hidden>
wrote:
> >> I think we should use the xdg stuff I mentioned to rvb yesterday, and
> >> not have yet another configuration option. Or is there a compelling
> >> use-case for allowing this? This feels like getting the user to choose
> >> because we can't make a decision.
>
> I saw that whizz past in a merge proposal and promptly forgot about
> it. That makes perfect sense to me.

For the record, I didn't say that, Gavin did :)

Revision history for this message
Graham Binns (gmb) wrote :

On 28 November 2013 07:24, Julian Edwards <email address hidden> wrote:
> For the record, I didn't say that, Gavin did :)

Yeah, trimming fail.

79. By Graham Binns

Removed config-dir option stuff; we'll use xdg instead.

80. By Graham Binns

XDG conversion.

81. By Graham Binns

Merged trunk.

82. By Graham Binns

Added dependencies.

83. By Graham Binns

Trimmed some lint.

84. By Graham Binns

Removed a TODO.

Revision history for this message
Gavin Panella (allenap) wrote :

Tip top. One more small thing:

[2]

-            os.path.expanduser('~'), '.maas-test', 'vm_ssh_id_rsa')
+            BaseDirectory.save_config_path('.maas-test'), 'vm_ssh_id_rsa')

No need for the leading . on .maas-test.

This appears elsewhere too.

Also, fwiw, any number of components can passed to save_config_path(),
for example:

            BaseDirectory.save_config_path('maas-test', 'vm-ssh')

would create a directory at $XDG_CONFIG_HOME/maas-test/vm-ssh.

review: Approve
Revision history for this message
Graham Binns (gmb) wrote :

On 28 November 2013 10:03, Gavin Panella <email address hidden> wrote:
> Review: Approve
>
> Tip top. One more small thing:
>
>
> [2]
>
> - os.path.expanduser('~'), '.maas-test', 'vm_ssh_id_rsa')
> + BaseDirectory.save_config_path('.maas-test'), 'vm_ssh_id_rsa')
>
> No need for the leading . on .maas-test.
>
> This appears elsewhere too.

On it.

> Also, fwiw, any number of components can passed to save_config_path(),
> for example:
>
> BaseDirectory.save_config_path('maas-test', 'vm-ssh')
>
> would create a directory at $XDG_CONFIG_HOME/maas-test/vm-ssh.

Ah, but we don't want to create a directory there (I've improved the
code so that's more obvious). vm_ssh_id_rsa is the name of the
keyfile, so we need to make sure the directory is there and then
create the path to the file from it. As I said, I've improved the
clarity.

85. By Graham Binns

Fixed an assortment of wonderful things.

86. By Graham Binns

Removed unused imports.

Revision history for this message
Gavin Panella (allenap) wrote :

> Ah, but we don't want to create a directory there (I've improved the
> code so that's more obvious).

I did understand that - your code was clear - I was just pointing it out
for future reference.

Revision history for this message
Graham Binns (gmb) wrote :

On 28 November 2013 14:25, Gavin Panella <email address hidden> wrote:
> I did understand that - your code was clear - I was just pointing it out
> for future reference.

Okay, cool. Thanks for the clarification.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'maastest/cases.py'
2--- maastest/cases.py 2013-11-27 17:22:21 +0000
3+++ maastest/cases.py 2013-11-28 14:16:14 +0000
4@@ -129,11 +129,12 @@
5 "URL: http://%s/MAAS/\n"
6 "Username: %s\n"
7 "Password: %s\n"
8- "SSH login: ssh -i ~/.maas-test/vm_ssh_id_rsa %s\n"
9+ "SSH login: ssh -i %s %s\n"
10 % (
11 self.machine.ip_address(),
12 self.maas.admin_user,
13 self.maas.admin_password,
14+ self.machine.ssh_private_key_file,
15 self.machine.identity(),
16 ))
17
18
19=== modified file 'maastest/kvmfixture.py'
20--- maastest/kvmfixture.py 2013-11-27 13:36:27 +0000
21+++ maastest/kvmfixture.py 2013-11-28 14:16:14 +0000
22@@ -34,6 +34,7 @@
23 import netaddr
24 from six import text_type
25 from testtools.content import text_content
26+from xdg import BaseDirectory
27
28 # Maximum wait for the virtual machine to complete its cloud-init
29 # initialization. It can take quite a while, because it performs an
30@@ -67,7 +68,7 @@
31 """
32 def __init__(self, series, architecture, proxy_url,
33 direct_interface=None, direct_network=None, name=None,
34- archive=None):
35+ archive=None, ssh_key_dir=None):
36 """Initialise a KVM-based Virtual Machine fixture.
37
38 The VM's network is configured like this:
39@@ -103,6 +104,10 @@
40 :param archive: An optional repository name. If provided, the
41 repository will be added onto the VM.
42 :type archive: string
43+ :param ssh_key_dir: The directory in which to store the SSH keys
44+ for connecting to this KVM instance. If None, this defaults
45+ to the default XDG config directory.
46+ :type ssh_key_dir: string.
47 """
48 super(KVMFixture, self).__init__()
49 self.command_count = itertools.count(1)
50@@ -124,8 +129,10 @@
51 if name is None:
52 name = text_type(uuid1())
53 self.name = name
54+ if ssh_key_dir is None:
55+ ssh_key_dir = BaseDirectory.save_config_path('maas-test')
56 self.ssh_private_key_file = os.path.join(
57- os.path.expanduser('~'), '.maas-test', 'vm_ssh_id_rsa')
58+ ssh_key_dir, 'vm_ssh_id_rsa')
59 self.running = False
60
61 def setUp(self):
62
63=== modified file 'maastest/proxyfixture.py'
64--- maastest/proxyfixture.py 2013-11-27 13:36:27 +0000
65+++ maastest/proxyfixture.py 2013-11-28 14:16:14 +0000
66@@ -23,10 +23,9 @@
67 from maastest import utils
68 from netaddr import IPNetwork
69 import netifaces
70+from xdg import BaseDirectory
71
72-# TODO: '.maas-test' shouln't be harcoded like that, it should
73-# be a parameter passed to LocalProxyFixture().
74-DISK_CACHE_ROOT = '~/.maas-test/proxy_cache/'
75+DISK_CACHE_ROOT = '%(config_dir)s/proxy_cache/'
76
77 PROXY_CONFIG_ITEMS = {
78 'daemonise': 'true',
79@@ -59,7 +58,7 @@
80
81 #TODO: port should be determined at runtime from the set of
82 # available ports rather than being an arbitrary one as it is here.
83- def __init__(self, port=42676):
84+ def __init__(self, config_dir=None, port=42676):
85 """Create a `LocalProxyFixture` object.
86
87 :param url: The URL of the proxy to use. If None, LocalProxyFixture
88@@ -68,13 +67,15 @@
89 :param port: The port on which to start a local caching proxy.
90 If URL is specified, this parameter is ignored.
91 :type port: int
92+ :param config_dir: The directory in which to put the proxy's
93+ config, pid file and cache.
94+ :type config_dir: string
95 """
96 super(LocalProxyFixture, self).__init__()
97 self.port = port
98- # TODO: '.maas-test' shouln't be harcoded like that, it should
99- # be a parameter passed to LocalProxyFixture().
100- self.config_dir = os.path.join(
101- os.path.expanduser('~'), '.maas-test')
102+ if config_dir is None:
103+ config_dir = BaseDirectory.save_config_path('maas-test')
104+ self.config_dir = config_dir
105 self.pid_file = os.path.join(self.config_dir, 'proxy.pid')
106 self._network_address = None
107
108@@ -132,7 +133,7 @@
109 logging.info("Done starting proxy.")
110
111 def create_cache_root(self):
112- cache_root = os.path.expanduser(DISK_CACHE_ROOT)
113+ cache_root = DISK_CACHE_ROOT % {'config_dir': self.config_dir}
114 try:
115 os.makedirs(cache_root)
116 except OSError as error:
117
118=== modified file 'maastest/tests/test_kvmfixture.py'
119--- maastest/tests/test_kvmfixture.py 2013-11-27 17:44:58 +0000
120+++ maastest/tests/test_kvmfixture.py 2013-11-28 14:16:14 +0000
121@@ -13,8 +13,6 @@
122 __all__ = []
123
124 import itertools
125-import os
126-import os.path
127 import random
128 from random import randint
129 import textwrap
130@@ -49,9 +47,7 @@
131 # KVMFixture.generate_ssh_key() generates an ssh key in ~/.maas-test,
132 # creating that directory if necessary. Set up a fake home directory
133 # so it can do what it needs to.
134- home_dir = self.useFixture(fixtures.TempDir()).path
135- self.patch(
136- os.path, 'expanduser', mock.MagicMock(return_value=home_dir))
137+ self.home_dir = self.useFixture(fixtures.TempDir()).path
138
139 def patch_run_command(self, return_value=0, stdout=b'', stderr=b''):
140 """Patch out `kvmfixture` calls to `run_command`.
141@@ -84,7 +80,7 @@
142 series, architecture, name=name,
143 direct_interface=direct_interface,
144 direct_network=direct_network, archive=archive,
145- proxy_url=proxy_url)
146+ proxy_url=proxy_url, ssh_key_dir=self.home_dir)
147 # Hack to get fixture.addDetail to work without actually calling
148 # fixture.setUp().
149 fixture._details = {}
150@@ -288,7 +284,6 @@
151 self.logger.output.strip().split("\n"))
152
153 def test_generate_ssh_key_sets_up_temporary_key_pair(self):
154- home_dir = os.path.expanduser('~')
155 fixture = self.make_KVMFixture()
156 fixtures.Fixture.setUp(fixture)
157
158@@ -297,7 +292,7 @@
159 self.assertThat(fixture.ssh_private_key_file, FileExists())
160 self.assertThat(fixture.get_ssh_public_key_file(), FileExists())
161 self.assertThat(
162- fixture.ssh_private_key_file, StartsWith(home_dir + '/'))
163+ fixture.ssh_private_key_file, StartsWith(self.home_dir + '/'))
164
165 self.assertThat(
166 fixture.ssh_private_key_file,
167
168=== modified file 'maastest/tests/test_proxyfixture.py'
169--- maastest/tests/test_proxyfixture.py 2013-11-26 22:51:09 +0000
170+++ maastest/tests/test_proxyfixture.py 2013-11-28 14:16:14 +0000
171@@ -39,24 +39,23 @@
172 'netmask': '255.255.255.0',
173 }]}
174 self.patch(netifaces, 'ifaddresses', mock_ifaddresses)
175+ self.temp_dir = self.useFixture(TempDir()).path
176
177 def get_random_port_number(self):
178 return random.randint(1, 65535)
179
180 def test_init_sets_properties(self):
181 port = self.get_random_port_number()
182- proxy_fixture = LocalProxyFixture(port=port)
183- expected_config_path = os.path.join(
184- os.path.expanduser('~'), '.maas-test')
185+ proxy_fixture = LocalProxyFixture(port=port, config_dir=self.temp_dir)
186 self.assertEqual(port, proxy_fixture.port)
187- self.assertEqual(expected_config_path, proxy_fixture.config_dir)
188+ self.assertEqual(self.temp_dir, proxy_fixture.config_dir)
189 self.assertEqual(
190- os.path.join(expected_config_path, 'proxy.pid'),
191+ os.path.join(self.temp_dir, 'proxy.pid'),
192 proxy_fixture.pid_file)
193
194 def test_get_url_returns_proxy_url(self):
195 port = self.get_random_port_number()
196- proxy_fixture = LocalProxyFixture(port=port)
197+ proxy_fixture = LocalProxyFixture(config_dir=self.temp_dir, port=port)
198 self.assertEqual(
199 "http://192.168.0.1:%s" % port,
200 proxy_fixture.get_url())
201@@ -65,8 +64,9 @@
202 self.patch(LocalProxyFixture, 'create_cache_root', mock.MagicMock())
203 self.patch(LocalProxyFixture, 'start_proxy', mock.MagicMock())
204
205- random_port = self.get_random_port_number()
206- with LocalProxyFixture(port=random_port) as fixture:
207+ port = self.get_random_port_number()
208+ config_dir = self.temp_dir
209+ with LocalProxyFixture(config_dir=config_dir, port=port) as fixture:
210 pass
211
212 self.assertEqual(
213@@ -79,7 +79,8 @@
214 def test_start_proxy_starts_proxy(self):
215 mock_run_command = mock.MagicMock()
216 self.patch(utils, 'run_command', mock_run_command)
217- proxy_fixture = LocalProxyFixture(port=self.get_random_port_number())
218+ proxy_fixture = LocalProxyFixture(
219+ config_dir=self.temp_dir, port=self.get_random_port_number())
220
221 proxy_fixture.start_proxy()
222
223@@ -90,26 +91,27 @@
224 mock_run_command.mock_calls[-1])
225
226 def test_create_cache_root_creates_directory(self):
227- temp_dir = self.useFixture(TempDir()).path
228- test_cache_path = temp_dir + "path"
229- self.patch(proxyfixture, 'DISK_CACHE_ROOT', test_cache_path)
230- proxy_fixture = LocalProxyFixture(port=self.get_random_port_number())
231+ proxy_fixture = LocalProxyFixture(
232+ config_dir=self.temp_dir, port=self.get_random_port_number())
233
234 proxy_fixture.create_cache_root()
235-
236- self.assertThat(test_cache_path, DirExists())
237+ expected_cache_path = proxyfixture.DISK_CACHE_ROOT % {
238+ 'config_dir': self.temp_dir}
239+ self.assertThat(expected_cache_path, DirExists())
240
241 def test_create_cache_root_ignores_existing_directory(self):
242 temp_dir = self.useFixture(TempDir()).path
243 self.patch(proxyfixture, 'DISK_CACHE_ROOT', temp_dir)
244- proxy_fixture = LocalProxyFixture(port=self.get_random_port_number())
245+ proxy_fixture = LocalProxyFixture(
246+ config_dir=self.temp_dir, port=self.get_random_port_number())
247
248 proxy_fixture.create_cache_root()
249
250 self.assertThat(temp_dir, DirExists())
251
252 def test_get_network_address(self):
253- proxy_fixture = LocalProxyFixture(port=self.get_random_port_number())
254+ proxy_fixture = LocalProxyFixture(
255+ config_dir=self.temp_dir, port=self.get_random_port_number())
256 proxy_adddress = proxy_fixture._get_network_address()
257 self.assertEqual('192.168.0.1', proxy_adddress.ip.format())
258 self.assertEqual(24, proxy_adddress.prefixlen)
259@@ -120,7 +122,7 @@
260 mock_read_file = mock.MagicMock()
261 mock_read_file.return_value = bytes(self.getUniqueInteger())
262 self.patch(utils, 'read_file', mock_read_file)
263- proxy_fixture = LocalProxyFixture()
264+ proxy_fixture = LocalProxyFixture(config_dir=self.temp_dir)
265 proxy_fixture.kill_running_proxy()
266 self.assertEqual(
267 mock.call(['kill', mock_read_file.return_value], check_call=True),
268@@ -132,7 +134,7 @@
269 mock_read_file = mock.MagicMock()
270 mock_read_file.side_effect = Exception(self.getUniqueString())
271 self.patch(utils, 'read_file', mock_read_file)
272- proxy_fixture = LocalProxyFixture()
273+ proxy_fixture = LocalProxyFixture(config_dir=self.temp_dir)
274 proxy_fixture.kill_running_proxy()
275 mock_log_error.assert_has_calls([
276 mock.call("Unable to kill proxy:"),
277@@ -147,7 +149,7 @@
278 mock_read_file = mock.MagicMock()
279 mock_read_file.return_value = bytes(self.getUniqueInteger())
280 self.patch(utils, 'read_file', mock_read_file)
281- proxy_fixture = LocalProxyFixture()
282+ proxy_fixture = LocalProxyFixture(config_dir=self.temp_dir)
283 proxy_fixture.kill_running_proxy()
284 mock_log_error.assert_has_calls([
285 mock.call("Unable to kill proxy:"),
286@@ -162,7 +164,7 @@
287 mock_kill_running_proxy = mock.MagicMock()
288
289 port = self.get_random_port_number()
290- proxy_fixture = LocalProxyFixture(port)
291+ proxy_fixture = LocalProxyFixture(config_dir=self.temp_dir, port=port)
292 self.patch(
293 proxy_fixture, 'kill_running_proxy', mock_kill_running_proxy)
294
295@@ -174,5 +176,5 @@
296 mock_exists = mock.MagicMock()
297 mock_exists.return_value = True
298 self.patch(os.path, 'exists', mock_exists)
299- proxy_fixture = LocalProxyFixture()
300+ proxy_fixture = LocalProxyFixture(config_dir=self.temp_dir)
301 self.assertRaises(Exception, proxy_fixture.setUp)
302
303=== modified file 'packages.txt'
304--- packages.txt 2013-11-26 13:10:43 +0000
305+++ packages.txt 2013-11-28 14:16:14 +0000
306@@ -11,6 +11,7 @@
307 python-testresources
308 python-testtools
309 python-virtualenv
310+python-xdg
311 python3-fixtures
312 python3-lxml
313 python3-mock
314@@ -18,6 +19,7 @@
315 python3-six
316 python3-testresources
317 python3-testtools
318+python3-xdg
319 qemu-kvm
320 uvtool
321 uvtool-libvirt

Subscribers

People subscribed via source and target branches