diff --git a/cmd/mesh-controller/rollout.go b/cmd/mesh-controller/rollout.go index 6e4e8e1..562a9f7 100644 --- a/cmd/mesh-controller/rollout.go +++ b/cmd/mesh-controller/rollout.go @@ -33,14 +33,19 @@ import ( // ability to change things, not the services its modules are serving — measured on 2026-09-27, when // a seat emptied mid-change and the control plane looped for two hours while every service stayed up. -const rolloutUsage = "rollout check | rollout mint | rollout --confirm" +const rolloutUsage = "rollout check | rollout mint [--again] | rollout --confirm" func rolloutCommand(ctx context.Context, args []string) error { switch { case len(args) == 1 && args[0] == "check": return rolloutCheck(ctx) case len(args) == 1 && args[0] == "mint": - return rolloutMint(ctx) + return rolloutMint(ctx, false) + case len(args) == 2 && args[0] == "mint" && args[1] == "--again": + // Every credential minted afresh, whether or not one exists — for a mint that was wrong + // before anything was pushed. Afterwards nothing that received the old one still works, + // which is fine exactly when nothing received it. + return rolloutMint(ctx, true) case len(args) == 1 && args[0] == "--confirm": return errors.New( "the rollout itself is not built yet: `rollout check` answers whether it could run, and " + @@ -205,7 +210,7 @@ func notReadyOf(state broker.Readiness) []string { return broker.NotReady(state) // why `rollout check` refuses until this has run. The bus's address is worked out here, from where // the module that provides it is assigned, rather than read from this process's environment: this // process is still on the old bus when this runs, and must be. -func rolloutMint(ctx context.Context) error { +func rolloutMint(ctx context.Context, again bool) error { open, err := openStores(ctx) if err != nil { return err @@ -250,7 +255,16 @@ func rolloutMint(ctx context.Context) error { // when the new bus runs on the same machine, that address is the one to tell them, with the // new port. Found live: the control node is the hub, and the map lists the machines placed // around it. - host := strings.TrimSpace(broker.BareAddress(known.Address)) + // The host alone: no scheme (BareAddress adds one where none was, which is the wrong + // direction here — every URL built below adds its own) and no port. + _, _, host := broker.CredentialIn(known.Address) + if host == "" { + host = known.Address + } + if _, after, hasScheme := strings.Cut(host, "://"); hasScheme { + host = after + } + host = strings.TrimSpace(host) if i := strings.LastIndex(host, ":"); i > 0 && !strings.Contains(host[i:], "]") { host = host[:i] } @@ -286,7 +300,7 @@ func rolloutMint(ctx context.Context) error { var machines, modules, skipped int for _, p := range users { - if !wanted[p.Username()] { + if !again && !wanted[p.Username()] { continue } switch p.Kind {