mirror of
https://github.com/fankes/beszel.git
synced 2025-10-19 01:39:34 +08:00
158 lines
4.2 KiB
Go
158 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/henrygd/beszel"
|
|
"github.com/henrygd/beszel/agent"
|
|
"github.com/henrygd/beszel/agent/health"
|
|
"github.com/spf13/pflag"
|
|
"golang.org/x/crypto/ssh"
|
|
)
|
|
|
|
// cli options
|
|
type cmdOptions struct {
|
|
key string // key is the public key(s) for SSH authentication.
|
|
listen string // listen is the address or port to listen on.
|
|
// TODO: add hubURL and token
|
|
// hubURL string // hubURL is the URL of the hub to use.
|
|
// token string // token is the token to use for authentication.
|
|
}
|
|
|
|
// parse parses the command line flags and populates the config struct.
|
|
// It returns true if a subcommand was handled and the program should exit.
|
|
func (opts *cmdOptions) parse() bool {
|
|
subcommand := ""
|
|
if len(os.Args) > 1 {
|
|
subcommand = os.Args[1]
|
|
}
|
|
|
|
// Subcommands that don't require any pflag parsing
|
|
switch subcommand {
|
|
case "-v", "version":
|
|
fmt.Println(beszel.AppName+"-agent", beszel.Version)
|
|
return true
|
|
case "health":
|
|
err := health.Check()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
fmt.Print("ok")
|
|
return true
|
|
}
|
|
|
|
// pflag.CommandLine.ParseErrorsWhitelist.UnknownFlags = true
|
|
pflag.StringVarP(&opts.key, "key", "k", "", "Public key(s) for SSH authentication")
|
|
pflag.StringVarP(&opts.listen, "listen", "l", "", "Address or port to listen on")
|
|
// pflag.StringVarP(&opts.hubURL, "hub-url", "u", "", "URL of the hub to use")
|
|
// pflag.StringVarP(&opts.token, "token", "t", "", "Token to use for authentication")
|
|
chinaMirrors := pflag.BoolP("china-mirrors", "c", false, "Use mirror for update (gh.beszel.dev) instead of GitHub")
|
|
help := pflag.BoolP("help", "h", false, "Show this help message")
|
|
|
|
// Convert old single-dash long flags to double-dash for backward compatibility
|
|
flagsToConvert := []string{"key", "listen"}
|
|
for i, arg := range os.Args {
|
|
for _, flag := range flagsToConvert {
|
|
singleDash := "-" + flag
|
|
doubleDash := "--" + flag
|
|
if arg == singleDash {
|
|
os.Args[i] = doubleDash
|
|
break
|
|
} else if strings.HasPrefix(arg, singleDash+"=") {
|
|
os.Args[i] = doubleDash + arg[len(singleDash):]
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
pflag.Usage = func() {
|
|
builder := strings.Builder{}
|
|
builder.WriteString("Usage: ")
|
|
builder.WriteString(os.Args[0])
|
|
builder.WriteString(" [command] [flags]\n")
|
|
builder.WriteString("\nCommands:\n")
|
|
builder.WriteString(" health Check if the agent is running\n")
|
|
// builder.WriteString(" help Display this help message\n")
|
|
builder.WriteString(" update Update to the latest version\n")
|
|
builder.WriteString("\nFlags:\n")
|
|
fmt.Print(builder.String())
|
|
pflag.PrintDefaults()
|
|
}
|
|
|
|
// Parse all arguments with pflag
|
|
pflag.Parse()
|
|
|
|
// Must run after pflag.Parse()
|
|
switch {
|
|
case *help || subcommand == "help":
|
|
pflag.Usage()
|
|
return true
|
|
case subcommand == "update":
|
|
agent.Update(*chinaMirrors)
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// loadPublicKeys loads the public keys from the command line flag, environment variable, or key file.
|
|
func (opts *cmdOptions) loadPublicKeys() ([]ssh.PublicKey, error) {
|
|
// Try command line flag first
|
|
if opts.key != "" {
|
|
return agent.ParseKeys(opts.key)
|
|
}
|
|
|
|
// Try environment variable
|
|
if key, ok := agent.GetEnv("KEY"); ok && key != "" {
|
|
return agent.ParseKeys(key)
|
|
}
|
|
|
|
// Try key file
|
|
keyFile, ok := agent.GetEnv("KEY_FILE")
|
|
if !ok {
|
|
return nil, fmt.Errorf("no key provided: must set -key flag, KEY env var, or KEY_FILE env var. Use 'beszel-agent help' for usage")
|
|
}
|
|
|
|
pubKey, err := os.ReadFile(keyFile)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read key file: %w", err)
|
|
}
|
|
return agent.ParseKeys(string(pubKey))
|
|
}
|
|
|
|
func (opts *cmdOptions) getAddress() string {
|
|
return agent.GetAddress(opts.listen)
|
|
}
|
|
|
|
func main() {
|
|
var opts cmdOptions
|
|
subcommandHandled := opts.parse()
|
|
|
|
if subcommandHandled {
|
|
return
|
|
}
|
|
|
|
var serverConfig agent.ServerOptions
|
|
var err error
|
|
serverConfig.Keys, err = opts.loadPublicKeys()
|
|
if err != nil {
|
|
log.Fatal("Failed to load public keys:", err)
|
|
}
|
|
|
|
addr := opts.getAddress()
|
|
serverConfig.Addr = addr
|
|
serverConfig.Network = agent.GetNetwork(addr)
|
|
|
|
a, err := agent.NewAgent()
|
|
if err != nil {
|
|
log.Fatal("Failed to create agent: ", err)
|
|
}
|
|
|
|
if err := a.Start(serverConfig); err != nil {
|
|
log.Fatal("Failed to start server: ", err)
|
|
}
|
|
}
|