cloud-init-dev team mailing list archive
-
cloud-init-dev team
-
Mailing list archive
-
Message #00948
[Merge] lp:~harlowja/cloud-init/cloud-init-fix-up-cli into lp:cloud-init
Joshua Harlow has proposed merging lp:~harlowja/cloud-init/cloud-init-fix-up-cli into lp:cloud-init.
Requested reviews:
cloud init development team (cloud-init-dev)
For more details, see:
https://code.launchpad.net/~harlowja/cloud-init/cloud-init-fix-up-cli/+merge/297409
--
Your team cloud init development team is requested to review the proposed merge of lp:~harlowja/cloud-init/cloud-init-fix-up-cli into lp:cloud-init.
=== removed directory 'bin'
=== added directory 'cloudinit/cmd'
=== added file 'cloudinit/cmd/__init__.py'
--- cloudinit/cmd/__init__.py 1970-01-01 00:00:00 +0000
+++ cloudinit/cmd/__init__.py 2016-06-14 21:58:15 +0000
@@ -0,0 +1,21 @@
+# vi: ts=4 expandtab
+#
+# Copyright (C) 2012 Canonical Ltd.
+# Copyright (C) 2012 Hewlett-Packard Development Company, L.P.
+# Copyright (C) 2012 Yahoo! Inc.
+#
+# Author: Scott Moser <scott.moser@xxxxxxxxxxxxx>
+# Author: Juerg Haefliger <juerg.haefliger@xxxxxx>
+# Author: Joshua Harlow <harlowja@xxxxxxxxxxxxx>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 3, as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
=== renamed file 'bin/cloud-init' => 'cloudinit/cmd/main.py'
--- bin/cloud-init 2016-05-31 21:17:39 +0000
+++ cloudinit/cmd/main.py 2016-06-14 21:58:15 +0000
@@ -25,17 +25,10 @@
import json
import os
import sys
+import tempfile
import time
-import tempfile
import traceback
-# This is more just for running from the bin folder so that
-# cloud-init binary can find the cloudinit module
-possible_topdir = os.path.normpath(os.path.join(os.path.abspath(
- sys.argv[0]), os.pardir, os.pardir))
-if os.path.exists(os.path.join(possible_topdir, "cloudinit", "__init__.py")):
- sys.path.insert(0, possible_topdir)
-
from cloudinit import patcher
patcher.patch()
@@ -46,9 +39,10 @@
from cloudinit import stages
from cloudinit import templater
from cloudinit import util
+from cloudinit import version
+
from cloudinit import reporting
from cloudinit.reporting import events
-from cloudinit import version
from cloudinit.settings import (PER_INSTANCE, PER_ALWAYS, PER_ONCE,
CLOUD_CONFIG)
@@ -188,7 +182,7 @@
LOG.debug("Closing stdin")
util.close_stdin()
(outfmt, errfmt) = util.fixup_output(init.cfg, name)
- except:
+ except Exception:
util.logexc(LOG, "Failed to setup output redirection!")
print_exc("Failed to setup output redirection!")
if args.debug:
@@ -325,7 +319,7 @@
if outfmt_orig != outfmt or errfmt_orig != errfmt:
LOG.warn("Stdout, stderr changing to (%s, %s)", outfmt, errfmt)
(outfmt, errfmt) = util.fixup_output(mods.cfg, name)
- except:
+ except Exception:
util.logexc(LOG, "Failed to re-adjust output redirection!")
logging.setupLogging(mods.cfg)
@@ -367,7 +361,7 @@
LOG.debug("Closing stdin")
util.close_stdin()
util.fixup_output(mods.cfg, name)
- except:
+ except Exception:
util.logexc(LOG, "Failed to setup output redirection!")
if args.debug:
# Reset so that all the debug handlers are closed out
@@ -430,7 +424,7 @@
LOG.debug("Closing stdin")
util.close_stdin()
util.fixup_output(mods.cfg, None)
- except:
+ except Exception:
util.logexc(LOG, "Failed to setup output redirection!")
if args.debug:
# Reset so that all the debug handlers are closed out
@@ -510,7 +504,7 @@
else:
try:
status = json.loads(util.load_file(status_path))
- except:
+ except Exception:
pass
if status is None:
@@ -569,8 +563,12 @@
return len(v1[mode]['errors'])
-def main():
- parser = argparse.ArgumentParser()
+def main(sysv_args=None):
+ if sysv_args is not None:
+ parser = argparse.ArgumentParser(prog=sysv_args[0])
+ sysv_args = sysv_args[1:]
+ else:
+ parser = argparse.ArgumentParser()
# Top level args
parser.add_argument('--version', '-v', action='version',
@@ -646,7 +644,7 @@
' pass to this module'))
parser_single.set_defaults(action=('single', main_single))
- args = parser.parse_args()
+ args = parser.parse_args(args=sysv_args)
# Setup basic logging to start (until reinitialized)
# iff in debug mode...
@@ -656,9 +654,8 @@
# Setup signal handlers before running
signal_handler.attach_handlers()
- if not hasattr(args, 'action'):
- parser.error('too few arguments')
(name, functor) = args.action
+
if name in ("modules", "init"):
functor = status_wrapper
@@ -683,7 +680,3 @@
return util.log_time(
logfunc=LOG.debug, msg="cloud-init mode '%s'" % name,
get_uptime=True, func=functor, args=(name, args))
-
-
-if __name__ == '__main__':
- sys.exit(main())
=== modified file 'setup.py'
--- setup.py 2016-06-07 01:42:29 +0000
+++ setup.py 2016-06-14 21:58:15 +0000
@@ -204,10 +204,14 @@
author_email='scott.moser@xxxxxxxxxxxxx',
url='http://launchpad.net/cloud-init/',
packages=setuptools.find_packages(exclude=['tests']),
- scripts=['bin/cloud-init',
- 'tools/cloud-init-per'],
+ scripts=['tools/cloud-init-per'],
license='GPLv3',
data_files=data_files,
install_requires=requirements,
cmdclass=cmdclass,
+ entry_points={
+ 'console_scripts': [
+ 'cloud-init = cloudinit.cmd.main:main'
+ ],
+ }
)
=== modified file 'tests/unittests/test_cli.py'
--- tests/unittests/test_cli.py 2016-05-19 21:26:30 +0000
+++ tests/unittests/test_cli.py 2016-06-14 21:58:15 +0000
@@ -6,7 +6,7 @@
from . import helpers as test_helpers
mock = test_helpers.mock
-BIN_CLOUDINIT = "bin/cloud-init"
+from cloudinit.cmd import main as cli
class TestCLI(test_helpers.FilesystemMockingTestCase):
@@ -15,35 +15,22 @@
super(TestCLI, self).setUp()
self.stderr = six.StringIO()
self.patchStdoutAndStderr(stderr=self.stderr)
- self.sys_exit = mock.MagicMock()
- self.patched_funcs.enter_context(
- mock.patch.object(sys, 'exit', self.sys_exit))
- def _call_main(self):
- self.patched_funcs.enter_context(
- mock.patch.object(sys, 'argv', ['cloud-init']))
- cli = imp.load_module(
- 'cli', open(BIN_CLOUDINIT), '', ('', 'r', imp.PY_SOURCE))
+ def _call_main(self, sysv_args=None):
+ if not sysv_args:
+ sysv_args = ['cloud-init']
try:
- return cli.main()
- except Exception:
- pass
+ return cli.main(sysv_args=sysv_args)
+ except SystemExit as e:
+ return e.code
- @test_helpers.skipIf(not os.path.isfile(BIN_CLOUDINIT), "no bin/cloudinit")
def test_no_arguments_shows_usage(self):
- self._call_main()
+ exit_code = self._call_main()
self.assertIn('usage: cloud-init', self.stderr.getvalue())
-
- @test_helpers.skipIf(not os.path.isfile(BIN_CLOUDINIT), "no bin/cloudinit")
- def test_no_arguments_exits_2(self):
- exit_code = self._call_main()
- if self.sys_exit.call_count:
- self.assertEqual(mock.call(2), self.sys_exit.call_args)
- else:
- self.assertEqual(2, exit_code)
-
- @test_helpers.skipIf(not os.path.isfile(BIN_CLOUDINIT), "no bin/cloudinit")
+ self.assertEqual(2, exit_code)
+
def test_no_arguments_shows_error_message(self):
- self._call_main()
+ exit_code = self._call_main()
self.assertIn('cloud-init: error: too few arguments',
self.stderr.getvalue())
+ self.assertEqual(2, exit_code)
Follow ups