Merge ~chad.smith/cloud-init:fix-cloudinit-subcommands into cloud-init:master

Proposed by Chad Smith
Status: Merged
Approved by: Scott Moser
Approved revision: 3bbe537c848f5f107d0af8d328fb85c5f5592b7e
Merged at revision: 89579a68d9f51e51b24f96b933da656afd83edfb
Proposed branch: ~chad.smith/cloud-init:fix-cloudinit-subcommands
Merge into: cloud-init:master
Diff against target: 46 lines (+19/-5)
2 files modified
cloudinit/cmd/main.py (+4/-5)
tests/unittests/test_cli.py (+15/-0)
Reviewer Review Type Date Requested Status
Scott Moser Approve
Server Team CI bot continuous-integration Approve
Review via email: mp+329493@code.launchpad.net

Description of the change

cloud-init cli: Fix command line parsing of coniditionally loaded subcommands

In an effort to save file load cost during system boot, certain
subcommands, analyze and devel, do not get loaded unless the subcommand is
specified on the commandline. Because setup.py entrypoint for cloud-init
script doesn't specify sysv_args parameter when calling the CLI's main()
we need main to read sys.argv into sysv_args so our subparser loading
continues to work.

LP: #1712676

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:3bbe537c848f5f107d0af8d328fb85c5f5592b7e
https://jenkins.ubuntu.com/server/job/cloud-init-ci/193/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    SUCCESS: MAAS Compatability Testing
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/193/rebuild

review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/cmd/main.py b/cloudinit/cmd/main.py
2index 5b46797..68563e0 100644
3--- a/cloudinit/cmd/main.py
4+++ b/cloudinit/cmd/main.py
5@@ -676,11 +676,10 @@ def main_features(name, args):
6
7
8 def main(sysv_args=None):
9- if sysv_args is not None:
10- parser = argparse.ArgumentParser(prog=sysv_args[0])
11- sysv_args = sysv_args[1:]
12- else:
13- parser = argparse.ArgumentParser()
14+ if not sysv_args:
15+ sysv_args = sys.argv
16+ parser = argparse.ArgumentParser(prog=sysv_args[0])
17+ sysv_args = sysv_args[1:]
18
19 # Top level args
20 parser.add_argument('--version', '-v', action='version',
21diff --git a/tests/unittests/test_cli.py b/tests/unittests/test_cli.py
22index 2449880..12f0185 100644
23--- a/tests/unittests/test_cli.py
24+++ b/tests/unittests/test_cli.py
25@@ -70,6 +70,21 @@ class TestCLI(test_helpers.FilesystemMockingTestCase):
26 self.assertEqual('modules', parseargs.action[0])
27 self.assertEqual('main_modules', parseargs.action[1].__name__)
28
29+ def test_conditional_subcommands_from_entry_point_sys_argv(self):
30+ """Subcommands from entry-point are properly parsed from sys.argv."""
31+ expected_errors = [
32+ 'usage: cloud-init analyze', 'usage: cloud-init devel']
33+ conditional_subcommands = ['analyze', 'devel']
34+ # The cloud-init entrypoint calls main without passing sys_argv
35+ for subcommand in conditional_subcommands:
36+ with mock.patch('sys.argv', ['cloud-init', subcommand]):
37+ try:
38+ cli.main()
39+ except SystemExit as e:
40+ self.assertEqual(2, e.code) # exit 2 on proper usage docs
41+ for error_message in expected_errors:
42+ self.assertIn(error_message, self.stderr.getvalue())
43+
44 def test_analyze_subcommand_parser(self):
45 """The subcommand cloud-init analyze calls the correct subparser."""
46 self._call_main(['cloud-init', 'analyze'])

Subscribers

People subscribed via source and target branches