Preseed: Add lightweight preseed configuration - #1529
Conversation
43a91d8 to
07b995f
Compare
07b995f to
071d82a
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates MicroCloud’s preseed workflow so each node only needs to specify its own local preseed configuration, which is then forwarded to the initiator after trust is established, reducing per-node upfront configuration.
Changes:
- Add support for exchanging per-node preseed
Systemconfiguration during session join confirmation. - Replace preseed-wide
systemslist usage withsystem(plussession_systems), while keeping backward compatibility for legacy preseeds. - Update CLI/session plumbing to collect and validate the full set of system configs on the initiator side.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| service/session.go | Store and expose the local node’s System config in the trust session lifecycle. |
| service/microcloud.go | Extend RequestJoinIntent to return join confirmation metadata. |
| cmd/microcloud/session.go | Pass local System on join; collect joiner System configs on initiator. |
| cmd/microcloud/preseed.go | Introduce session_systems + system; translate legacy systems into system; validate once all configs are collected. |
| cmd/microcloud/preseed_test.go | Adapt validation tests and add legacy-resolution coverage. |
| cmd/microcloud/main_init.go | Track aggregated preseed System configs in initConfig. |
| cmd/microcloud/join.go | Update joining session call signature. |
| cmd/microcloud/ask.go | Switch join-intent expectations from explicit system list to expected count. |
| cmd/microcloud/add.go | Update initiating session call signature. |
| client/client.go | Parse join-intent response metadata into a SessionJoinConfirmation. |
| api/types/session.go | Add System fields and introduce SessionJoinConfirmation. |
| api/types/preseed.go | Add shared preseed System/storage types in API types. |
| api/session.go | Attach returned joiner System config to confirmed intents and return them to the CLI. |
| api/session_join.go | Return SessionJoinConfirmation (including joiner System when applicable). |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
2fdc0d1 to
678d9ac
Compare
The joiners will report their own System information as part of the join procedure. Therefore make the underlying type generally available. Signed-off-by: Julian Pelizäus <julian.pelizaeus@canonical.com>
Signed-off-by: Julian Pelizäus <julian.pelizaeus@canonical.com>
eb64be7 to
c10167b
Compare
There was a problem hiding this comment.
🟡 Changes recommended
There is a confirmed regression in auto-setup join-intent collection when expectedSystems is 0, causing erroneous failure in “no fixed number expected” scenarios.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 14/14 changed files
- Comments generated: 2
- Review effort level: Lite
c10167b to
e457b5b
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The current join-confirmation path can fail in non-preseed joins when no system config is set, and the lightweight preseed test data contains conflicting underlay IP assignments.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 15/15 changed files
- Comments generated: 4
- Review effort level: Lite
Signed-off-by: Julian Pelizäus <julian.pelizaeus@canonical.com>
SessionJoinConfirmation is essentially the addition to the trust establishment protocol. As part of the join confirmation, it allows the joiner to send back its own configuration over the estabsished mTLS connection which at this stage is already trusted by both peers. Signed-off-by: Julian Pelizäus <julian.pelizaeus@canonical.com>
This uses the last request of the join procedure to pass the joiners preseed configuration over the already established secure mTLS connection. Signed-off-by: Julian Pelizäus <julian.pelizaeus@canonical.com>
Signed-off-by: Julian Pelizäus <julian.pelizaeus@canonical.com>
Signed-off-by: Julian Pelizäus <julian.pelizaeus@canonical.com>
Signed-off-by: Julian Pelizäus <julian.pelizaeus@canonical.com>
Signed-off-by: Julian Pelizäus <julian.pelizaeus@canonical.com>
e457b5b to
b7acf97
Compare
Resolve the legacy preseed format and make sure the code always uses the new format (backwards compatibility). Also allow tracking the preseed configuration sent by the joiners and run the validation later once we have collected all of the preseed configuration. To ensure the initiator knows for how many systems it should wait, a new session_systems key is added to the preseed config. Signed-off-by: Julian Pelizäus <julian.pelizaeus@canonical.com>
Signed-off-by: Julian Pelizäus <julian.pelizaeus@canonical.com>
1db1ce6 to
8b4c629
Compare
…rmat Signed-off-by: Julian Pelizäus <julian.pelizaeus@canonical.com>
8b4c629 to
fe22c9b
Compare
|
This is ready for a first pass. As we still fully support the existing preseed format, I haven't yet adapted the docs but added another test to the preseed suite using the new lightweight format. |
kadinsayani
left a comment
There was a problem hiding this comment.
Looking good overall, just have a few questions :)
| if c.preseedSystems == nil { | ||
| c.preseedSystems = make([]*types.System, 0, 1) | ||
| } | ||
|
|
There was a problem hiding this comment.
Should we also check the joiner's System.Name against joinIntent.Name here?
| if !initiator { | ||
| err = c.runSession(context.Background(), s, types.SessionJoining, c.sessionTimeout, func(gw *cloudClient.WebsocketGateway) error { | ||
| return c.joiningSession(gw, s, installedServices, p.InitiatorAddress, p.SessionPassphrase) | ||
| return c.joiningSession(gw, s, installedServices, p.InitiatorAddress, p.SessionPassphrase, p.System) |
There was a problem hiding this comment.
Does this early return mean that joining systems never run p.validate()?
Overview
This PR aims to reduce the amount configuration that needs to be present on each system during preseed. Instead each system should be required to only define its own configuration and pass it to the initiator post successful trust establishment.
This "lightweight" preseed configuration aims to support a more performant charm deployment across many members/units.
Explanation
Step (18) in the sequence diagram of the explicit trust establishment mentions the long polling request returned by the joiner to the initiator (join confirmation). It allows the joiner to send data back to the initiator over the established and verified mTLS connection (verified by both peers). We use this already existing request to send a joiners preseed configuration over the wire. It's intentionally not sent as part of any of the initial requests as both peers don't yet trust each other and we don't want to leak any system internal information like disk paths or network interfaces over a not yet trusted link:
Impact
The configuration requirements are backwards compatible meaning the already existing preseed configuration will continue to work.
However joiners aren't anymore required to list all of the systems. Also initiators aren't anymore required to list any system. Instead they will wait for
session_systemsnumber of systems when using the new configuration format. This is a new configuration key.Both formats cannot be mixed.