Skip to content

cli: add --system param to allow validating system user-data on a machine#575

Merged
OddBloke merged 4 commits into
canonical:masterfrom
blackboxsw:schema-system
Nov 18, 2020
Merged

cli: add --system param to allow validating system user-data on a machine#575
OddBloke merged 4 commits into
canonical:masterfrom
blackboxsw:schema-system

Conversation

@blackboxsw
Copy link
Copy Markdown
Collaborator

@blackboxsw blackboxsw commented Sep 15, 2020

Proposed Commit Message

cli: add --system param schema to allow validating system user-data

Allow root user to validate the userdata provided to the launched a machine using:
cloud-init devel schema --system

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 --system

Checklist:

  • My code follows the process laid out in the documentation
  • I have updated or added any unit tests accordingly
  • I have updated or added any documentation accordingly: NOTE: separating auto-generated documentation for all CLI commands to a separate PR

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')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't there be associated doc updates with adding a new argument to UI?

Comment thread doc/rtd/topics/faq.rst
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:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the doc update but it seemed an edit to an existing doc and didn't seem clear to me.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Collaborator

@OddBloke OddBloke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Chad, this is a nice little UX improvement. A couple of inline comments.

Comment thread cloudinit/config/schema.py Outdated
Comment thread cloudinit/config/schema.py Outdated
SCHEMA_EXAMPLES_HEADER = '\n**Examples**::\n\n'
SCHEMA_EXAMPLES_SPACER_TEMPLATE = '\n # --- Example{0} ---'

SYSTEM_USERDATA_FILE = "/var/lib/cloud/instance/user-data.txt"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should really be using a Paths object rather than hardcoding a path.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mitechie @OddBloke OOPS while the code no longer relies on this static var, I had forgotten to remove it.
Done.

@OddBloke OddBloke self-assigned this Sep 17, 2020
@github-actions github-actions Bot added the stale-pr Pull request is stale; will be auto-closed soon label Oct 8, 2020
@mitechie mitechie removed the stale-pr Pull request is stale; will be auto-closed soon label Oct 12, 2020
@canonical canonical deleted a comment from github-actions Bot Oct 12, 2020
@github-actions
Copy link
Copy Markdown

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.)

@github-actions github-actions Bot added the stale-pr Pull request is stale; will be auto-closed soon label Oct 27, 2020
@blackboxsw blackboxsw removed the stale-pr Pull request is stale; will be auto-closed soon label Nov 4, 2020
@blackboxsw
Copy link
Copy Markdown
Collaborator Author

@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).

@blackboxsw blackboxsw force-pushed the schema-system branch 2 times, most recently from 20aebc0 to 2c1eb9d Compare November 5, 2020 14:48
@blackboxsw
Copy link
Copy Markdown
Collaborator Author

@OddBloke @mitechie separated doc changes into a followup PR as discussed in standup yesterday

Copy link
Copy Markdown
Contributor

@mitechie mitechie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With a +1 to Dan's comment on the file path at the start of the PR.

Copy link
Copy Markdown
Collaborator

@OddBloke OddBloke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 👍).

Comment thread cloudinit/config/schema.py Outdated
Comment thread cloudinit/config/schema.py Outdated
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.
Copy link
Copy Markdown
Collaborator

@OddBloke OddBloke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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]))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@OddBloke OddBloke merged commit f680114 into canonical:master Nov 18, 2020
TheRealFalcon added a commit to TheRealFalcon/cloud-init that referenced this pull request Dec 15, 2020
Ensure `cloud-init devel schema` indicates valid userdata is valid
and invalid userdata is invalid.
TheRealFalcon added a commit to TheRealFalcon/cloud-init that referenced this pull request Dec 15, 2020
This currently covers functionality added in canonical#575
@TheRealFalcon TheRealFalcon mentioned this pull request Dec 15, 2020
3 tasks
TheRealFalcon added a commit that referenced this pull request Dec 15, 2020
This currently covers functionality added in #575
This was referenced May 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants