The setup screens can reach a database machine by a join code instead of ssh: they listen on 7444 and show a short code; llmgw join dials out, checks the setup by fingerprint, admits itself with the code's secret, and runs what the setup sends until it is done. A joined machine is one more onboard.Remote, so checks and the Patroni install run over it unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
62 lines
2.1 KiB
Go
62 lines
2.1 KiB
Go
package cli
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"runtime"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
joinpkg "gitea.mynodes.xyz/ilker/llmgw/internal/join"
|
|
"gitea.mynodes.xyz/ilker/llmgw/internal/release"
|
|
"gitea.mynodes.xyz/ilker/llmgw/internal/version"
|
|
)
|
|
|
|
func newJoinCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "join <code>",
|
|
Short: "Let a setup on another machine set this one up, with the code it gave",
|
|
Long: "For a machine nothing may log into: the setup screens (sudo llmgw on\n" +
|
|
"the control plane) show a code for each machine they expect. Run this\n" +
|
|
"with it, as root, on that machine. It dials out to the setup — nothing\n" +
|
|
"dials in — checks it is the setup the code was made by, and runs what\n" +
|
|
"the setup sends until it is done: the same checks and installs ssh\n" +
|
|
"would carry. Each step is printed here as it runs.\n\n" +
|
|
"A code is good for one machine, for an hour, and only while the setup\n" +
|
|
"that made it is waiting.",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
if runtime.GOOS != "linux" {
|
|
return fmt.Errorf("join sets up a Linux machine; this is %s", runtime.GOOS)
|
|
}
|
|
if os.Geteuid() != 0 {
|
|
return errors.New("run it as root — sudo llmgw join … — since the setup installs software here")
|
|
}
|
|
code, err := joinpkg.Parse(args[0])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
out := cmd.OutOrStdout()
|
|
role := code.Role
|
|
if role == "" {
|
|
role = "part of a cluster"
|
|
}
|
|
fmt.Fprintf(out, "Joining the setup at %s, as %s. It runs as root here until it is done.\n", code.Addr, role)
|
|
return joinpkg.Serve(cmd.Context(), code, func(s string) { fmt.Fprintln(out, s) })
|
|
},
|
|
}
|
|
}
|
|
|
|
// joinInstall is what to run on a machine that has no llmgw yet, to fetch
|
|
// this version for its architecture: short lines, since it is copied from a
|
|
// screen that cuts long ones off.
|
|
func joinInstall() []string {
|
|
v := version.Version
|
|
return []string{
|
|
`a=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')`,
|
|
fmt.Sprintf("sudo curl -fsSL -o /usr/local/bin/llmgw \\\n %s/%s/llmgw-%s-linux-$a", release.DefaultBase, v, v),
|
|
"sudo chmod 755 /usr/local/bin/llmgw",
|
|
}
|
|
}
|