cmd.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package base
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. "os"
  7. "reflect"
  8. "runtime"
  9. "strings"
  10. "github.com/bjdgyc/anylink/pkg/utils"
  11. "github.com/skip2/go-qrcode"
  12. "github.com/spf13/cobra"
  13. "github.com/spf13/viper"
  14. "github.com/xlzd/gotp"
  15. )
  16. var (
  17. // 提交id
  18. CommitId string
  19. // pass明文
  20. passwd string
  21. // 生成otp
  22. otp bool
  23. // 生成密钥
  24. secret bool
  25. // 显示版本信息
  26. rev bool
  27. // 输出debug信息
  28. debug bool
  29. // Used for flags.
  30. runSrv bool
  31. linkViper *viper.Viper
  32. rootCmd *cobra.Command
  33. )
  34. // Execute executes the root command.
  35. func execute() {
  36. initCmd()
  37. err := rootCmd.Execute()
  38. if err != nil {
  39. fmt.Println(err)
  40. os.Exit(0)
  41. }
  42. // viper.Debug()
  43. ref := reflect.ValueOf(linkViper)
  44. s := ref.Elem()
  45. ee := s.FieldByName("env")
  46. if ee.Kind() != reflect.Map {
  47. panic("Viper env is err")
  48. }
  49. rr := ee.MapRange()
  50. for rr.Next() {
  51. // fmt.Println(rr.Key(), rr.Value().Index(0))
  52. envs[rr.Key().String()] = rr.Value().Index(0).String()
  53. }
  54. if !runSrv {
  55. os.Exit(0)
  56. }
  57. }
  58. func initCmd() {
  59. linkViper = viper.New()
  60. rootCmd = &cobra.Command{
  61. Use: "anylink",
  62. Short: "AnyLink VPN Server",
  63. Long: `AnyLink is a VPN Server application`,
  64. Run: func(cmd *cobra.Command, args []string) {
  65. // fmt.Println("cmd:", cmd.Use, args)
  66. runSrv = true
  67. if rev {
  68. printVersion()
  69. os.Exit(0)
  70. }
  71. },
  72. }
  73. linkViper.SetEnvPrefix("link")
  74. // 基础配置
  75. for _, v := range configs {
  76. if v.Typ == cfgStr {
  77. rootCmd.Flags().StringP(v.Name, v.Short, v.ValStr, v.Usage)
  78. }
  79. if v.Typ == cfgInt {
  80. rootCmd.Flags().IntP(v.Name, v.Short, v.ValInt, v.Usage)
  81. }
  82. if v.Typ == cfgBool {
  83. rootCmd.Flags().BoolP(v.Name, v.Short, v.ValBool, v.Usage)
  84. }
  85. _ = linkViper.BindPFlag(v.Name, rootCmd.Flags().Lookup(v.Name))
  86. _ = linkViper.BindEnv(v.Name)
  87. // viper.SetDefault(v.Name, v.Value)
  88. }
  89. rootCmd.Flags().BoolVarP(&rev, "version", "v", false, "display version info")
  90. rootCmd.AddCommand(initToolCmd())
  91. cobra.OnInitialize(func() {
  92. linkViper.AutomaticEnv()
  93. conf := linkViper.GetString("conf")
  94. _, err := os.Stat(conf)
  95. if errors.Is(err, os.ErrNotExist) {
  96. // 没有配置文件,不做处理
  97. panic(err)
  98. }
  99. linkViper.SetConfigFile(conf)
  100. err = linkViper.ReadInConfig()
  101. if err != nil {
  102. panic("config file err:" + err.Error())
  103. }
  104. })
  105. }
  106. func initToolCmd() *cobra.Command {
  107. toolCmd := &cobra.Command{
  108. Use: "tool",
  109. Short: "AnyLink tool",
  110. Long: `AnyLink tool is a application`,
  111. }
  112. toolCmd.Flags().BoolVarP(&rev, "version", "v", false, "display version info")
  113. toolCmd.Flags().BoolVarP(&secret, "secret", "s", false, "generate a random jwt secret")
  114. toolCmd.Flags().StringVarP(&passwd, "passwd", "p", "", "convert the password plaintext")
  115. toolCmd.Flags().BoolVarP(&otp, "otp", "o", false, "generate a random otp secret")
  116. toolCmd.Flags().BoolVarP(&debug, "debug", "d", false, "list the config viper.Debug() info")
  117. toolCmd.Run = func(cmd *cobra.Command, args []string) {
  118. switch {
  119. case rev:
  120. printVersion()
  121. case secret:
  122. s, _ := utils.RandSecret(40, 60)
  123. s = strings.Trim(s, "=")
  124. fmt.Printf("Secret:%s\n", s)
  125. case otp:
  126. s := gotp.RandomSecret(32)
  127. fmt.Printf("Otp:%s\n\n", s)
  128. qrstr := fmt.Sprintf("otpauth://totp/%s:%s?issuer=%s&secret=%s", "anylink_admin", "admin@anylink", "anylink_admin", s)
  129. qr, _ := qrcode.New(qrstr, qrcode.High)
  130. ss := qr.ToSmallString(false)
  131. io.WriteString(os.Stderr, ss)
  132. case passwd != "":
  133. pass, _ := utils.PasswordHash(passwd)
  134. fmt.Printf("Passwd:%s\n", pass)
  135. case debug:
  136. linkViper.Debug()
  137. default:
  138. fmt.Println("Using [anylink tool -h] for help")
  139. }
  140. }
  141. return toolCmd
  142. }
  143. func printVersion() {
  144. fmt.Printf("%s v%s build on %s [%s, %s] commit_id(%s) \n",
  145. APP_NAME, APP_VER, runtime.Version(), runtime.GOOS, runtime.GOARCH, CommitId)
  146. }