mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-03-17 05:13:01 +00:00
feat(sandbox): add --anyone-client flag to rollout
- propagate `--anyone-client` to `orama node upgrade` on all nodes - prioritize explicit `--anyone-client` over prefs/auto-detect in production - ensure mutual exclusivity between relay/client modes in prefs
This commit is contained in:
parent
78d876e71b
commit
733b059681
@ -76,7 +76,10 @@ var rolloutCmd = &cobra.Command{
|
|||||||
Short: "Build + push + rolling upgrade to sandbox cluster",
|
Short: "Build + push + rolling upgrade to sandbox cluster",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
name, _ := cmd.Flags().GetString("name")
|
name, _ := cmd.Flags().GetString("name")
|
||||||
return sandbox.Rollout(name)
|
anyoneClient, _ := cmd.Flags().GetBool("anyone-client")
|
||||||
|
return sandbox.Rollout(name, sandbox.RolloutFlags{
|
||||||
|
AnyoneClient: anyoneClient,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,6 +124,7 @@ func init() {
|
|||||||
|
|
||||||
// rollout flags
|
// rollout flags
|
||||||
rolloutCmd.Flags().String("name", "", "Sandbox name (uses active if not specified)")
|
rolloutCmd.Flags().String("name", "", "Sandbox name (uses active if not specified)")
|
||||||
|
rolloutCmd.Flags().Bool("anyone-client", false, "Enable Anyone client (SOCKS5 proxy) on all nodes")
|
||||||
|
|
||||||
// ssh flags
|
// ssh flags
|
||||||
sshCmd.Flags().String("name", "", "Sandbox name (uses active if not specified)")
|
sshCmd.Flags().String("name", "", "Sandbox name (uses active if not specified)")
|
||||||
|
|||||||
@ -41,7 +41,8 @@ func NewOrchestrator(flags *Flags) *Orchestrator {
|
|||||||
setup := production.NewProductionSetup(oramaHome, os.Stdout, flags.Force, flags.SkipChecks)
|
setup := production.NewProductionSetup(oramaHome, os.Stdout, flags.Force, flags.SkipChecks)
|
||||||
setup.SetNameserver(isNameserver)
|
setup.SetNameserver(isNameserver)
|
||||||
|
|
||||||
// Configure Anyone mode (flag > saved preference > auto-detect)
|
// Configure Anyone mode (explicit flags > saved preferences > auto-detect)
|
||||||
|
// Explicit flags always win — they represent the user's current intent.
|
||||||
if flags.AnyoneRelay {
|
if flags.AnyoneRelay {
|
||||||
setup.SetAnyoneRelayConfig(&production.AnyoneRelayConfig{
|
setup.SetAnyoneRelayConfig(&production.AnyoneRelayConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
@ -55,6 +56,9 @@ func NewOrchestrator(flags *Flags) *Orchestrator {
|
|||||||
BandwidthPct: flags.AnyoneBandwidth,
|
BandwidthPct: flags.AnyoneBandwidth,
|
||||||
AccountingMax: flags.AnyoneAccounting,
|
AccountingMax: flags.AnyoneAccounting,
|
||||||
})
|
})
|
||||||
|
} else if flags.AnyoneClient {
|
||||||
|
// Explicit --anyone-client flag overrides saved relay prefs and auto-detect.
|
||||||
|
setup.SetAnyoneClient(true)
|
||||||
} else if prefs.AnyoneRelay {
|
} else if prefs.AnyoneRelay {
|
||||||
// Restore relay config from saved preferences (for firewall rules)
|
// Restore relay config from saved preferences (for firewall rules)
|
||||||
orPort := prefs.AnyoneORPort
|
orPort := prefs.AnyoneORPort
|
||||||
@ -65,6 +69,8 @@ func NewOrchestrator(flags *Flags) *Orchestrator {
|
|||||||
Enabled: true,
|
Enabled: true,
|
||||||
ORPort: orPort,
|
ORPort: orPort,
|
||||||
})
|
})
|
||||||
|
} else if prefs.AnyoneClient {
|
||||||
|
setup.SetAnyoneClient(true)
|
||||||
} else if detectAnyoneRelay(oramaDir) {
|
} else if detectAnyoneRelay(oramaDir) {
|
||||||
// Auto-detect: relay is installed but preferences weren't saved.
|
// Auto-detect: relay is installed but preferences weren't saved.
|
||||||
// This happens when upgrading from older versions that didn't persist
|
// This happens when upgrading from older versions that didn't persist
|
||||||
@ -79,8 +85,6 @@ func NewOrchestrator(flags *Flags) *Orchestrator {
|
|||||||
prefs.AnyoneORPort = orPort
|
prefs.AnyoneORPort = orPort
|
||||||
_ = production.SavePreferences(oramaDir, prefs)
|
_ = production.SavePreferences(oramaDir, prefs)
|
||||||
fmt.Printf(" Auto-detected Anyone relay (ORPort: %d), saved to preferences\n", orPort)
|
fmt.Printf(" Auto-detected Anyone relay (ORPort: %d), saved to preferences\n", orPort)
|
||||||
} else if flags.AnyoneClient || prefs.AnyoneClient {
|
|
||||||
setup.SetAnyoneClient(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Orchestrator{
|
return &Orchestrator{
|
||||||
@ -207,15 +211,15 @@ func (o *Orchestrator) handleBranchPreferences() error {
|
|||||||
fmt.Printf(" Nameserver mode: enabled (CoreDNS + Caddy)\n")
|
fmt.Printf(" Nameserver mode: enabled (CoreDNS + Caddy)\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
// If anyone-client was explicitly provided, update it
|
// Anyone client and relay are mutually exclusive — setting one clears the other.
|
||||||
if o.flags.AnyoneClient {
|
if o.flags.AnyoneClient {
|
||||||
prefs.AnyoneClient = true
|
prefs.AnyoneClient = true
|
||||||
|
prefs.AnyoneRelay = false
|
||||||
|
prefs.AnyoneORPort = 0
|
||||||
prefsChanged = true
|
prefsChanged = true
|
||||||
}
|
} else if o.flags.AnyoneRelay {
|
||||||
|
|
||||||
// If anyone-relay was explicitly provided, update it
|
|
||||||
if o.flags.AnyoneRelay {
|
|
||||||
prefs.AnyoneRelay = true
|
prefs.AnyoneRelay = true
|
||||||
|
prefs.AnyoneClient = false
|
||||||
prefs.AnyoneORPort = o.flags.AnyoneORPort
|
prefs.AnyoneORPort = o.flags.AnyoneORPort
|
||||||
if prefs.AnyoneORPort == 0 {
|
if prefs.AnyoneORPort == 0 {
|
||||||
prefs.AnyoneORPort = 9001
|
prefs.AnyoneORPort = 9001
|
||||||
|
|||||||
@ -4,14 +4,20 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/DeBrosOfficial/network/pkg/cli/remotessh"
|
"github.com/DeBrosOfficial/network/pkg/cli/remotessh"
|
||||||
"github.com/DeBrosOfficial/network/pkg/inspector"
|
"github.com/DeBrosOfficial/network/pkg/inspector"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// RolloutFlags holds optional flags passed through to `orama node upgrade`.
|
||||||
|
type RolloutFlags struct {
|
||||||
|
AnyoneClient bool
|
||||||
|
}
|
||||||
|
|
||||||
// Rollout builds, pushes, and performs a rolling upgrade on a sandbox cluster.
|
// Rollout builds, pushes, and performs a rolling upgrade on a sandbox cluster.
|
||||||
func Rollout(name string) error {
|
func Rollout(name string, flags RolloutFlags) error {
|
||||||
cfg, err := LoadConfig()
|
cfg, err := LoadConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -34,6 +40,9 @@ func Rollout(name string) error {
|
|||||||
info, _ := os.Stat(archivePath)
|
info, _ := os.Stat(archivePath)
|
||||||
fmt.Printf("Archive: %s (%s)\n\n", filepath.Base(archivePath), formatBytes(info.Size()))
|
fmt.Printf("Archive: %s (%s)\n\n", filepath.Base(archivePath), formatBytes(info.Size()))
|
||||||
|
|
||||||
|
// Build extra flags string for upgrade command
|
||||||
|
extraFlags := flags.upgradeFlags()
|
||||||
|
|
||||||
// Step 2: Push archive to all nodes (upload to first, fan out server-to-server)
|
// Step 2: Push archive to all nodes (upload to first, fan out server-to-server)
|
||||||
fmt.Println("Pushing archive to all nodes...")
|
fmt.Println("Pushing archive to all nodes...")
|
||||||
if err := fanoutArchive(state.Servers, sshKeyPath, archivePath); err != nil {
|
if err := fanoutArchive(state.Servers, sshKeyPath, archivePath); err != nil {
|
||||||
@ -54,7 +63,7 @@ func Rollout(name string) error {
|
|||||||
if i == leaderIdx {
|
if i == leaderIdx {
|
||||||
continue // skip leader, do it last
|
continue // skip leader, do it last
|
||||||
}
|
}
|
||||||
if err := upgradeNode(srv, sshKeyPath, i+1, len(state.Servers)); err != nil {
|
if err := upgradeNode(srv, sshKeyPath, i+1, len(state.Servers), extraFlags); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Wait between nodes
|
// Wait between nodes
|
||||||
@ -67,7 +76,7 @@ func Rollout(name string) error {
|
|||||||
// Upgrade leader last
|
// Upgrade leader last
|
||||||
if leaderIdx >= 0 {
|
if leaderIdx >= 0 {
|
||||||
srv := state.Servers[leaderIdx]
|
srv := state.Servers[leaderIdx]
|
||||||
if err := upgradeNode(srv, sshKeyPath, len(state.Servers), len(state.Servers)); err != nil {
|
if err := upgradeNode(srv, sshKeyPath, len(state.Servers), len(state.Servers), extraFlags); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,6 +85,15 @@ func Rollout(name string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// upgradeFlags builds the extra CLI flags string for `orama node upgrade`.
|
||||||
|
func (f RolloutFlags) upgradeFlags() string {
|
||||||
|
var parts []string
|
||||||
|
if f.AnyoneClient {
|
||||||
|
parts = append(parts, "--anyone-client")
|
||||||
|
}
|
||||||
|
return strings.Join(parts, " ")
|
||||||
|
}
|
||||||
|
|
||||||
// findLeaderIndex returns the index of the RQLite leader node, or -1 if unknown.
|
// findLeaderIndex returns the index of the RQLite leader node, or -1 if unknown.
|
||||||
func findLeaderIndex(state *SandboxState, sshKeyPath string) int {
|
func findLeaderIndex(state *SandboxState, sshKeyPath string) int {
|
||||||
for i, srv := range state.Servers {
|
for i, srv := range state.Servers {
|
||||||
@ -92,7 +110,7 @@ func findLeaderIndex(state *SandboxState, sshKeyPath string) int {
|
|||||||
// It pre-replaces the orama CLI binary before running the upgrade command
|
// It pre-replaces the orama CLI binary before running the upgrade command
|
||||||
// to avoid ETXTBSY ("text file busy") errors when the old binary doesn't
|
// to avoid ETXTBSY ("text file busy") errors when the old binary doesn't
|
||||||
// have the os.Remove fix in copyBinary().
|
// have the os.Remove fix in copyBinary().
|
||||||
func upgradeNode(srv ServerState, sshKeyPath string, current, total int) error {
|
func upgradeNode(srv ServerState, sshKeyPath string, current, total int, extraFlags string) error {
|
||||||
node := inspector.Node{User: "root", Host: srv.IP, SSHKey: sshKeyPath}
|
node := inspector.Node{User: "root", Host: srv.IP, SSHKey: sshKeyPath}
|
||||||
|
|
||||||
fmt.Printf(" [%d/%d] Upgrading %s (%s)...\n", current, total, srv.Name, srv.IP)
|
fmt.Printf(" [%d/%d] Upgrading %s (%s)...\n", current, total, srv.Name, srv.IP)
|
||||||
@ -105,7 +123,11 @@ func upgradeNode(srv ServerState, sshKeyPath string, current, total int) error {
|
|||||||
return fmt.Errorf("pre-replace orama binary on %s: %w", srv.Name, err)
|
return fmt.Errorf("pre-replace orama binary on %s: %w", srv.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := remotessh.RunSSHStreaming(node, "orama node upgrade --restart", remotessh.WithNoHostKeyCheck()); err != nil {
|
upgradeCmd := "orama node upgrade --restart"
|
||||||
|
if extraFlags != "" {
|
||||||
|
upgradeCmd += " " + extraFlags
|
||||||
|
}
|
||||||
|
if err := remotessh.RunSSHStreaming(node, upgradeCmd, remotessh.WithNoHostKeyCheck()); err != nil {
|
||||||
return fmt.Errorf("upgrade %s: %w", srv.Name, err)
|
return fmt.Errorf("upgrade %s: %w", srv.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user