cli: add --system param to allow validating system user-data on a machine#575
Conversation
| parser.add_argument('-c', '--config-file', | ||
| help='Path of the cloud-config yaml file to validate') | ||
| parser.add_argument('--system', action='store_true', default=False, | ||
| help='Validate the system cloud-config userdata') |
There was a problem hiding this comment.
shouldn't there be associated doc updates with adding a new argument to UI?
| Another option is to run the following on an instance when debugging: | ||
| Another option is to run the following on an instance to debug userdata | ||
| provided to the system: | ||
|
|
There was a problem hiding this comment.
This is the doc update but it seemed an edit to an existing doc and didn't seem clear to me.
There was a problem hiding this comment.
Yeah, devel commands, and general CLI documentation, isn't great. In the devel case I had originally left it fairly undocumented as these devel commands will likely change form or break compatibility before we decide to make them fully fledged top-level (non-devel) subcommands of cloud-init. But, now that we are referencing subcommand switches in docs in other places. it would be helpful to have a more full rendering of cli docs for this devel subcommands. I ultimately think we should autogeerate docs from the argparse configs so that we can keep that up to date any time the cli is changed. I think sphinx-argparse extension could do this for us, but I'd like to leave that to a separate PR as it'll potentially involve re-organizing the top-level CLI docs docs. As I think we could try to modify how the CLI docs in general are exposed and documented.
There was a problem hiding this comment.
That said, I did just push a commit that renders cmdline devel schema to this branch. I think we can build on this if an acceptable format for all CLI commands.
OddBloke
left a comment
There was a problem hiding this comment.
Thanks Chad, this is a nice little UX improvement. A couple of inline comments.
| SCHEMA_EXAMPLES_HEADER = '\n**Examples**::\n\n' | ||
| SCHEMA_EXAMPLES_SPACER_TEMPLATE = '\n # --- Example{0} ---' | ||
|
|
||
| SYSTEM_USERDATA_FILE = "/var/lib/cloud/instance/user-data.txt" |
There was a problem hiding this comment.
This should really be using a Paths object rather than hardcoding a path.
|
Hello! Thank you for this proposed change to cloud-init. This pull request is now marked as stale as it has not seen any activity in 14 days. If no activity occurs within the next 7 days, this pull request will automatically close. If you are waiting for code review and you are seeing this message, apologies! Please reply, tagging mitechie, and he will ensure that someone takes a look soon. (If the pull request is closed, please do feel free to reopen it if you wish to continue working on it.) |
314ca95 to
10b4174
Compare
|
@OddBloke @mitechie I've updated this branch and added auto-generated docs for review for only the devel subcommand using sphinx-argparse. If this documentation approach is palatable. I can add a followup PR to auto-gen docs for our entire CLI as a followup PR. (I could separate that from this PR too). |
20aebc0 to
2c1eb9d
Compare
mitechie
left a comment
There was a problem hiding this comment.
With a +1 to Dan's comment on the file path at the start of the PR.
2c1eb9d to
55245a3
Compare
OddBloke
left a comment
There was a problem hiding this comment.
Thanks Chad! Overall this looks good, I have one inline comment that I think needs addressing before this can land (and another one which you can ignore because it's a nit 👍).
Platform userdata could be configured to live in a differnt place. Use Paths object to determine that userdata_raw file path. Also add a getuid check if --system param is provided to schema because non-root users cannot access system userdata.
55245a3 to
b3d7bcd
Compare
OddBloke
left a comment
There was a problem hiding this comment.
Thanks Chad! Some nits inline, which you can fix in a follow-up if you so desire.
| @pytest.mark.parametrize("params", exclusive_combinations) | ||
| def test_main_exclusive_args(self, params, capsys): | ||
| """Main exits non-zero and error on required exclusive args.""" | ||
| params = list(itertools.chain(*[a.split() for a in params])) |
There was a problem hiding this comment.
A nit: it took me a while to grok what this was doing; I think params = " ".join(params).split() has the same effect?
In [12]: params = ('--docs all', '--config-file something')
In [13]: list(itertools.chain(*[a.split() for a in params]))
Out[13]: ['--docs', 'all', '--config-file', 'something']
In [14]: " ".join(params).split()
Out[14]: ['--docs', 'all', '--config-file', 'something']| """Main exits non-zero and error on required exclusive args.""" | ||
| params = list(itertools.chain(*[a.split() for a in params])) | ||
| with mock.patch('sys.argv', ['mycmd'] + params): | ||
| with pytest.raises(SystemExit) as context_manager: |
There was a problem hiding this comment.
A nit: the pytest docs use excinfo for these, and we follow that pattern elsewhere in the codebase:
$ a -s pytest.raises.\*as
cloudinit/tests/test_conftest.py
28: with pytest.raises(AssertionError) as excinfo:
35: with pytest.raises(AssertionError) as excinfo:
We also broadly follow the pattern in UA client and pycloudlib, though there is more divergence there.
| ) | ||
| assert expected == err | ||
|
|
||
| def test_main_missing_args(self, capsys): |
There was a problem hiding this comment.
A nit (unless I'm wrong, then not even that): you could potentially fold this into the above definition by making the parameters list(exclusive_combinations) + [()].
| ["--system", "--docs all", "--config-file something"], 2 | ||
| ) | ||
|
|
||
| @pytest.mark.parametrize("params", exclusive_combinations) |
There was a problem hiding this comment.
Nit: a not-particularly-important gap here is all three being specified at once.
| content = load_file(config_path, decode=False) | ||
| if config_path is None: | ||
| # Use system's raw userdata path | ||
| if os.getuid() != 0: |
There was a problem hiding this comment.
This file is always root:root-owned by default and not world-readable, so this is not even a nit: we could instead rely on the user's permissions to determine if they can use this path.
Ensure `cloud-init devel schema` indicates valid userdata is valid and invalid userdata is invalid.
This currently covers functionality added in canonical#575
This currently covers functionality added in #575
Proposed Commit Message
Test Steps
lxc launch ubuntu-daily:xenial dev-x lxc file push cloudinit/config/schema.py dev-x/usr/lib/python3/dist-packages/cloudinit/config/ lxc exec dev-x bash $ cloud-init devel schema --systemChecklist: