-
Notifications
You must be signed in to change notification settings - Fork 51
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
Parse ip%scope
in CLI arguments
#443
Conversation
Currently, the Humility CLI accepts IP addresses as a `String`, and then attempts to parse them as an `Ipv6Addr` and scope. This is a bit unfortunate, as when argument parsing is performed by `clap`, the CLI will emit a somewhat nicer error message when parsing fails (indicating which argument the error occurred while parsing, including the invalid value, and suggesting the help text). On the other hand, when we accept the argument as a `String`, `clap` doesn't add that useful context to the error message. This branch adds a `ScopedV6Addr` newtype, consisting of an `Ipv6Addr` and a scope identifier, and adds a `FromStr` implementation for that type. Now, we can use `ScopedV6Addr` as the type of the CLI argument, and `clap` performs the parsing for us, getting us somewhat nicer error messages. Compare the error output from master: ```console $ cargo run -- --ip ::%fakeiface0 probe Finished dev [unoptimized + debuginfo] target(s) in 0.13s Running `target/debug/humility --ip '::%fakeiface0' probe` humility probe failed: Could not find interface for fakeiface0 $ cargo run -- --ip :: probe Finished dev [unoptimized + debuginfo] target(s) in 0.13s Running `target/debug/humility --ip '::' probe` humility probe failed: Missing scope id in IP (e.g. '%en0') $ cargo run -- --ip barf%eth0 probe Finished dev [unoptimized + debuginfo] target(s) in 0.13s Running `target/debug/humility --ip 'barf%eth0' probe` humility probe failed: invalid Zip archive: Invalid zip header ``` with the error output on this branch: ```console $ cargo run -- --ip :: probe Finished dev [unoptimized + debuginfo] target(s) in 0.14s Running `target/debug/humility --ip '::' probe` error: Invalid value "::" for '--ip <IP>': missing scope ID (e.g. "%en0") in IPv6 address For more information try --help $ cargo run -- --ip ::%fakeiface0 probe Finished dev [unoptimized + debuginfo] target(s) in 8.45s Running `target/debug/humility --ip '::%fakeiface0' probe` error: Invalid value "::%fakeiface0" for '--ip <IP>': Could not find interface for fakeiface0 For more information try --help $ cargo run -- --ip barf%eth0 probe Finished dev [unoptimized + debuginfo] target(s) in 12.87s Running `target/debug/humility --ip 'barf%eth0' probe` error: Invalid value "barf%eth0" for '--ip <IP>': "barf" is not a valid IPv6 address For more information try --help ``` Additionally, using the `ScopedIpv6Addr` type allows us to provide a `fmt::Display` implementation that combines the IP address and scope ID when formatting. This lets us get rid of a little bit of repeated logic for formatting an address with the delimiter, which seems kinda nice to me.
Hoo boy. I can't even explain to myself why this would happen, particularly for |
Yeah, I, uh...have no idea what's going on with that... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an improvement! The two remaining sites of manually copy-pasted scope ID parsing that I'm aware of are in cmd/rpc
and cmd/gimlet
-- if you've got the bandwidth to fix those in this PR that'd rock, though IMO it's an improvement either way. One suggestion below.
@@ -158,7 +158,7 @@ impl ExecutionContext { | |||
if let Ok(e) = env::var("HUMILITY_PROBE") { | |||
cli.probe = Some(e); | |||
} else if let Ok(e) = env::var("HUMILITY_IP") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, this is news to me -- some commands use a different env var for this, like HUMILITY_RPC_IP
. Wonder how that happened.
Humility does some manual wrangling of Clap, e.g. not using its built-in subcommand facility, so it's possible we confused it somehow or messed up an error handling path somewhere. |
Ah, I understand the zip archive failure, I think. When no archive is given, Humility still creates a So the error is, deceptively, not related to IP address parsing -- Humility has actually accepted I had to change it to |
...more generally, it looks like |
Ah, yeah, that makes sense...it's a bit unfortunate that the failure thus ends up being "the zip file is missing a header" rather than "there is no zip file at all". I could look into fixing that separately, if you like? |
Now that your |
I'm prepping a fix, unfortunately the place where the failure happens is outside Humility's normal "I have no archive but I must scream" failure path, so the reporting will be a tad shoddy, but I can get it to say
(The reason it's outside the failure path: |
Because `humility rpc` accepts a list of addresses or a `-i <INTERFACE>` (with `--listen`), we still need to use `decode_iface` directly when called with `-i`.
@cbiffle I've updated the |
Currently, the Humility CLI accepts IP addresses as a
String
, and thenattempts to parse them as an
Ipv6Addr
and scope. This is a bitunfortunate, as when argument parsing is performed by
clap
, the CLIwill emit a somewhat nicer error message when parsing fails (indicating
which argument the error occurred while parsing, including the invalid
value, and suggesting the help text). On the other hand, when we accept
the argument as a
String
,clap
doesn't add that useful context tothe error message.
This branch adds a
ScopedV6Addr
newtype, consisting of anIpv6Addr
and a scope identifier, and adds a
FromStr
implementation for thattype. Now, we can use
ScopedV6Addr
as the type of the CLI argument,and
clap
performs the parsing for us, getting us somewhat nicer errormessages. Compare the error output from master:
with the error output on this branch:
Additionally, using the
ScopedIpv6Addr
type allows us to provide afmt::Display
implementation that combines the IP address and scope IDwhen formatting. This lets us get rid of a little bit of repeated logic
for formatting an address with the delimiter, which seems kinda nice to
me.