mirror of
https://github.com/khorevaa/kubodin.git
synced 2025-03-03 15:32:43 +02:00
263 lines
6.0 KiB
Go
263 lines
6.0 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/gofiber/fiber/v2/middleware/pprof"
|
|
"github.com/khorevaa/kubodin/api"
|
|
db "github.com/khorevaa/kubodin/database"
|
|
"github.com/khorevaa/kubodin/models"
|
|
"github.com/khorevaa/kubodin/service"
|
|
"github.com/khorevaa/kubodin/service/cache"
|
|
"github.com/mattn/go-colorable"
|
|
"github.com/mattn/go-isatty"
|
|
"github.com/urfave/cli/v2"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"strconv"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
swagger "github.com/arsmn/fiber-swagger/v2"
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/gofiber/fiber/v2/middleware/logger"
|
|
rec "github.com/gofiber/fiber/v2/middleware/recover"
|
|
|
|
_ "github.com/khorevaa/kubodin/docs" // docs is generated by Swag CLI, you have to import it.
|
|
)
|
|
|
|
type MainCommand struct {
|
|
debug bool
|
|
port string
|
|
|
|
appServer string
|
|
|
|
Version string
|
|
BuildBy string
|
|
Date string
|
|
}
|
|
|
|
func (c *MainCommand) Run(context *cli.Context) error {
|
|
|
|
server := fiber.New(fiber.Config{
|
|
DisableStartupMessage: true,
|
|
})
|
|
memoryCache := &cache.Memory{
|
|
Expiration: 30 * time.Minute,
|
|
}
|
|
memoryCache.Connect()
|
|
|
|
rep := db.NewMemoryRepository()
|
|
|
|
addr, port := parseAddr(c.appServer)
|
|
|
|
err := rep.AddAppServer(models.AppServer{
|
|
Name: "default",
|
|
Addr: addr,
|
|
Port: port,
|
|
Description: "default app server",
|
|
})
|
|
|
|
if err != nil {
|
|
log.Println("ERROR: Connect to ras server")
|
|
}
|
|
|
|
serv, err := service.NewService(memoryCache, rep)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Middleware
|
|
server.Use(rec.New())
|
|
server.Use(service.Middleware(serv))
|
|
|
|
if c.debug {
|
|
server.Use(logger.New())
|
|
server.Use(pprof.New())
|
|
}
|
|
|
|
api.Routes(server, serv)
|
|
|
|
server.Use("/docs", swagger.Handler) // default
|
|
|
|
// Handle not founds
|
|
server.Use(api.NotFound)
|
|
|
|
go func() {
|
|
c.startupMessage(c.port, false, c.debug, serv)
|
|
log.Fatal(server.Listen(c.port)) // go run main.go -port=:3000
|
|
}()
|
|
|
|
gracefullyShutdownInit(server)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *MainCommand) Flags() []cli.Flag {
|
|
|
|
return []cli.Flag{
|
|
&cli.StringFlag{
|
|
Destination: &c.port, Name: "port",
|
|
Value: ":3001", Usage: "port to listen on"},
|
|
&cli.StringFlag{
|
|
Destination: &c.appServer, Name: "server",
|
|
Value: "localhost:1545", Usage: "ras client address with port"},
|
|
&cli.BoolFlag{
|
|
Destination: &c.debug, Name: "debug",
|
|
Value: false, Usage: "debug mode"},
|
|
}
|
|
}
|
|
|
|
func (c *MainCommand) startupMessage(addr string, tls bool, debug bool, serv service.Service) {
|
|
|
|
if len(os.Getenv("FIBER_PREFORK_CHILD")) > 0 {
|
|
// Для подчиненных процессов мы не выводим сообщение
|
|
return
|
|
}
|
|
|
|
var logo string
|
|
logo += "%s"
|
|
logo += " ┌───────────────────────────────────────────────────┐\n"
|
|
logo += " │ %s │\n"
|
|
logo += " │ %s │\n"
|
|
logo += " │ %s │\n"
|
|
logo += " │ %s │\n"
|
|
logo += " │ %s │\n"
|
|
logo += " │ %s │\n"
|
|
logo += " │ │\n"
|
|
logo += " │ Built by: %s Built at: %s │\n"
|
|
logo += " │ Cache: %s DB: %s │\n"
|
|
logo += " └───────────────────────────────────────────────────┘"
|
|
logo += "%s"
|
|
|
|
const (
|
|
cBlack = "\u001b[90m"
|
|
// cRed = "\u001b[91m"
|
|
cCyan = "\u001b[96m"
|
|
// cGreen = "\u001b[92m"
|
|
cYellow = "\u001b[93m"
|
|
// cBlue = "\u001b[94m"
|
|
// cMagenta = "\u001b[95m"
|
|
// cWhite = "\u001b[97m"
|
|
cReset = "\u001b[0m"
|
|
)
|
|
|
|
value := func(s string, width int) string {
|
|
pad := width - len(s)
|
|
str := ""
|
|
for i := 0; i < pad; i++ {
|
|
str += "."
|
|
}
|
|
if s == "Disabled" {
|
|
str += " " + s
|
|
} else {
|
|
str += fmt.Sprintf(" %s%s%s", cYellow, s, cBlack)
|
|
}
|
|
return str
|
|
}
|
|
|
|
center := func(s string, width int) string {
|
|
pad := strconv.Itoa((width - len(s)) / 2)
|
|
str := fmt.Sprintf("%"+pad+"s", " ")
|
|
str += s
|
|
str += fmt.Sprintf("%"+pad+"s", " ")
|
|
if len(str) < width {
|
|
str += " "
|
|
}
|
|
return str
|
|
}
|
|
|
|
centerValue := func(s string, width int) string {
|
|
pad := strconv.Itoa((width - len(s)) / 2)
|
|
str := fmt.Sprintf("%"+pad+"s", " ")
|
|
str += fmt.Sprintf("%s%s%s", cCyan, s, cBlack)
|
|
str += fmt.Sprintf("%"+pad+"s", " ")
|
|
if len(str)-10 < width {
|
|
str += " "
|
|
}
|
|
return str
|
|
}
|
|
|
|
host, port := parseAddr(addr)
|
|
if host == "" || host == "0.0.0.0" {
|
|
host = "127.0.0.1"
|
|
}
|
|
addr = "http://" + host + ":" + port
|
|
if tls {
|
|
addr = "https://" + host + ":" + port
|
|
}
|
|
|
|
t, _ := time.Parse(time.RFC3339, c.Date)
|
|
|
|
cacheInfo := "redis"
|
|
switch serv.GetCache().(type) {
|
|
case *cache.Memory:
|
|
cacheInfo = "in memory"
|
|
}
|
|
|
|
dbInfo := "pudge"
|
|
pprofInfo := ""
|
|
if debug {
|
|
pprofInfo = " Pprof: " + addr + "/debug/pprof"
|
|
}
|
|
|
|
switch serv.Repository().(type) {
|
|
case *db.InMemory:
|
|
dbInfo = "in memory"
|
|
}
|
|
|
|
mainLogo := fmt.Sprintf(logo,
|
|
cBlack,
|
|
centerValue(" KUBODIN "+c.Version, 49),
|
|
center("Remote Administration", 49),
|
|
center("for 1S.Enterprise Application Servers", 49),
|
|
centerValue(" API: "+addr+"/api/v1", 49),
|
|
centerValue(" Docs: "+addr+"/docs", 49),
|
|
centerValue(pprofInfo, 49),
|
|
value(c.BuildBy, 13), value(t.Format("2006-01-02"), 13),
|
|
value(cacheInfo, 16), value(dbInfo, 19),
|
|
cReset,
|
|
)
|
|
|
|
out := colorable.NewColorableStdout()
|
|
if os.Getenv("TERM") == "dumb" ||
|
|
(!isatty.IsTerminal(os.Stdout.Fd()) &&
|
|
!isatty.IsCygwinTerminal(os.Stdout.Fd())) {
|
|
out = colorable.NewNonColorable(os.Stdout)
|
|
}
|
|
|
|
fmt.Fprintln(out, mainLogo)
|
|
}
|
|
|
|
func parseAddr(raw string) (host, port string) {
|
|
if i := strings.LastIndex(raw, ":"); i != -1 {
|
|
return raw[:i], raw[i+1:]
|
|
}
|
|
return raw, ""
|
|
}
|
|
|
|
func gracefullyShutdownInit(app *fiber.App) {
|
|
|
|
// Wait for interrupt signal to gracefully shutdown the server with
|
|
// setup signal catching
|
|
quit := make(chan os.Signal, 1)
|
|
// catch all signals since not explicitly listing
|
|
signal.Notify(quit, syscall.SIGQUIT, os.Interrupt, os.Kill)
|
|
|
|
q := <-quit
|
|
|
|
if q != nil {
|
|
println(fmt.Sprintf("RECEIVED SIGNAL: %s", q))
|
|
}
|
|
|
|
println("Shutdown Server ...")
|
|
if err := app.Shutdown(); err != nil {
|
|
log.Println("Server Shutdown:", err)
|
|
}
|
|
time.Sleep(2 * time.Second)
|
|
_ = cli.Exit("Shutdown complete", 0)
|
|
|
|
}
|