Migrate to spf13/cobra for flags parsing

This commit is contained in:
Berger Eugene 2022-10-22 22:13:31 +03:00
parent 2c66707e6d
commit 5c49172cbc
7 changed files with 155 additions and 115 deletions

3
go.mod
View File

@ -28,6 +28,7 @@ require (
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.11.1 // indirect
github.com/goccy/go-json v0.9.11 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
@ -38,6 +39,8 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/rivo/uniseg v0.4.2 // indirect
github.com/spf13/cobra v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be // indirect
golang.org/x/net v0.0.0-20220926192436-02166a98028e // indirect

8
go.sum
View File

@ -18,6 +18,7 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -77,6 +78,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@ -150,12 +153,17 @@ github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI=
github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=

View File

@ -13,7 +13,7 @@ import (
"syscall"
"time"
"github.com/f1bonacc1/process-compose/src/cmd"
"github.com/f1bonacc1/process-compose/src/command"
"github.com/f1bonacc1/process-compose/src/health"
"github.com/f1bonacc1/process-compose/src/pclog"
@ -85,7 +85,7 @@ func (p *Process) run() error {
}
for {
starter := func() error {
p.command = cmd.BuildCommand(p.getCommand())
p.command = command.BuildCommand(p.getCommand())
p.command.Env = p.getProcessEnvironment()
p.setProcArgs()
stdout, _ := p.command.StdoutPipe()
@ -223,10 +223,10 @@ func (p *Process) doConfiguredStop(params ShutDownParams) error {
defer cancel()
defer p.notifyDaemonStopped()
command := cmd.BuildCommandContext(ctx, params.ShutDownCommand)
command.Env = p.getProcessEnvironment()
cmd := command.BuildCommandContext(ctx, params.ShutDownCommand)
cmd.Env = p.getProcessEnvironment()
if err := command.Run(); err != nil {
if err := cmd.Run(); err != nil {
// the process termination timedout and it will be killed
log.Error().Msgf("terminating %s with timeout %d failed - %s", p.getName(), timeout, err.Error())
return p.stop(int(syscall.SIGKILL))
@ -393,7 +393,7 @@ func (p *Process) stopProbes() {
}
}
func (p *Process) onLivenessCheckEnd(isOk, isFatal bool, err string) {
func (p *Process) onLivenessCheckEnd(_, isFatal bool, err string) {
if isFatal {
log.Info().Msgf("%s is not alive anymore - %s", p.getName(), err)
p.logBuffer.Write("Error: liveness check fail - " + err)

132
src/cmd/root.go Normal file
View File

@ -0,0 +1,132 @@
package cmd
import (
"fmt"
"github.com/f1bonacc1/process-compose/src/api"
"github.com/f1bonacc1/process-compose/src/app"
"github.com/f1bonacc1/process-compose/src/tui"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
)
const EnvDebugMode = "PC_DEBUG_MODE"
var (
fileName string
port int
isTui bool
version string
// rootCmd represents the base command when called without any subcommands
rootCmd = &cobra.Command{
Use: "process-compose",
Short: "A brief description of your application",
Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
// Uncomment the following line if your bare application
// has an action associated with it:
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(fileName)
if !cmd.Flags().Changed("config") {
pwd, err := os.Getwd()
if err != nil {
log.Fatal().Msg(err.Error())
}
file, err := app.AutoDiscoverComposeFile(pwd)
if err != nil {
log.Fatal().Msg(err.Error())
}
fileName = file
}
if os.Getenv(EnvDebugMode) == "" {
gin.SetMode(gin.ReleaseMode)
}
routersInit := api.InitRoutes(!isTui)
readTimeout := time.Duration(60) * time.Second
writeTimeout := time.Duration(60) * time.Second
endPoint := fmt.Sprintf(":%d", port)
maxHeaderBytes := 1 << 20
server := &http.Server{
Addr: endPoint,
Handler: routersInit,
ReadTimeout: readTimeout,
WriteTimeout: writeTimeout,
MaxHeaderBytes: maxHeaderBytes,
}
log.Info().Msgf("start http server listening %s", endPoint)
go server.ListenAndServe()
project := app.CreateProject(fileName)
if isTui {
defer quiet()()
go project.Run()
tui.SetupTui(version, project.LogLength)
} else {
runHeadless(project)
}
log.Info().Msg("Thank you for using proccess-compose")
},
}
)
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute(ver string) {
version = ver
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
func init() {
rootCmd.Flags().StringVarP(&fileName, "config", "f", app.DefaultFileNames[0], "path to config file to load")
rootCmd.Flags().BoolVarP(&isTui, "tui", "t", true, "disable tui (-t=false)")
rootCmd.Flags().IntVarP(&port, "port", "p", 8080, "port number")
}
func runHeadless(project *app.Project) {
cancelChan := make(chan os.Signal, 1)
// catch SIGTERM or SIGINTERRUPT
signal.Notify(cancelChan, syscall.SIGTERM, syscall.SIGINT)
go project.Run()
sig := <-cancelChan
log.Info().Msgf("Caught %v - Shutting down the running processes...", sig)
project.ShutDownProject()
}
func quiet() func() {
null, _ := os.Open(os.DevNull)
sout := os.Stdout
serr := os.Stderr
os.Stdout = null
os.Stderr = null
zerolog.SetGlobalLevel(zerolog.Disabled)
return func() {
defer null.Close()
os.Stdout = sout
os.Stderr = serr
zerolog.SetGlobalLevel(zerolog.DebugLevel)
}
}

View File

@ -1,4 +1,4 @@
package cmd
package command
import (
"context"

View File

@ -2,9 +2,8 @@ package health
import (
"context"
"github.com/f1bonacc1/process-compose/src/command"
"time"
"github.com/f1bonacc1/process-compose/src/cmd"
)
type execChecker struct {
@ -16,7 +15,7 @@ func (c *execChecker) Status() (interface{}, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(c.timeout)*time.Second)
defer cancel()
cmd := cmd.BuildCommandContext(ctx, c.command)
cmd := command.BuildCommandContext(ctx, c.command)
if err := cmd.Run(); err != nil {
return nil, err

View File

@ -1,25 +1,12 @@
package main
import (
"flag"
"fmt"
"net/http"
"os/signal"
"syscall"
"time"
"os"
"github.com/f1bonacc1/process-compose/src/api"
"github.com/f1bonacc1/process-compose/src/app"
"github.com/f1bonacc1/process-compose/src/tui"
"github.com/gin-gonic/gin"
"github.com/f1bonacc1/process-compose/src/cmd"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"os"
)
const EnvDebugMode = "PC_DEBUG_MODE"
var version = "undefined"
func setupLogger() {
@ -31,99 +18,10 @@ func setupLogger() {
zerolog.SetGlobalLevel(zerolog.DebugLevel)
}
func isFlagPassed(name string) bool {
found := false
flag.Visit(func(f *flag.Flag) {
if f.Name == name {
found = true
}
})
return found
}
func init() {
setupLogger()
}
func quiet() func() {
null, _ := os.Open(os.DevNull)
sout := os.Stdout
serr := os.Stderr
os.Stdout = null
os.Stderr = null
zerolog.SetGlobalLevel(zerolog.Disabled)
return func() {
defer null.Close()
os.Stdout = sout
os.Stderr = serr
zerolog.SetGlobalLevel(zerolog.DebugLevel)
}
}
func runHeadless(project *app.Project) {
cancelChan := make(chan os.Signal, 1)
// catch SIGTERM or SIGINTERRUPT
signal.Notify(cancelChan, syscall.SIGTERM, syscall.SIGINT)
go func() {
project.Run()
}()
sig := <-cancelChan
log.Info().Msgf("Caught %v - Shutting down the running processes...", sig)
project.ShutDownProject()
}
func main() {
fileName := ""
port := 8080
isTui := true
flag.StringVar(&fileName, "f", app.DefaultFileNames[0], "path to file to load")
flag.IntVar(&port, "p", port, "port number")
flag.BoolVar(&isTui, "t", isTui, "disable tui (-t=false)")
flag.Parse()
if !isFlagPassed("f") {
pwd, err := os.Getwd()
if err != nil {
log.Fatal().Msg(err.Error())
}
file, err := app.AutoDiscoverComposeFile(pwd)
if err != nil {
log.Fatal().Msg(err.Error())
}
fileName = file
}
if os.Getenv(EnvDebugMode) == "" {
gin.SetMode(gin.ReleaseMode)
}
routersInit := api.InitRoutes(!isTui)
readTimeout := time.Duration(60) * time.Second
writeTimeout := time.Duration(60) * time.Second
endPoint := fmt.Sprintf(":%d", port)
maxHeaderBytes := 1 << 20
server := &http.Server{
Addr: endPoint,
Handler: routersInit,
ReadTimeout: readTimeout,
WriteTimeout: writeTimeout,
MaxHeaderBytes: maxHeaderBytes,
}
log.Info().Msgf("start http server listening %s", endPoint)
go server.ListenAndServe()
project := app.CreateProject(fileName)
if isTui {
defer quiet()()
go project.Run()
tui.SetupTui(version, project.LogLength)
} else {
runHeadless(project)
}
log.Info().Msg("Thank you for using proccess-compose")
cmd.Execute(version)
}