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

wicket cli: add "inventory configured-bootstrap-sleds" #6218

Merged
merged 11 commits into from
Aug 9, 2024

Conversation

faithanalog
Copy link
Contributor

@faithanalog faithanalog commented Aug 3, 2024

This PR

My main motivation for adding: I am working on automating control plane deployment on london and madrid. Before we can start rack init, we need to know if all the sleds we are going to initialize are actually available. This information is something you can see from the rack init TUI, but there was no way to get it from the CLI.

I have added an inventory command with a configured-bootstrap-sleds subcommand, which presents exactly the same information accessible in the TUI's rack init screen.

(Note: there is no way to start rack init for the CLI yet, but I will add that in a future PR.)

In theory inventory could be expanded to provide other information.

Note, I am absolutely not attached to the command interface or data format. I only care about making this information accessible so I can use it in my scripts. Meaning, if any of this interface should be different from how I've done it in this initial PR, I will make those changes as asked.

Example Usage

artemis@jeeves ~ $ ssh londonwicket inventory configured-bootstrap-sleds
⚠ Cubby 14      BRM42220036     not_available
✔ Cubby 15      BRM42220062     fdb0:a840:2504:312::1
✔ Cubby 16      BRM42220030     fdb0:a840:2504:257::1
✔ Cubby 17      BRM44220007     fdb0:a840:2504:492::1
artemis@jeeves ~ $ ssh londonwicket -- inventory configured-bootstrap-sleds --json | jq
[
  {
    "id": {
      "slot": 14,
      "type": "sled"
    },
    "baseboard": {
      "type": "gimlet",
      "identifier": "BRM42220036",
      "model": "913-0000019",
      "revision": 6
    },
    "bootstrap_ip": "fdb0:a840:2504:212::1"
  },
  {
    "id": {
      "slot": 15,
      "type": "sled"
    },
    "baseboard": {
      "type": "gimlet",
      "identifier": "BRM42220062",
      "model": "913-0000019",
      "revision": 6
    },
    "bootstrap_ip": "fdb0:a840:2504:312::1"
  },
  {
    "id": {
      "slot": 16,
      "type": "sled"
    },
    "baseboard": {
      "type": "gimlet",
      "identifier": "BRM42220030",
      "model": "913-0000019",
      "revision": 6
    },
    "bootstrap_ip": "fdb0:a840:2504:257::1"
  },
  {
    "id": {
      "slot": 17,
      "type": "sled"
    },
    "baseboard": {
      "type": "gimlet",
      "identifier": "BRM44220007",
      "model": "913-0000019",
      "revision": 6
    },
    "bootstrap_ip": "fdb0:a840:2504:492::1"
  }
]

@faithanalog faithanalog requested a review from sunshowers August 3, 2024 02:51
Copy link
Contributor

@sunshowers sunshowers left a comment

Choose a reason for hiding this comment

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

Looks fine to me! This isn't a stable interface I presume so we can iterate on it.

How hard would it be to add an integration test for this? There are a few in wicketd that spin up mgs, sp-sim, wicketd, and wicket, and ensure that it's sound end-to-end.


