summaryrefslogtreecommitdiff
path: root/tests/unittests/test_cli.py
diff options
context:
space:
mode:
authorChad Smith <chad.smith@canonical.com>2018-02-02 11:11:36 -0700
committerChad Smith <chad.smith@canonical.com>2018-02-02 11:11:36 -0700
commit78013bc65030421699b5feb66bc8b7a205abfbc0 (patch)
tree2ebf7111129f4aaf8a833ba6d226d4513ed59388 /tests/unittests/test_cli.py
parent192261fe38a32edbd1f605ba25bbb6f4822a0720 (diff)
parentf7deaf15acf382d62554e2b1d70daa9a9109d542 (diff)
downloadvyos-cloud-init-78013bc65030421699b5feb66bc8b7a205abfbc0.tar.gz
vyos-cloud-init-78013bc65030421699b5feb66bc8b7a205abfbc0.zip
merge from master at 17.2-30-gf7deaf15
Diffstat (limited to 'tests/unittests/test_cli.py')
-rw-r--r--tests/unittests/test_cli.py105
1 files changed, 99 insertions, 6 deletions
diff --git a/tests/unittests/test_cli.py b/tests/unittests/test_cli.py
index fccbbd23..0c0f427a 100644
--- a/tests/unittests/test_cli.py
+++ b/tests/unittests/test_cli.py
@@ -1,16 +1,21 @@
# This file is part of cloud-init. See LICENSE file for license information.
+from collections import namedtuple
+import os
import six
+from cloudinit.cmd import main as cli
from cloudinit.tests import helpers as test_helpers
+from cloudinit.util import load_file, load_json
-from cloudinit.cmd import main as cli
mock = test_helpers.mock
class TestCLI(test_helpers.FilesystemMockingTestCase):
+ with_logs = True
+
def setUp(self):
super(TestCLI, self).setUp()
self.stderr = six.StringIO()
@@ -24,6 +29,76 @@ class TestCLI(test_helpers.FilesystemMockingTestCase):
except SystemExit as e:
return e.code
+ def test_status_wrapper_errors_on_invalid_name(self):
+ """status_wrapper will error when the name parameter is not valid.
+
+ Valid name values are only init and modules.
+ """
+ tmpd = self.tmp_dir()
+ data_d = self.tmp_path('data', tmpd)
+ link_d = self.tmp_path('link', tmpd)
+ FakeArgs = namedtuple('FakeArgs', ['action', 'local', 'mode'])
+
+ def myaction():
+ raise Exception('Should not call myaction')
+
+ myargs = FakeArgs(('doesnotmatter', myaction), False, 'bogusmode')
+ with self.assertRaises(ValueError) as cm:
+ cli.status_wrapper('init1', myargs, data_d, link_d)
+ self.assertEqual('unknown name: init1', str(cm.exception))
+ self.assertNotIn('Should not call myaction', self.logs.getvalue())
+
+ def test_status_wrapper_errors_on_invalid_modes(self):
+ """status_wrapper will error if a parameter combination is invalid."""
+ tmpd = self.tmp_dir()
+ data_d = self.tmp_path('data', tmpd)
+ link_d = self.tmp_path('link', tmpd)
+ FakeArgs = namedtuple('FakeArgs', ['action', 'local', 'mode'])
+
+ def myaction():
+ raise Exception('Should not call myaction')
+
+ myargs = FakeArgs(('modules_name', myaction), False, 'bogusmode')
+ with self.assertRaises(ValueError) as cm:
+ cli.status_wrapper('modules', myargs, data_d, link_d)
+ self.assertEqual(
+ "Invalid cloud init mode specified 'modules-bogusmode'",
+ str(cm.exception))
+ self.assertNotIn('Should not call myaction', self.logs.getvalue())
+
+ def test_status_wrapper_init_local_writes_fresh_status_info(self):
+ """When running in init-local mode, status_wrapper writes status.json.
+
+ Old status and results artifacts are also removed.
+ """
+ tmpd = self.tmp_dir()
+ data_d = self.tmp_path('data', tmpd)
+ link_d = self.tmp_path('link', tmpd)
+ status_link = self.tmp_path('status.json', link_d)
+ # Write old artifacts which will be removed or updated.
+ for _dir in data_d, link_d:
+ test_helpers.populate_dir(
+ _dir, {'status.json': 'old', 'result.json': 'old'})
+
+ FakeArgs = namedtuple('FakeArgs', ['action', 'local', 'mode'])
+
+ def myaction(name, args):
+ # Return an error to watch status capture them
+ return 'SomeDatasource', ['an error']
+
+ myargs = FakeArgs(('ignored_name', myaction), True, 'bogusmode')
+ cli.status_wrapper('init', myargs, data_d, link_d)
+ # No errors reported in status
+ status_v1 = load_json(load_file(status_link))['v1']
+ self.assertEqual(['an error'], status_v1['init-local']['errors'])
+ self.assertEqual('SomeDatasource', status_v1['datasource'])
+ self.assertFalse(
+ os.path.exists(self.tmp_path('result.json', data_d)),
+ 'unexpected result.json found')
+ self.assertFalse(
+ os.path.exists(self.tmp_path('result.json', link_d)),
+ 'unexpected result.json link found')
+
def test_no_arguments_shows_usage(self):
exit_code = self._call_main()
self.assertIn('usage: cloud-init', self.stderr.getvalue())
@@ -45,8 +120,8 @@ class TestCLI(test_helpers.FilesystemMockingTestCase):
"""All known subparsers are represented in the cloud-int help doc."""
self._call_main()
error = self.stderr.getvalue()
- expected_subcommands = ['analyze', 'init', 'modules', 'single',
- 'dhclient-hook', 'features', 'devel']
+ expected_subcommands = ['analyze', 'clean', 'devel', 'dhclient-hook',
+ 'features', 'init', 'modules', 'single']
for subcommand in expected_subcommands:
self.assertIn(subcommand, error)
@@ -76,9 +151,11 @@ class TestCLI(test_helpers.FilesystemMockingTestCase):
self.patchStdoutAndStderr(stdout=stdout)
expected_errors = [
- 'usage: cloud-init analyze', 'usage: cloud-init collect-logs',
- 'usage: cloud-init devel']
- conditional_subcommands = ['analyze', 'collect-logs', 'devel']
+ 'usage: cloud-init analyze', 'usage: cloud-init clean',
+ 'usage: cloud-init collect-logs', 'usage: cloud-init devel',
+ 'usage: cloud-init status']
+ conditional_subcommands = [
+ 'analyze', 'clean', 'collect-logs', 'devel', 'status']
# The cloud-init entrypoint calls main without passing sys_argv
for subcommand in conditional_subcommands:
with mock.patch('sys.argv', ['cloud-init', subcommand, '-h']):
@@ -106,6 +183,22 @@ class TestCLI(test_helpers.FilesystemMockingTestCase):
self._call_main(['cloud-init', 'collect-logs', '-h'])
self.assertIn('usage: cloud-init collect-log', stdout.getvalue())
+ def test_clean_subcommand_parser(self):
+ """The subcommand cloud-init clean calls the subparser."""
+ # Provide -h param to clean to avoid having to mock behavior.
+ stdout = six.StringIO()
+ self.patchStdoutAndStderr(stdout=stdout)
+ self._call_main(['cloud-init', 'clean', '-h'])
+ self.assertIn('usage: cloud-init clean', stdout.getvalue())
+
+ def test_status_subcommand_parser(self):
+ """The subcommand cloud-init status calls the subparser."""
+ # Provide -h param to clean to avoid having to mock behavior.
+ stdout = six.StringIO()
+ self.patchStdoutAndStderr(stdout=stdout)
+ self._call_main(['cloud-init', 'status', '-h'])
+ self.assertIn('usage: cloud-init status', stdout.getvalue())
+
def test_devel_subcommand_parser(self):
"""The subcommand cloud-init devel calls the correct subparser."""
self._call_main(['cloud-init', 'devel'])