Refactor: Rename NanoKVM to BatchuKVM and update server URL
This commit is contained in:
147
server/service/extensions/tailscale/cli.go
Normal file
147
server/service/extensions/tailscale/cli.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package tailscale
|
||||
|
||||
import (
|
||||
"NanoKVM-Server/utils"
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
ScriptPath = "/etc/init.d/S98tailscaled"
|
||||
ScriptBackupPath = "/kvmapp/system/init.d/S98tailscaled"
|
||||
)
|
||||
|
||||
type Cli struct{}
|
||||
|
||||
type TsStatus struct {
|
||||
BackendState string `json:"BackendState"`
|
||||
|
||||
Self struct {
|
||||
HostName string `json:"HostName"`
|
||||
TailscaleIPs []string `json:"TailscaleIPs"`
|
||||
} `json:"Self"`
|
||||
|
||||
CurrentTailnet struct {
|
||||
Name string `json:"Name"`
|
||||
} `json:"CurrentTailnet"`
|
||||
}
|
||||
|
||||
func NewCli() *Cli {
|
||||
return &Cli{}
|
||||
}
|
||||
|
||||
func (c *Cli) Start() error {
|
||||
for _, filePath := range []string{TailscalePath, TailscaledPath} {
|
||||
if err := utils.EnsurePermission(filePath, 0o100); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
commands := []string{
|
||||
fmt.Sprintf("cp -f %s %s", ScriptBackupPath, ScriptPath),
|
||||
fmt.Sprintf("%s start", ScriptPath),
|
||||
}
|
||||
|
||||
command := strings.Join(commands, " && ")
|
||||
return exec.Command("sh", "-c", command).Run()
|
||||
}
|
||||
|
||||
func (c *Cli) Restart() error {
|
||||
commands := []string{
|
||||
fmt.Sprintf("cp -f %s %s", ScriptBackupPath, ScriptPath),
|
||||
fmt.Sprintf("%s restart", ScriptPath),
|
||||
}
|
||||
|
||||
command := strings.Join(commands, " && ")
|
||||
return exec.Command("sh", "-c", command).Run()
|
||||
}
|
||||
|
||||
func (c *Cli) Stop() error {
|
||||
command := fmt.Sprintf("%s stop", ScriptPath)
|
||||
err := exec.Command("sh", "-c", command).Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.Remove(ScriptPath)
|
||||
}
|
||||
|
||||
func (c *Cli) Up() error {
|
||||
command := "tailscale up --accept-dns=false"
|
||||
return exec.Command("sh", "-c", command).Run()
|
||||
}
|
||||
|
||||
func (c *Cli) Down() error {
|
||||
command := "tailscale down"
|
||||
return exec.Command("sh", "-c", command).Run()
|
||||
}
|
||||
|
||||
func (c *Cli) Status() (*TsStatus, error) {
|
||||
command := "tailscale status --json"
|
||||
cmd := exec.Command("sh", "-c", command)
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// output is not in standard json format
|
||||
if outputStr := string(output); !strings.HasPrefix(outputStr, "{") {
|
||||
index := strings.Index(outputStr, "{")
|
||||
if index == -1 {
|
||||
return nil, errors.New("unknown output")
|
||||
}
|
||||
|
||||
output = []byte(outputStr[index:])
|
||||
}
|
||||
|
||||
var status TsStatus
|
||||
err = json.Unmarshal(output, &status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &status, nil
|
||||
}
|
||||
|
||||
func (c *Cli) Login() (string, error) {
|
||||
command := "tailscale login --accept-dns=false --timeout=10m"
|
||||
cmd := exec.Command("sh", "-c", command)
|
||||
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer func() {
|
||||
_ = stderr.Close()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
_ = cmd.Run()
|
||||
}()
|
||||
|
||||
reader := bufio.NewReader(stderr)
|
||||
for {
|
||||
line, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if strings.Contains(line, "https") {
|
||||
reg := regexp.MustCompile(`\s+`)
|
||||
url := reg.ReplaceAllString(line, "")
|
||||
return url, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cli) Logout() error {
|
||||
command := "tailscale logout"
|
||||
return exec.Command("sh", "-c", command).Run()
|
||||
}
|
||||
Reference in New Issue
Block a user