anylink/server/base/cmd.go

176 lines
3.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package base
import (
"fmt"
"io"
"os"
"reflect"
"runtime"
"strings"
"github.com/bjdgyc/anylink/pkg/utils"
"github.com/skip2/go-qrcode"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/xlzd/gotp"
)
var (
// pass明文
passwd string
// 生成otp
otp bool
// 生成密钥
secret bool
// 显示版本信息
rev bool
// 输出debug信息
debug bool
// Used for flags.
runSrv bool
linkViper *viper.Viper
rootCmd *cobra.Command
)
// Execute executes the root command.
func execute() {
initCmd()
err := rootCmd.Execute()
if err != nil {
fmt.Println(err)
os.Exit(0)
}
// viper.Debug()
ref := reflect.ValueOf(linkViper)
s := ref.Elem()
ee := s.FieldByName("env")
if ee.Kind() != reflect.Map {
panic("Viper env is err")
}
rr := ee.MapRange()
for rr.Next() {
// fmt.Println(rr.Key(), rr.Value().Index(0))
envs[rr.Key().String()] = rr.Value().Index(0).String()
}
if !runSrv {
if debug {
scfgData := ServerCfg2Slice()
fmtStr := "%-18v %-23v %-20v %v\n"
fmt.Printf(fmtStr, "Name", "Env", "Value", "Info")
for _, v := range scfgData {
if v.Name == "admin_pass" || v.Name == "jwt_secret" {
v.Val = "******"
}
fmt.Printf(fmtStr, v.Name, v.Env, v.Val, v.Info)
}
}
os.Exit(0)
}
// 移动配置解析代码
conf := linkViper.GetString("conf")
linkViper.SetConfigFile(conf)
err = linkViper.ReadInConfig()
if err != nil {
// 没有配置文件,直接报错
panic("config file err:" + err.Error())
}
}
func initCmd() {
linkViper = viper.New()
rootCmd = &cobra.Command{
Use: "anylink",
Short: "AnyLink VPN Server",
Long: `AnyLink is a VPN Server application`,
Run: func(cmd *cobra.Command, args []string) {
// fmt.Println("cmd", cmd.Use, args)
runSrv = true
if rev {
printVersion()
os.Exit(0)
}
},
}
linkViper.SetEnvPrefix("link")
// 基础配置
for _, v := range configs {
if v.Typ == cfgStr {
rootCmd.Flags().StringP(v.Name, v.Short, v.ValStr, v.Usage)
}
if v.Typ == cfgInt {
rootCmd.Flags().IntP(v.Name, v.Short, v.ValInt, v.Usage)
}
if v.Typ == cfgBool {
rootCmd.Flags().BoolP(v.Name, v.Short, v.ValBool, v.Usage)
}
_ = linkViper.BindPFlag(v.Name, rootCmd.Flags().Lookup(v.Name))
_ = linkViper.BindEnv(v.Name)
// viper.SetDefault(v.Name, v.Value)
}
rootCmd.Flags().BoolVarP(&rev, "version", "v", false, "display version info")
rootCmd.AddCommand(initToolCmd())
cobra.OnInitialize(func() {
linkViper.AutomaticEnv()
})
}
func initToolCmd() *cobra.Command {
toolCmd := &cobra.Command{
Use: "tool",
Short: "AnyLink tool",
Long: `AnyLink tool is a application`,
}
toolCmd.Flags().BoolVarP(&rev, "version", "v", false, "display version info")
toolCmd.Flags().BoolVarP(&secret, "secret", "s", false, "generate a random jwt secret")
toolCmd.Flags().StringVarP(&passwd, "passwd", "p", "", "convert the password plaintext")
toolCmd.Flags().BoolVarP(&otp, "otp", "o", false, "generate a random otp secret")
toolCmd.Flags().BoolVarP(&debug, "debug", "d", false, "list the config viper.Debug() info")
toolCmd.Run = func(cmd *cobra.Command, args []string) {
runSrv = false
switch {
case rev:
printVersion()
case secret:
s, _ := utils.RandSecret(40, 60)
s = strings.Trim(s, "=")
fmt.Printf("Secret:%s\n", s)
case otp:
s := gotp.RandomSecret(32)
fmt.Printf("Otp:%s\n\n", s)
qrstr := fmt.Sprintf("otpauth://totp/%s:%s?issuer=%s&secret=%s", "anylink_admin", "admin@anylink", "anylink_admin", s)
qr, _ := qrcode.New(qrstr, qrcode.High)
ss := qr.ToSmallString(false)
io.WriteString(os.Stderr, ss)
case passwd != "":
pass, _ := utils.PasswordHash(passwd)
fmt.Printf("Passwd:%s\n", pass)
case debug:
// linkViper.Debug()
default:
fmt.Println("Using [anylink tool -h] for help")
}
}
return toolCmd
}
func printVersion() {
fmt.Printf("%s v%s build on %s [%s, %s] date:%s commit_id(%s)\n",
APP_NAME, APP_VER, runtime.Version(), runtime.GOOS, runtime.GOARCH, BuildDate, CommitId)
}