if json {
let json_str = serde_json::to_string(&sled_data)
.context("serializing sled data")?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe "error serializing sled data"?


#[derive(Serialize)]
struct ConfiguredBootstrapSledData {
cubby: u32,
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we call this slot?

};

let addr_fmt = match address {
None => "not_available".to_string(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this be (not available)?

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 admit I made it not_available to make it one field in awk even if you are using all whitespace as your field separator. but i think that's probably a bad reason given we have the json output and the data is tab-separated so yeah I'll change that

@faithanalog
Copy link
Contributor Author

Looks fine to me! This isn't a stable interface I presume so we can iterate on it.

How hard would it be to add an integration test for this? There are a few in wicketd that spin up mgs, sp-sim, wicketd, and wicket, and ensure that it's sound end-to-end.

yeah I will take a look, I was wanting to write a test for it but didn't know we had a framework in place for doing that.

};

// The rest of the data
println!("{status} Cubby {:02}\t{identifier}{addr_fmt}", slot);
Copy link
Member

Choose a reason for hiding this comment

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

@sunshowers i saw in the other comment above you asked for the field to be changed from slot to cubby, so:

  • is there a distinction between what "slot" vs "cubby" describes? i've seen "cubby" elsewhere and i'm kinda wondering if it's an (implicit?) word choice change or something else.
  • should this be {status} Slot {:02}? 😁

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 i am also not sure about that. This says Cubby because the wicket TUI also says Cubby today and I am just matching what that does.

Copy link
Contributor

Choose a reason for hiding this comment

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

is there a distinction between what "slot" vs "cubby" describes? i've seen "cubby" elsewhere and i'm kinda wondering if it's an (implicit?) word choice change or something else.

I think we've used the two terms interchangeably, not aware of specific differences between the two -- I know that the data structures internally mostly use "slot" which is why I was hoping at least the JSON could use "slot".

@faithanalog
Copy link
Contributor Author

I changed the json interface to use the type I was extracting data out of. It's a bit more verbose but it's got all the data I care about, and some extras someone else might find handy. And more importantly, it's a type used in other places of the codebase, so it'll be more clear that this command (and its test) might need adjustment if it changes.

Copy link
Contributor

@sunshowers sunshowers left a comment

Choose a reason for hiding this comment

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

Thank you!

Comment on lines 71 to 72
// This is the data we have today but I want it to be different from
// this to test having an address and such
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this comment left over from an earlier iteration?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh yeah sure is

@sunshowers
Copy link
Contributor

The test failure is a flaky one that should be resolved if you rebase on main FYI

Copy link
Member

@hawkw hawkw left a comment

Choose a reason for hiding this comment

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

I left some very minor little nits, but overall, this looks good to me!

Comment on lines 25 to 27
/// Print output as json
#[clap(long)]
json: bool,
Copy link
Member

Choose a reason for hiding this comment

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

suuuper nitpicky, doesn't actually matter: elsewhere, when writing CLI commands with multiple output formats, i like to define an output format enum and have a --output plain or --output text in addition to --output json/--output csv or what-have-you, rather than having a boolean flag for a specific format. that has two very small advantages IMO:

  1. if adding an additional output format, it makes it a bit clearer in the CLI that the output formats are mutually exclusive,
  2. when programmatically invoking the command, it's a bit nicer to just have to change the value of an arg based on the desired output format, rather than conditionally add or not-add an arg. e.g., a script invoking this can just always add an --output flag and pass plain or json, rather than adding/removing the --json.

but, OTTOH, this is a bit more code as it requires adding an enum and stuff...and, if other wicket commands have a --json already (AFAIK they don't, but i may have missed something), let's keep it consistent.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed about this! I'd use --format json and --format human.


let bootstrap_sleds = &conf.insensitive.bootstrap_sleds;
if json {
let json_str = serde_json::to_string(bootstrap_sleds)
Copy link
Member

Choose a reason for hiding this comment

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

nitpicky, take it or leave it: maybe nicer to use

Suggested change
let json_str = serde_json::to_string(bootstrap_sleds)
let json_str = serde_json::to_string_pretty(bootstrap_sleds)

here, since there isn't a ton of JSON and we're not trying to send it over the network? that way, a human user gets more readable output by default, which is maybe nice if the thing consuming the JSON chokes on it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, love the idea of using to_string_pretty.

Comment on lines +93 to +94
None => format!("{}", '⚠'.red()),
Some(_) => format!("{}", '✔'.green()),
Copy link
Member

Choose a reason for hiding this comment

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

IIUC, the colored crate's .red() and .green() return a ColoredString, which is the same type either way, so i don't think we need to format! these?

Suggested change
None => format!("{}", '⚠'.red()),
Some(_) => format!("{}", '✔'.green()),
None => '⚠'.red(),
Some(_) => '✔'.green(),

although maybe i'm overlooking something...

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah I think we use owo-colors here.

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 i think red() and green() here return Display or something like that.

};

let addr_fmt = match address {
None => "(not available)".to_string(),
Copy link
Member

Choose a reason for hiding this comment

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

nitpicky: looks like there's no whitespace in this case and it's smushed up against the identifier field? should there maybe be a tab or space here?

Copy link
Contributor Author

@faithanalog faithanalog Aug 9, 2024

Choose a reason for hiding this comment

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

yeah. artifact from my first pass where i didnt print anything when there wasnt an address.

@faithanalog faithanalog force-pushed the artemis/wicket-inventory-bootstrap-sleds branch from c259882 to 83ee04f Compare August 9, 2024 00:44
@faithanalog
Copy link
Contributor Author

oh dear i've been nitted! I will add --format json|table and make the json pretty so you dont need to jq it

@faithanalog
Copy link
Contributor Author

this worked fine on london so i am going to do the merge

@faithanalog faithanalog merged commit d391e5c into main Aug 9, 2024
22 checks passed
@faithanalog faithanalog deleted the artemis/wicket-inventory-bootstrap-sleds branch August 9, 2024 21:45
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.

4 participants