Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mgr_module.py: make keyword style argument passing explicit #36910

Closed
wants to merge 3 commits into from

Conversation

jan--f
Copy link
Contributor

@jan--f jan--f commented Aug 31, 2020

This PR changes the recent addition to CLICommand to support kwargs style passing. With this a module author has to explicitly mark arguments that can be passed with a keyword.

Checklist

  • References tracker ticket
  • Updates documentation if necessary
  • Includes tests for new functionality or reproducer for bug

Show available Jenkins commands
  • jenkins retest this please
  • jenkins test classic perf
  • jenkins test crimson perf
  • jenkins test signed
  • jenkins test make check
  • jenkins test make check arm64
  • jenkins test submodules
  • jenkins test dashboard
  • jenkins test api
  • jenkins test docs
  • jenkins render docs
  • jenkins test ceph-volume all
  • jenkins test ceph-volume tox

@sebastian-philipp
Copy link
Contributor

jenkins render docs

@ceph-jenkins
Copy link
Collaborator

Doc render available at http://docs.ceph.com/ceph-prs/36910/

@sebastian-philipp
Copy link
Contributor

interesting. those calls are missing from https://docs.ceph.com/ceph-prs/36910/api/mon_command_api/

@sebastian-philipp
Copy link
Contributor

sebastian-philipp commented Aug 31, 2020

what I still don't quite understand is:

fs snap-schedule status --path=<mypath> --subvol=<subvol>

already works. But kw=true is not expose to the ceph binary, how is this supposed to work?

I mean, I can still say:

fs snap-schedule status <mypath> <subvol>

@jan--f
Copy link
Contributor Author

jan--f commented Aug 31, 2020

interesting. those calls are missing from https://docs.ceph.com/ceph-prs/36910/api/mon_command_api/

Looks like commands that are setup via the CLICommand decorator (or its variants) are just not extracted. E.g all dashboard dashboard ac-user-* commands are also missing.

@jan--f
Copy link
Contributor Author

jan--f commented Aug 31, 2020

what I still don't quite understand is:

fs snap-schedule status --path=<mypath> --subvol=<subvol>

Unfortunaltey things can't look quite like this. The command would be

fs snap-schedule status path=<mypath> subvol=<subvol>

already works. But kw=true is not expose to the ceph binary, how is this supposed to work?
An argument path=/foo is passed as a string.

I mean, I can still say:

fs snap-schedule status <mypath> <subvol>

Right, that will still work. I'd be up for adding a kw=always variant if one wants to force passing as kwarg, but I don't really see a use case for this.

@jan--f
Copy link
Contributor Author

jan--f commented Sep 1, 2020

Hmm seems like ceph_argparse.py needs a change as well. Looking into it.

Jan Fajerski added 3 commits September 1, 2020 16:44
Instead of assuming a kwarg when a '=' is encountered, this commit
changes the CLICommand decorator to require an explicit 'kw=true'
specification in a command definition to add the option to parse it
as a kwarg.
Arguments marked with kw=true can either be passed kwarg style
(arg_name=value) or as a positional argument. Once a kwarg style
argument was seen, the following ones must not be passed as positionals.

Signed-off-by: Jan Fajerski <jfajerski@suse.com>
When setting up the module commands we can warn if the developer
defined a positional after a keyword argument.

Signed-off-by: Jan Fajerski <jfajerski@suse.com>
Signed-off-by: Jan Fajerski <jfajerski@suse.com>
Copy link
Member

@jecluis jecluis left a comment

Choose a reason for hiding this comment

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

I think the idea makes sense, especially given that the support already exists but the current implementation seems broken due to assuming any = will be handled as the separator for a key/value pair.

I do have a few comments on the approach though.

@@ -299,6 +300,12 @@ def _parse_args(self):
arg_d[k] = v
else:
self.args_dict[v] = arg_d
if k == 'kw' and v == 'true':
Copy link
Member

Choose a reason for hiding this comment

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

