Merge lp:~allenap/maas/remove-old-atomic-delete-and-write into lp:~maas-committers/maas/trunk

Proposed by Gavin Panella
Status: Merged
Approved by: Gavin Panella
Approved revision: no longer in the source branch.
Merged at revision: 5851
Proposed branch: lp:~allenap/maas/remove-old-atomic-delete-and-write
Merge into: lp:~maas-committers/maas/trunk
Prerequisite: lp:~allenap/maas/use-atomic-delete-and-write-scripts
Diff against target: 297 lines (+4/-233)
3 files modified
src/provisioningserver/__main__.py (+1/-7)
src/provisioningserver/utils/script.py (+0/-65)
src/provisioningserver/utils/tests/test_script.py (+3/-161)
To merge this branch: bzr merge lp:~allenap/maas/remove-old-atomic-delete-and-write
Reviewer Review Type Date Requested Status
Blake Rouse (community) Approve
Review via email: mp+320770@code.launchpad.net

Commit message

Remove the old AtomicDeleteScript and AtomicWriteScript.

To post a comment you must log in.
Revision history for this message
Blake Rouse (blake-rouse) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/provisioningserver/__main__.py'
2--- src/provisioningserver/__main__.py 2016-09-29 18:40:44 +0000
3+++ src/provisioningserver/__main__.py 2017-03-23 08:48:30 +0000
4@@ -14,16 +14,10 @@
5 import provisioningserver.utils.avahi
6 import provisioningserver.utils.dhcp
7 import provisioningserver.utils.scan_network
8-from provisioningserver.utils.script import (
9- AtomicDeleteScript,
10- AtomicWriteScript,
11- MainScript,
12-)
13+from provisioningserver.utils.script import MainScript
14
15
16 script_commands = {
17- 'atomic-write': AtomicWriteScript,
18- 'atomic-delete': AtomicDeleteScript,
19 'check-for-shared-secret': security.CheckForSharedSecretScript,
20 'config': provisioningserver.cluster_config_command,
21 'install-shared-secret': security.InstallSharedSecretScript,
22
23=== modified file 'src/provisioningserver/utils/script.py'
24--- src/provisioningserver/utils/script.py 2016-08-09 00:14:06 +0000
25+++ src/provisioningserver/utils/script.py 2017-03-23 08:48:30 +0000
26@@ -5,7 +5,6 @@
27
28 __all__ = [
29 'ActionScript',
30- 'AtomicWriteScript',
31 'MainScript',
32 ]
33
34@@ -18,11 +17,6 @@
35 from subprocess import CalledProcessError
36 import sys
37
38-from provisioningserver.utils.fs import (
39- atomic_delete,
40- atomic_write,
41-)
42-
43
44 class ActionScriptError(ValueError):
45 """Exception which should be printed to `stderr` if raised."""
46@@ -109,62 +103,3 @@
47
48 class MainScript(ActionScript):
49 """An `ActionScript` denoting the main script in an application."""
50-
51-
52-class AtomicWriteScript:
53- """Wrap the atomic_write function turning it into an ActionScript.
54-
55- To use:
56- >>> main = MainScript(atomic_write.__doc__)
57- >>> main.register("myscriptname", AtomicWriteScript)
58- >>> main()
59- """
60-
61- @staticmethod
62- def add_arguments(parser):
63- """Initialise options for writing files atomically.
64-
65- :param parser: An instance of :class:`ArgumentParser`.
66- """
67- parser.add_argument(
68- "--no-overwrite", action="store_true", required=False,
69- default=False, help="Don't overwrite file if it exists")
70- parser.add_argument(
71- "--filename", action="store", required=True, help=(
72- "The name of the file in which to store contents of stdin"))
73- parser.add_argument(
74- "--mode", action="store", required=False, default="0600", help=(
75- "They permissions to set on the file. If not set "
76- "will be r/w only to owner"))
77-
78- @staticmethod
79- def run(args):
80- """Take content from stdin and write it atomically to a file."""
81- atomic_write(
82- sys.stdin.buffer.read(), args.filename, mode=int(args.mode, 8),
83- overwrite=(not args.no_overwrite))
84-
85-
86-class AtomicDeleteScript:
87- """Wrap the atomic_delete function turning it into an ActionScript.
88-
89- To use:
90- >>> main = MainScript(atomic_delete.__doc__)
91- >>> main.register("myscriptname", AtomicDeleteScript)
92- >>> main()
93- """
94-
95- @staticmethod
96- def add_arguments(parser):
97- """Initialise options for deleting files atomically.
98-
99- :param parser: An instance of :class:`ArgumentParser`.
100- """
101- parser.add_argument(
102- "--filename", action="store", required=True, help=(
103- "The name of the file to delete."))
104-
105- @staticmethod
106- def run(args):
107- """Delete the file atomically."""
108- atomic_delete(args.filename)
109
110=== modified file 'src/provisioningserver/utils/tests/test_script.py'
111--- src/provisioningserver/utils/tests/test_script.py 2016-08-09 00:14:06 +0000
112+++ src/provisioningserver/utils/tests/test_script.py 2017-03-23 08:48:30 +0000
113@@ -9,39 +9,19 @@
114 ArgumentParser,
115 Namespace,
116 )
117-import io
118-import os
119 from random import randint
120-import stat
121-from subprocess import (
122- CalledProcessError,
123- PIPE,
124- Popen,
125-)
126-import sys
127+from subprocess import CalledProcessError
128 import types
129
130-from maastesting import bindir
131 from maastesting.factory import factory
132 from maastesting.fixtures import CaptureStandardIO
133-from maastesting.matchers import (
134- FileContains,
135- MockCalledOnceWith,
136-)
137 from maastesting.testcase import MAASTestCase
138-import provisioningserver.utils
139 from provisioningserver.utils import script as script_module
140 from provisioningserver.utils.script import (
141 ActionScript,
142 ActionScriptError,
143- AtomicDeleteScript,
144- AtomicWriteScript,
145-)
146-from provisioningserver.utils.shell import select_c_utf8_locale
147-from testtools.matchers import (
148- Equals,
149- MatchesStructure,
150-)
151+)
152+from testtools.matchers import Equals
153 from testtools.testcase import ExpectedException
154
155
156@@ -170,141 +150,3 @@
157 self.patch(script_module.ActionScript, 'setup')
158 script(['smash'])
159 self.assertThat(self.stdio.getError(), Equals("Towel.\n"))
160-
161-
162-class TestAtomicWriteScript(MAASTestCase):
163-
164- def setUp(self):
165- super(TestAtomicWriteScript, self).setUp()
166- # ArgumentParser sometimes likes to print to stdout/err.
167- self.stdio = self.useFixture(CaptureStandardIO())
168-
169- def get_parser(self):
170- parser = ArgumentParser()
171- AtomicWriteScript.add_arguments(parser)
172- return parser
173-
174- def get_and_run_mocked_script(self, content, filename, *args):
175- self.stdio.addInput(content)
176- parser = self.get_parser()
177- parsed_args = parser.parse_args(*args)
178- mocked_atomic_write = self.patch(
179- provisioningserver.utils.script, 'atomic_write')
180- AtomicWriteScript.run(parsed_args)
181- return mocked_atomic_write
182-
183- def test_arg_setup(self):
184- parser = self.get_parser()
185- filename = factory.make_string()
186- args = parser.parse_args((
187- '--no-overwrite',
188- '--filename', filename,
189- '--mode', "111"))
190- self.assertThat(
191- args, MatchesStructure.byEquality(
192- no_overwrite=True,
193- filename=filename,
194- mode="111"))
195-
196- def test_filename_arg_required(self):
197- parser = self.get_parser()
198- self.assertRaises(SystemExit, parser.parse_args, ('--no-overwrite',))
199-
200- def test_no_overwrite_defaults_to_false(self):
201- parser = self.get_parser()
202- filename = factory.make_string()
203- args = parser.parse_args(('--filename', filename))
204- self.assertFalse(args.no_overwrite)
205-
206- def test_script_executable(self):
207- content = factory.make_string()
208- script = [os.path.join(bindir, "maas-rack"), 'atomic-write']
209- target_file = self.make_file()
210- script.extend(('--filename', target_file, '--mode', '615'))
211- cmd = Popen(script, stdin=PIPE, env=select_c_utf8_locale())
212- cmd.communicate(content.encode("ascii"))
213- self.assertThat(target_file, FileContains(content, encoding="ascii"))
214- self.assertEqual(0o615, stat.S_IMODE(os.stat(target_file).st_mode))
215-
216- def test_passes_overwrite_flag(self):
217- content = factory.make_string()
218- filename = factory.make_string()
219- mocked_atomic_write = self.get_and_run_mocked_script(
220- content, filename,
221- ('--filename', filename, '--no-overwrite'))
222-
223- self.assertThat(
224- mocked_atomic_write,
225- MockCalledOnceWith(
226- content.encode("ascii"), filename,
227- mode=0o600, overwrite=False))
228-
229- def test_passes_mode_flag(self):
230- content = factory.make_string()
231- filename = factory.make_string()
232- # Mode that's unlikely to occur in the wild.
233- mode = 0o377
234- mocked_atomic_write = self.get_and_run_mocked_script(
235- content, filename,
236- ('--filename', filename, '--mode', oct(mode)))
237-
238- self.assertThat(
239- mocked_atomic_write,
240- MockCalledOnceWith(
241- content.encode("ascii"), filename, mode=mode, overwrite=True))
242-
243- def test_default_mode(self):
244- content = factory.make_string()
245- filename = factory.make_string()
246- mocked_atomic_write = self.get_and_run_mocked_script(
247- content, filename,
248- ('--filename', filename))
249-
250- self.assertThat(
251- mocked_atomic_write,
252- MockCalledOnceWith(
253- content.encode("ascii"), filename, mode=0o600, overwrite=True))
254-
255-
256-class TestAtomicDeleteScript(MAASTestCase):
257-
258- def setUp(self):
259- super(TestAtomicDeleteScript, self).setUp()
260- # Silence ArgumentParser.
261- self.patch(sys, "stdout", io.StringIO())
262- self.patch(sys, "stderr", io.StringIO())
263-
264- def get_parser(self):
265- parser = ArgumentParser()
266- AtomicDeleteScript.add_arguments(parser)
267- return parser
268-
269- def get_and_run_mocked_script(self, *args):
270- parser = self.get_parser()
271- parsed_args = parser.parse_args(*args)
272- mocked_atomic_delete = self.patch(
273- provisioningserver.utils.script, 'atomic_delete')
274- AtomicDeleteScript.run(parsed_args)
275- return mocked_atomic_delete
276-
277- def test_arg_setup(self):
278- parser = self.get_parser()
279- filename = factory.make_string()
280- args = parser.parse_args((
281- '--filename', filename))
282- self.assertThat(
283- args, MatchesStructure.byEquality(
284- filename=filename))
285-
286- def test_filename_arg_required(self):
287- parser = self.get_parser()
288- self.assertRaises(SystemExit, parser.parse_args, tuple())
289-
290- def test_calls_atomic_delete_with_filename(self):
291- filename = factory.make_string()
292- mocked_atomic_delete = self.get_and_run_mocked_script(
293- ('--filename', filename))
294-
295- self.assertThat(
296- mocked_atomic_delete,
297- MockCalledOnceWith(filename))