RunBrowserBootstrap walks the operator through the browser-based first- admin bootstrap. Returns nil on success (server has flipped to setup_required: false), an error if the helper can't proceed (no token configured, token file unreadable, timeout, ctx cancelled). Callers in this PR: only setupCmd
(ctx context.Context, client *Client, cfg *config.Config, next string)
| 90 | // touching the token file or printing anything. That matters for any |
| 91 | // caller invoking it against a server where setup is already done. |
| 92 | func RunBrowserBootstrap(ctx context.Context, client *Client, cfg *config.Config, next string) error { |
| 93 | if client == nil { |
| 94 | return errors.New("RunBrowserBootstrap: nil client") |
| 95 | } |
| 96 | if cfg == nil { |
| 97 | return errors.New("RunBrowserBootstrap: nil config") |
| 98 | } |
| 99 | |
| 100 | session, err := client.CheckSession() |
| 101 | if err != nil { |
| 102 | return fmt.Errorf("check server status: %w", err) |
| 103 | } |
| 104 | if !session.SetupRequired { |
| 105 | // Already bootstrapped — nothing to do. |
| 106 | return nil |
| 107 | } |
| 108 | |
| 109 | setupURL, err := buildBootstrapURL(cfg, session.SetupMethod, next) |
| 110 | if err != nil { |
| 111 | return err |
| 112 | } |
| 113 | |
| 114 | bold := color.New(color.Bold).SprintFunc() |
| 115 | fmt.Println() |
| 116 | fmt.Println(" Open this URL in your browser to finish setup:") |
| 117 | fmt.Println() |
| 118 | fmt.Printf(" %s\n", bold(setupURL)) |
| 119 | fmt.Println() |
| 120 | fmt.Println(" Waiting for setup to complete (Ctrl+C to cancel)...") |
| 121 | |
| 122 | if err := pollUntilSetupDone(ctx, client); err != nil { |
| 123 | return err |
| 124 | } |
| 125 | |
| 126 | green := color.New(color.FgGreen).SprintFunc() |
| 127 | fmt.Printf(" %s Setup complete\n", green("✓")) |
| 128 | return nil |
| 129 | } |
| 130 | |
| 131 | // buildBootstrapURL constructs the /setup URL the operator should open. |
| 132 | // |