Skip to content

Improve usability of switch port settings #7966

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

Merged
merged 13 commits into from
May 31, 2025

Conversation

internet-diglett
Copy link
Contributor

@internet-diglett internet-diglett commented Apr 11, 2025

This PR aims to improve the usability of the switch port settings API by returning data of similar shape and content as what users provide when the create the switch port settings.

Issues resolved:

  • Before this PR, you only need one call to create a complete switch port settings object, but you have to perform several lookups to get the complete switch port configuration. We were already returning the object ids of the nested objects, so it makes a lot of sense to just return the actual object (especially since the user supplied the entire object when they configured it)
  • The HashMap<String_of_link_name, T> pattern also did not give the expected behavior in our go client generation. Changing this to a Vec<T_with_link_name_inside> matches what the user provides during creation and also resolves this behavior.
  • Some of our Vec<T> fields can be empty but must be present. In the Go client, an empty array is omitted from the json object. We needed to add a default annotation to these fields so Serde handles this situation correctly.

Related

Closes #5780

Switch port settings create params takes a hashmap of
link name -> configuration value. However, we return a struct
that has the configuration value and link name inside of a
single type. We are updating this to be the same for create params
and returned types.

This change accomplishes two things:
* The API is more consistent for users
* The generated go client doesn't seem to work properly with the
  hash map style params. This change allows us to properly create
  settings using the go client.
@internet-diglett internet-diglett changed the title wip Add missing data to switch port settings May 13, 2025
@internet-diglett internet-diglett marked this pull request as ready for review May 13, 2025 18:33
@internet-diglett internet-diglett changed the title Add missing data to switch port settings Improve useability of switch port settings May 13, 2025
@internet-diglett internet-diglett changed the title Improve useability of switch port settings Improve usability of switch port settings May 13, 2025
@@ -2824,7 +2805,7 @@ pub struct SwitchPortRouteConfig {
pub dst: oxnet::IpNet,

/// The route's gateway address.
pub gw: oxnet::IpNet,
Copy link
Contributor

Choose a reason for hiding this comment

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

why can this go from IpNet to IpAddr?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was likely never supposed to be an IpNet. The user provides an IpAddr when they create the configuration:

The DB stores singular ipv4 addresses as a full CIDR with /32, so that's probably how we ended up returning an IpNet instead of an IpAddr like what the user supplied.

@@ -2980,6 +2961,33 @@ pub struct SwitchPortAddressConfig {
pub interface_name: String,
}

/// An IP address configuration for a port settings object.
#[derive(Clone, Debug, Deserialize, JsonSchema, Serialize, PartialEq)]
pub struct SwitchPortAddressView {
Copy link
Contributor

Choose a reason for hiding this comment

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

I see this matches up with SwitchPortSettingsView, but we don't usually put View on the end of these structs we call views. In this case I think SwitchPortAddress might be ok, though it makes it sound like it's just the address. But either nothing or something more descriptive than View would be an improvement.

SwitchPortSettingsView can't be changed to SwitchPortSettings because there is already a SwitchPortSettings, and SwitchPortSettingsConfig is ridiculous. What if instead of the settings key, you took that #[serde(flatten)] identity bit and stuck it directly in SwitchPortSettingsView? Then you could rename the struct SwitchPortSettings.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Giving this a try now

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It looks like the existing SwitchPortSettings struct that wraps the IdentityMetadata is what we return when we list the SwitchPortSettings resource. I'm not sure on the original motivation for this, but the complete SwitchPortSettingsView struct is quite large and requires a bit of work to populate, so maybe we didn't want to do that when listing the resource.

Would SwitchPortSettingsIdentity make more sense for the wrapper struct? That would allow us to use SwitchPortSettings for the "view" struct.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. That's a naming conundrum. I don't think we distinguish the full view from the list item anywhere else, so we are inventing the convention here. *Identity feels natural because we have structs in the Rust code that are named like that, though we don't have any existing view schemas in the API ending with Identity. I think your proposal is solid: the list endpoint would return ResultsPage<SwitchPortSettingsIdentity> and the detail would be SwitchPortSettings. An alternative pair of names could be SwitchPortSettings and SwitchPortSettingsDetail. But I think I like the first one better.

Yet another option would be to return the full thing for the list as well, but you weren't kidding about it being a lot, so we probably shouldn't do that.

@ahl what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've updated these type names to SwitchPortSettings and SwitchPortSettingsIdentity.

Copy link
Contributor

Choose a reason for hiding this comment

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

Cool, I think it looks good.

Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@david-crespo
Copy link
Contributor

The hashmap to vec changes look good in the TS client. It's more intuitive this way.

image

@internet-diglett
Copy link
Contributor Author

The hashmap to vec changes look good in the TS client. It's more intuitive this way.

I'm VERY happy to hear this!

@rcgoodfellow rcgoodfellow added this to the 15 milestone May 15, 2025
@Nieuwejaar Nieuwejaar self-requested a review May 15, 2025 17:02
Copy link
Contributor

@rcgoodfellow rcgoodfellow left a comment

Choose a reason for hiding this comment

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

Thanks Levon. Just a few questions about testing at this point.

},
)]),
addresses: HashMap::new(),
links: vec![],
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you update this test to assert full round trip consistency? We're just looking at the number of ports below.

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 test should be ensuring full round trip consistency now

@@ -229,7 +227,7 @@ async fn test_port_settings_basic_crud(ctx: &ControlPlaneTestContext) {
assert_eq!(&link0.link_name, "phy0");
assert_eq!(link0.mtu, 4700);

let lldp0 = &roundtrip.link_lldp[0];
let lldp0 = link0.lldp_link_config.clone().unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to define (or derive) PartialEq for these structures to make the round trip testing more concise and less error prone?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll look into this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Looks like this test was disabled back when we didn't have mgs in the test context. I re-enabled it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like it!

@@ -0,0 +1 @@

Copy link
Contributor

Choose a reason for hiding this comment

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

Mistakenly added file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch

@internet-diglett internet-diglett merged commit 7547bfa into main May 31, 2025
17 checks passed
@internet-diglett internet-diglett deleted the return-similar-types-for-network-config branch May 31, 2025 00:00
hawkw pushed a commit that referenced this pull request Jun 2, 2025
This PR aims to improve the usability of the switch port settings API by
returning data of similar shape and content as what users provide when
the create the switch port settings.

Issues resolved:
* Before this PR, you only need one call to create a complete switch
port settings object, but you have to perform several lookups to get the
complete switch port configuration. We were already returning the object
ids of the nested objects, so it makes a lot of sense to just return the
actual object (especially since the user supplied the entire object when
they configured it)
* The `HashMap<String_of_link_name, T>` pattern also did not give the
expected behavior in our go client generation. Changing this to a
`Vec<T_with_link_name_inside>` matches what the user provides during
creation and also resolves this behavior.
* Some of our `Vec<T>` fields can be empty but must be present. In the
Go client, an empty array is omitted from the json object. We needed to
add a `default` annotation to these fields so Serde handles this
situation correctly.

## Related
- oxidecomputer/oxide.go#278
- oxidecomputer/terraform-provider-oxide#426

Closes #5780
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.

Make MGS available in nexus test suite
5 participants