I find the kw keyword a bit too weird, especially since we're then dropping "kwarg" terms bellow. I find going with something a bit more descriptive (especially since we're using this on the CLI descriptor) would be ideal. Something like "requires_args" or "with_map_args". More to type, but I'm sure with a bit of creativity we can find a better keyword ;)

Copy link
Member

Choose a reason for hiding this comment

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

maybe k/v argument? kv_arg?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

kw stands for keyword, borrowed from pythons keywords arguments. kwarg might be better and should be familiar to python developers.

Copy link
Member

Choose a reason for hiding this comment

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

but if we are exposing kw as a thing to the user (like we do on returning EINVAL later in the patch), this is no longer just for developer consumption and, I'd say, a more relatable term might be better.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah fair point.

else:
if kwargs_switch:
# we saw a kwarg earlier and now a positional
logging.warn('Found positional argument after kwarg')
Copy link
Member

Choose a reason for hiding this comment

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

is there a reason why we'd warn about positional arguments after a k/v pair was found? I don't see a particular technical difficulty in handling them, especially since we know which arguments are expected to be k/v pairs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here (while setting up the command and argument structures) I only warn since the kw=true currently enables optional passing as a kwarg. The user can also pass the arguments as positional arguments.

if not kwargs_switch and isinstance(cmd_dict[a], str) and '=' in cmd_dict[a]:
# We consider this a kwarg. Set the switch so that all
# future args are parsed as kwargs too.
mgr.log.debug('Seen a kwarg, assuming all following args are kw style')
Copy link
Member

Choose a reason for hiding this comment

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

I asked this above, but is there a technical reason why we can't handle positional arguments after k/v pairs?

We're not even allowing spaces between the key portion, the equal sign, and the value portion, so we're not actually dealing with 3 arguments in the CLI, just the one. Why not allowing other arguments to come after?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The reasoning is that once we have seen a kwarg and it is followed by a positional, we don't know what that positional argument is (since it is identified by its position in the arg list). This is consistent with python behaviour.

Copy link
Member

Choose a reason for hiding this comment

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

I see the point, but aren't these being pre-handled by argparse so that they arrive as a dictionary as is? IIRC, and I may be conflating argparse and command parsing in the mgr module, arguments are identified by their dictionary k/v pairs rather than list positional arguments; no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Once we're in mgr module land, yes, we have the dict. But the dict is filled by position on the command line iiuc. But I need to look closer into ceph_argparse, the kwargs parsing should probably happen there.

@jecluis
Copy link
Member

jecluis commented Sep 1, 2020

Okay, crazy idea: why not implementing this as a new type for argparse, such that you can have a map type?

@jan--f
Copy link
Contributor Author

jan--f commented Sep 2, 2020

Okay, crazy idea: why not implementing this as a new type for argparse, such that you can have a map type?

The argparse types are value types. We want to use those for positionals as well as kwarg style. I realise that in order to use the kwarg style they argument currently has to be a CephString, this is insufficient.
As mentioned above, I'll look into pushing the this code into ceph_argparse in order to play nicer with the types. It's also where that code should live.

@jan--f jan--f added the DNM label Sep 2, 2020
@stale
Copy link

stale bot commented Nov 1, 2020

This pull request has been automatically marked as stale because it has not had any activity for 60 days. It will be closed if no further activity occurs for another 30 days.
If you are a maintainer or core committer, please follow-up on this pull request to identify what steps should be taken by the author to move this proposed change forward.
If you are the author of this pull request, thank you for your proposed contribution. If you believe this change is still appropriate, please ensure that any feedback has been addressed and ask for a code review.

@stale stale bot added the stale label Nov 1, 2020
@github-actions
Copy link

This pull request can no longer be automatically merged: a rebase is needed and changes have to be manually resolved

@sebastian-philipp
Copy link
Contributor

relates to https://tracker.ceph.com/issues/50954

@ceph-jenkins
Copy link
Collaborator

Doc render available at https://ceph--36910.org.readthedocs.build/en/36910/

@leseb
Copy link
Member

leseb commented Jun 7, 2021

superseded by #41509?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants