-
Notifications
You must be signed in to change notification settings - Fork 18
Commands for common network operations #726
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
Conversation
cli/src/cmd_net.rs
Outdated
enum Port { | ||
Qsfp0, | ||
Qsfp1, | ||
Qsfp2, | ||
Qsfp3, | ||
Qsfp4, | ||
Qsfp5, | ||
Qsfp6, | ||
Qsfp7, | ||
Qsfp8, | ||
Qsfp9, | ||
Qsfp10, | ||
Qsfp11, | ||
Qsfp12, | ||
Qsfp13, | ||
Qsfp14, | ||
Qsfp15, | ||
Qsfp16, | ||
Qsfp17, | ||
Qsfp18, | ||
Qsfp19, | ||
Qsfp20, | ||
Qsfp21, | ||
Qsfp22, | ||
Qsfp23, | ||
Qsfp24, | ||
Qsfp25, | ||
Qsfp26, | ||
Qsfp27, | ||
Qsfp28, | ||
Qsfp29, | ||
Qsfp30, | ||
Qsfp31, | ||
} |
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.
I wonder if this is something that could live in the API? Lists like this could be difficult to maintain the same in various clients 🤔
Additionally, if our customers were to create their own clients from our API, they might find it pretty hard to know that this enum is required
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.
The network configuration API is going to be changing pretty significantly based on some work @internet-diglett is doing to eventually support things like terraform integration. A resource-based model is ultimately where we want to go. This PR is to make things reasonable for operators until that larger chunk of API work lands. It's my hope that at a CLI level, these commands will remain pretty much the same, while their internal implementation will benefit from broader API work, and things like this, which you rightfully note should be captured by the API will go away.
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.
gotcha, thanks for the clarification!
cli/src/cmd_net.rs
Outdated
let links: HashMap<String, LinkConfigCreate> = current | ||
.links | ||
.iter() | ||
.enumerate() | ||
.map(|(i, x)| { | ||
( | ||
format!("phy{}", i), | ||
LinkConfigCreate { | ||
autoneg: x.autoneg, | ||
fec: x.fec, | ||
lldp: LldpServiceConfigCreate { | ||
//TODO | ||
enabled: false, | ||
lldp_config: None, | ||
}, | ||
mtu: x.mtu, | ||
speed: x.speed, | ||
}, | ||
) | ||
}) | ||
.collect(); |
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.
same as above
61b3892
to
7f3fecb
Compare
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 "net" vs "networking" subcommand seems confusing
- I'd suggest we add some testing of these commands
- positional arguments are (I think) new to the CLI; I think we should stick with
-
and--
prefixed arguments for clarity (but if that seems cumbersome for these, let me know--recall we do have completion that is inclusive of arguments) - consider docs on subcommands and internal nodes
- I think there a few places we want to use .stream() rather than .send
cli/src/cmd_net.rs
Outdated
} | ||
|
||
#[async_trait] | ||
impl RunnableCmd for CmdNet { |
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 the only thing that needs to impl RunnableCmd
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.
All of the subcommands still need the Context
object, so I found the interface convenient to reuse. Is there a different approach you would suggest?
cli/docs/cli.json
Outdated
] | ||
}, | ||
{ | ||
"name": "net", |
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.
so we're going to have "networking" and "net" as top-level subcommands? this seems confusing.
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.
net
has been removed, and the commands have been integrated into the existing command hierarchy.
#[derive(Parser, Debug, Clone)] | ||
#[command(verbatim_doc_comment)] | ||
#[command(name = "net bgp status")] | ||
pub struct CmdBgpStatus {} |
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.
now does this differ from system networking bgp status
?
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.
The only difference is the output is formatted a bit nicer. Seems like this would fit in better as a flag to system networking bgp status
? Something like --output table
? This is likely true of several commands in this PR.
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.
ry@masaka:~$ oxide net bgp status
switch0
=======
Peer Address Local ASN Remote ASN Session State State Duration
169.254.30.1 65547 64502 Established 1h 5m 33s 942ms
169.254.10.1 65547 64500 Established 1h 5m 38s 910ms
switch1
=======
Peer Address Local ASN Remote ASN Session State State Duration
169.254.20.1 65547 64500 Established 1h 5m 38s 855ms
169.254.40.1 65547 64502 Established 1h 5m 33s 888ms
ry@masaka:~$ oxide system networking bgp status
[
{
"addr": "169.254.30.1",
"local_asn": 65547,
"remote_asn": 64502,
"state": "established",
"state_duration_millis": 3943140,
"switch": "switch0"
},
{
"addr": "169.254.10.1",
"local_asn": 65547,
"remote_asn": 64500,
"state": "established",
"state_duration_millis": 3948107,
"switch": "switch0"
},
{
"addr": "169.254.20.1",
"local_asn": 65547,
"remote_asn": 64500,
"state": "established",
"state_duration_millis": 3948072,
"switch": "switch1"
},
{
"addr": "169.254.40.1",
"local_asn": 65547,
"remote_asn": 64502,
"state": "established",
"state_duration_millis": 3943104,
"switch": "switch1"
}
]
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.
For the moment, opting to have show
commands that display information in a more human-oriented way than their status
and view
counterparts.
cli/src/cmd_net.rs
Outdated
.body(BgpAnnounceSetCreate { | ||
announcement: current, | ||
name: self.announce_set.clone(), | ||
description: self.announce_set.to_string(), //TODO? |
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.
is this the description we want?
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.
I've made this configurable
#[derive(Serialize, Deserialize, Clone, Debug)] | ||
pub struct MacAddr { | ||
a: [u8; 6], | ||
} | ||
|
||
#[derive(Serialize, Deserialize, Clone, Debug)] | ||
struct LinkStatus { | ||
address: MacAddr, | ||
enabled: bool, | ||
autoneg: bool, | ||
fec: String, | ||
link_state: String, | ||
fsm_state: String, | ||
media: String, | ||
speed: String, | ||
} | ||
|
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.
how fragile is this?
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.
Quite. The link status endpoint is experimental and opaque, passing just Object
back. We could, in theory, import types from Dendrite, which is where these types ultimately come from, but that repo is not open, so there are challenges on that front.
For testing, I've added an expectorate test for the one command that produces stable output: |
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.
great stuff!
SwitchInterfaceConfigCreate, SwitchInterfaceKind, SwitchInterfaceKind2, SwitchLocation, | ||
SwitchPort, SwitchPortConfigCreate, SwitchPortGeometry, SwitchPortGeometry2, |
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.
it's concerning to me that we've managed to have these types suffixed with 2 which indicates a name conflict, but that's a problem for another day. I should probably have some sort of lint check for that.
cli/src/cmd_net.rs
Outdated
#[derive(Parser, Debug, Clone)] | ||
#[command(verbatim_doc_comment)] | ||
#[command(name = "port")] | ||
pub struct CmdPort { | ||
#[clap(subcommand)] | ||
subcmd: PortSubCommand, | ||
} | ||
|
||
#[async_trait] | ||
impl RunnableCmd for CmdPort { | ||
async fn run(&self, ctx: &Context) -> Result<()> { | ||
match &self.subcmd { | ||
PortSubCommand::Config(cmd) => cmd.run(ctx).await, | ||
PortSubCommand::Status(cmd) => cmd.run(ctx).await, | ||
} | ||
} | ||
} | ||
|
||
#[derive(Parser, Debug, Clone)] | ||
enum PortSubCommand { | ||
/// Manage port configuration. | ||
Config(CmdPortConfig), | ||
|
||
/// Observe port status. | ||
Status(CmdPortStatus), | ||
} |
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.
can this all be deleted?
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.
yep sure can! removed
Status(CmdPortStatus), | ||
} | ||
|
||
#[derive(Parser, Debug, Clone)] |
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.
I don't claim to really understand what this does, but perhaps a short doc comment explaining very briefly the command and (probably) that the subcommands are short-hand for common operations one could perform via system networking switch-port-settings create
; if it's easy enough, I think a short doc comment on all the new commands and their subcommands would be great.
/// Prefixes to allow for the peer. | ||
#[clap(long, conflicts_with = "no_filtering")] | ||
allowed: Vec<oxnet::IpNet>, | ||
|
||
/// Do not filter. | ||
#[clap(long, conflicts_with = "allowed")] | ||
no_filtering: bool, |
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.
nice
We have a transactional API for port settings objects. The port settings object is somewhat complex. The port settings object returned by GET requests to view port settings is not exactly the same as the port settings object used to create/update port settings with PUT/POST requests. This makes it rather grueling to manage port settings.
This PR adds client-side read/modify/write routines for managing individual items within port settings such as addresses.
Also pulls in the observability stuff from #661.
An example of using these new commands is here, which demonstrates creating a new BGP connection to a cloud provider. An example of using the observability stuff pulled in from #661 is in this comment analyzing an Omicron bug.