summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/cli/reset.go107
-rw-r--r--cmd/cli/root.go101
-rw-r--r--cmd/cli/serve.go63
-rw-r--r--cmd/cli/version.go (renamed from cmd/rr/cmd/version.go)6
-rw-r--r--cmd/cli/workers.go110
-rw-r--r--cmd/main.go58
-rw-r--r--cmd/rr/LICENSE21
-rw-r--r--cmd/rr/cmd/root.go159
-rw-r--r--cmd/rr/cmd/serve.go64
-rw-r--r--cmd/rr/cmd/stop.go51
-rw-r--r--cmd/rr/http/debug.go139
-rw-r--r--cmd/rr/http/metrics.go124
-rw-r--r--cmd/rr/http/reset.go53
-rw-r--r--cmd/rr/http/workers.go101
-rw-r--r--cmd/rr/limit/debug.go71
-rw-r--r--cmd/rr/limit/metrics.go63
-rw-r--r--cmd/rr/main.go59
-rw-r--r--cmd/util/config.go182
-rw-r--r--cmd/util/cprint.go48
-rw-r--r--cmd/util/debug.go62
-rw-r--r--cmd/util/exit.go15
-rw-r--r--cmd/util/rpc.go19
-rw-r--r--cmd/util/table.go61
23 files changed, 442 insertions, 1295 deletions
diff --git a/cmd/cli/reset.go b/cmd/cli/reset.go
new file mode 100644
index 00000000..504d88ad
--- /dev/null
+++ b/cmd/cli/reset.go
@@ -0,0 +1,107 @@
+package cli
+
+import (
+ "fmt"
+ "sync"
+
+ "github.com/fatih/color"
+ "github.com/mattn/go-runewidth"
+ "github.com/spf13/cobra"
+ "github.com/spiral/errors"
+ "github.com/vbauerster/mpb/v5"
+ "github.com/vbauerster/mpb/v5/decor"
+)
+
+// List is the resetter.List RPC method
+const List string = "resetter.List"
+
+// Reset is the resetter.Reset RPC method
+const Reset string = "resetter.Reset"
+
+func init() {
+ root.AddCommand(&cobra.Command{
+ Use: "reset",
+ Short: "Reset workers of all or specific RoadRunner service",
+ RunE: resetHandler,
+ })
+}
+
+func resetHandler(cmd *cobra.Command, args []string) error {
+ const op = errors.Op("reset handler")
+ client, err := RPCClient()
+ if err != nil {
+ return err
+ }
+ defer func() {
+ _ = client.Close()
+ }()
+
+ var services []string
+ if len(args) != 0 {
+ services = args
+ } else {
+ err = client.Call(List, true, &services)
+ if err != nil {
+ return errors.E(op, err)
+ }
+ }
+
+ var wg sync.WaitGroup
+ pr := mpb.New(mpb.WithWaitGroup(&wg), mpb.WithWidth(6))
+ wg.Add(len(services))
+
+ for _, service := range services {
+ var (
+ bar *mpb.Bar
+ name = runewidth.FillRight(fmt.Sprintf("Resetting plugin: [%s]", color.HiYellowString(service)), 27)
+ result = make(chan interface{})
+ )
+
+ bar = pr.AddSpinner(
+ 1,
+ mpb.SpinnerOnMiddle,
+ mpb.SpinnerStyle([]string{"∙∙∙", "●∙∙", "∙●∙", "∙∙●", "∙∙∙"}),
+ mpb.PrependDecorators(decor.Name(name)),
+ mpb.AppendDecorators(onComplete(result)),
+ )
+
+ // simulating some work
+ go func(service string, result chan interface{}) {
+ defer wg.Done()
+ defer bar.Increment()
+
+ var done bool
+ err = client.Call(Reset, service, &done)
+ if err != nil {
+ result <- errors.E(op, err)
+ return
+ }
+ result <- nil
+ }(service, result)
+ }
+
+ pr.Wait()
+ return nil
+}
+
+func onComplete(result chan interface{}) decor.Decorator {
+ var (
+ msg = ""
+ fn = func(s decor.Statistics) string {
+ select {
+ case r := <-result:
+ if err, ok := r.(error); ok {
+ msg = color.HiRedString(err.Error())
+ return msg
+ }
+
+ msg = color.HiGreenString("done")
+ return msg
+ default:
+ return msg
+ }
+ }
+ )
+
+ return decor.Any(fn)
+}
diff --git a/cmd/cli/root.go b/cmd/cli/root.go
new file mode 100644
index 00000000..06a84a82
--- /dev/null
+++ b/cmd/cli/root.go
@@ -0,0 +1,101 @@
+package cli
+
+import (
+ "log"
+ "net/rpc"
+ "os"
+ "path/filepath"
+
+ "github.com/spiral/errors"
+ goridgeRpc "github.com/spiral/goridge/v3/pkg/rpc"
+ rpcPlugin "github.com/spiral/roadrunner/v2/plugins/rpc"
+
+ "github.com/spiral/roadrunner/v2/plugins/config"
+
+ "github.com/spf13/cobra"
+ "github.com/spiral/endure"
+)
+
+var (
+ // WorkDir is working directory
+ WorkDir string
+ // CfgFile is path to the .rr.yaml
+ CfgFile string
+ // Container is the pointer to the Endure container
+ Container *endure.Endure
+ cfg *config.Viper
+ root = &cobra.Command{
+ Use: "rr",
+ SilenceErrors: true,
+ SilenceUsage: true,
+ Version: Version,
+ }
+)
+
+func Execute() {
+ if err := root.Execute(); err != nil {
+ // exit with error, fatal invoke os.Exit(1)
+ log.Fatal(err)
+ }
+}
+
+func init() {
+ root.PersistentFlags().StringVarP(&CfgFile, "config", "c", ".rr.yaml", "config file (default is .rr.yaml)")
+ root.PersistentFlags().StringVarP(&WorkDir, "WorkDir", "w", "", "work directory")
+
+ cobra.OnInitialize(func() {
+ if CfgFile != "" {
+ if absPath, err := filepath.Abs(CfgFile); err == nil {
+ CfgFile = absPath
+
+ // force working absPath related to config file
+ if err := os.Chdir(filepath.Dir(absPath)); err != nil {
+ panic(err)
+ }
+ }
+ }
+
+ if WorkDir != "" {
+ if err := os.Chdir(WorkDir); err != nil {
+ panic(err)
+ }
+ }
+
+ cfg = &config.Viper{}
+ cfg.Path = CfgFile
+ cfg.Prefix = "rr"
+
+ // register config
+ err := Container.Register(cfg)
+ if err != nil {
+ panic(err)
+ }
+ })
+}
+
+// RPCClient is using to make a requests to the ./rr reset, ./rr workers
+func RPCClient() (*rpc.Client, error) {
+ rpcConfig := &rpcPlugin.Config{}
+
+ err := cfg.Init()
+ if err != nil {
+ return nil, err
+ }
+
+ if !cfg.Has(rpcPlugin.PluginName) {
+ return nil, errors.E("rpc service disabled")
+ }
+
+ err = cfg.UnmarshalKey(rpcPlugin.PluginName, rpcConfig)
+ if err != nil {
+ return nil, err
+ }
+ rpcConfig.InitDefaults()
+
+ conn, err := rpcConfig.Dialer()
+ if err != nil {
+ return nil, err
+ }
+
+ return rpc.NewClientWithCodec(goridgeRpc.NewClientCodec(conn)), nil
+}
diff --git a/cmd/cli/serve.go b/cmd/cli/serve.go
new file mode 100644
index 00000000..2fe54932
--- /dev/null
+++ b/cmd/cli/serve.go
@@ -0,0 +1,63 @@
+package cli
+
+import (
+ "log"
+ "os"
+ "os/signal"
+ "syscall"
+
+ "github.com/spf13/cobra"
+ "github.com/spiral/errors"
+ "go.uber.org/multierr"
+)
+
+func init() {
+ root.AddCommand(&cobra.Command{
+ Use: "serve",
+ Short: "Start RoadRunner server",
+ RunE: handler,
+ })
+}
+
+func handler(cmd *cobra.Command, args []string) error {
+ const op = errors.Op("handle serve command")
+ /*
+ We need to have path to the config at the RegisterTarget stage
+ But after cobra.Execute, because cobra fills up cli variables on this stage
+ */
+
+ err := Container.Init()
+ if err != nil {
+ return errors.E(op, err)
+ }
+
+ errCh, err := Container.Serve()
+ if err != nil {
+ return errors.E(op, err)
+ }
+
+ // https://golang.org/pkg/os/signal/#Notify
+ // should be of buffer size at least 1
+ c := make(chan os.Signal, 1)
+ signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
+
+ for {
+ select {
+ case e := <-errCh:
+ err = multierr.Append(err, e.Error)
+ log.Printf("error occurred: %v, service: %s", e.Error.Error(), e.VertexID)
+ er := Container.Stop()
+ if er != nil {
+ err = multierr.Append(err, er)
+ return errors.E(op, err)
+ }
+ return errors.E(op, err)
+ case <-c:
+ err = Container.Stop()
+ if err != nil {
+ return errors.E(op, err)
+ }
+ return nil
+ }
+ }
+}
diff --git a/cmd/rr/cmd/version.go b/cmd/cli/version.go
index a550c682..89728bd2 100644
--- a/cmd/rr/cmd/version.go
+++ b/cmd/cli/version.go
@@ -1,9 +1,9 @@
-package cmd
+package cli
var (
// Version - defines build version.
- Version = "local"
+ Version string = "local"
// BuildTime - defined build time.
- BuildTime = "development"
+ BuildTime string = "development"
)
diff --git a/cmd/cli/workers.go b/cmd/cli/workers.go
new file mode 100644
index 00000000..03639aa4
--- /dev/null
+++ b/cmd/cli/workers.go
@@ -0,0 +1,110 @@
+package cli
+
+import (
+ "fmt"
+ "log"
+ "net/rpc"
+ "os"
+ "os/signal"
+ "syscall"
+ "time"
+
+ tm "github.com/buger/goterm"
+ "github.com/fatih/color"
+ "github.com/spf13/cobra"
+ "github.com/spiral/errors"
+ "github.com/spiral/roadrunner/v2/plugins/informer"
+ "github.com/spiral/roadrunner/v2/tools"
+)
+
+var (
+ interactive bool
+)
+
+const InformerList string = "informer.List"
+const InformerWorkers string = "informer.Workers"
+
+func init() {
+ workersCommand := &cobra.Command{
+ Use: "workers",
+ Short: "Show information about active roadrunner workers",
+ RunE: workersHandler,
+ }
+
+ workersCommand.Flags().BoolVarP(
+ &interactive,
+ "interactive",
+ "i",
+ false,
+ "render interactive workers table",
+ )
+
+ root.AddCommand(workersCommand)
+}
+
+func workersHandler(cmd *cobra.Command, args []string) error {
+ const op = errors.Op("workers cobra handler")
+ // get RPC client
+ client, err := RPCClient()
+ if err != nil {
+ return err
+ }
+ defer func() {
+ err := client.Close()
+ if err != nil {
+ log.Printf("error when closing RPCClient: error %v", err)
+ }
+ }()
+
+ var plugins []string
+ // assume user wants to show workers from particular plugin
+ if len(args) != 0 {
+ plugins = args
+ } else {
+ err = client.Call(InformerList, true, &plugins)
+ if err != nil {
+ return errors.E(op, err)
+ }
+ }
+
+ if !interactive {
+ return showWorkers(plugins, client)
+ }
+
+ // https://golang.org/pkg/os/signal/#Notify
+ // should be of buffer size at least 1
+ c := make(chan os.Signal, 1)
+ signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
+
+ tm.Clear()
+ tt := time.NewTicker(time.Second)
+ defer tt.Stop()
+ for {
+ select {
+ case <-c:
+ return nil
+ case <-tt.C:
+ tm.MoveCursor(1, 1)
+ err := showWorkers(plugins, client)
+ if err != nil {
+ return errors.E(op, err)
+ }
+ tm.Flush()
+ }
+ }
+}
+
+func showWorkers(plugins []string, client *rpc.Client) error {
+ const op = errors.Op("show workers")
+ for _, plugin := range plugins {
+ list := &informer.WorkerList{}
+ err := client.Call(InformerWorkers, plugin, &list)
+ if err != nil {
+ return errors.E(op, err)
+ }
+
+ fmt.Printf("Workers of [%s]:\n", color.HiYellowString(plugin))
+ tools.WorkerTable(os.Stdout, list.Workers).Render()
+ }
+ return nil
+}
diff --git a/cmd/main.go b/cmd/main.go
new file mode 100644
index 00000000..56422e82
--- /dev/null
+++ b/cmd/main.go
@@ -0,0 +1,58 @@
+package main
+
+import (
+ "log"
+
+ "github.com/spiral/endure"
+ "github.com/spiral/roadrunner/v2/cmd/cli"
+ "github.com/spiral/roadrunner/v2/plugins/http"
+ "github.com/spiral/roadrunner/v2/plugins/informer"
+
+ "github.com/spiral/roadrunner/v2/plugins/kv/memcached"
+ "github.com/spiral/roadrunner/v2/plugins/kv/memory"
+ "github.com/spiral/roadrunner/v2/plugins/logger"
+ "github.com/spiral/roadrunner/v2/plugins/metrics"
+ "github.com/spiral/roadrunner/v2/plugins/redis"
+ "github.com/spiral/roadrunner/v2/plugins/reload"
+ "github.com/spiral/roadrunner/v2/plugins/resetter"
+ "github.com/spiral/roadrunner/v2/plugins/rpc"
+ "github.com/spiral/roadrunner/v2/plugins/server"
+)
+
+func main() {
+ var err error
+ cli.Container, err = endure.NewContainer(nil, endure.SetLogLevel(endure.ErrorLevel), endure.RetryOnFail(false))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ err = cli.Container.RegisterAll(
+ // logger plugin
+ &logger.ZapLogger{},
+ // metrics plugin
+ &metrics.Plugin{},
+ // redis plugin (internal)
+ &redis.Plugin{},
+ // http server plugin
+ &http.Plugin{},
+ // reload plugin
+ &reload.Plugin{},
+ // informer plugin (./rr workers, ./rr workers -i)
+ &informer.Plugin{},
+ // resetter plugin (./rr reset)
+ &resetter.Plugin{},
+ // rpc plugin (workers, reset)
+ &rpc.Plugin{},
+ // server plugin (NewWorker, NewWorkerPool)
+ &server.Plugin{},
+ // memcached kv plugin
+ &memcached.Plugin{},
+ // in-memory kv plugin
+ &memory.Plugin{},
+ )
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ cli.Execute()
+}
diff --git a/cmd/rr/LICENSE b/cmd/rr/LICENSE
deleted file mode 100644
index efb98c87..00000000
--- a/cmd/rr/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2018 SpiralScout
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE. \ No newline at end of file
diff --git a/cmd/rr/cmd/root.go b/cmd/rr/cmd/root.go
deleted file mode 100644
index 13d74d25..00000000
--- a/cmd/rr/cmd/root.go
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (c) 2018 SpiralScout
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-package cmd
-
-import (
- "log"
- "net/http"
- "net/http/pprof"
- "os"
-
- "github.com/sirupsen/logrus"
- "github.com/spf13/cobra"
- "github.com/spiral/roadrunner/cmd/util"
- "github.com/spiral/roadrunner/service"
- "github.com/spiral/roadrunner/service/limit"
-)
-
-// Services bus for all the commands.
-var (
- cfgFile, workDir, logFormat string
- override []string
- mergeJson string
-
- // Verbose enables verbosity mode (container specific).
- Verbose bool
-
- // Debug enables debug mode (service specific).
- Debug bool
-
- // Logger - shared logger.
- Logger = logrus.New()
-
- // Container - shared service bus.
- Container = service.NewContainer(Logger)
-
- // CLI is application endpoint.
- CLI = &cobra.Command{
- Use: "rr",
- SilenceErrors: true,
- SilenceUsage: true,
- Version: Version, // allows to use `--version` flag
- Short: util.Sprintf(
- "<green>RoadRunner</reset>, PHP Application Server\nVersion: <yellow+hb>%s</reset>, %s",
- Version,
- BuildTime,
- ),
- }
-)
-
-// Execute adds all child commands to the CLI command and sets flags appropriately.
-// This is called by main.main(). It only needs to happen once to the CLI.
-func Execute() {
- if err := CLI.Execute(); err != nil {
- util.ExitWithError(err)
- }
-}
-
-func init() {
- CLI.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
- CLI.PersistentFlags().BoolVarP(&Debug, "debug", "d", false, "debug mode")
- CLI.PersistentFlags().StringVarP(&logFormat, "logFormat", "l", "color", "select log formatter (color, json, plain)")
- CLI.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file (default is .rr.yaml)")
- CLI.PersistentFlags().StringVarP(&workDir, "workDir", "w", "", "work directory")
- CLI.PersistentFlags().StringVarP(&mergeJson, "jsonConfig", "j", "", "merge json configuration")
-
- CLI.PersistentFlags().StringArrayVarP(
- &override,
- "override",
- "o",
- nil,
- "override config value (dot.notation=value)",
- )
-
- cobra.OnInitialize(func() {
- if Verbose {
- Logger.SetLevel(logrus.DebugLevel)
- }
-
- configureLogger(logFormat)
-
- cfg, err := util.LoadConfig(cfgFile, []string{"."}, ".rr", override, mergeJson)
- if err != nil {
- Logger.Warnf("config: %s", err)
- return
- }
-
- if workDir != "" {
- if err := os.Chdir(workDir); err != nil {
- util.ExitWithError(err)
- }
- }
-
- if err := Container.Init(cfg); err != nil {
- util.ExitWithError(err)
- }
-
- // global watcher config
- if Verbose {
- wcv, _ := Container.Get(limit.ID)
- if wcv, ok := wcv.(*limit.Service); ok {
- wcv.AddListener(func(event int, ctx interface{}) {
- util.LogEvent(Logger, event, ctx)
- })
- }
- }
-
- // if debug --> also run pprof service
- if Debug {
- go runDebugServer()
- }
- })
-}
-func runDebugServer() {
- mux := http.NewServeMux()
- mux.HandleFunc("/debug/pprof/", pprof.Index)
- mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
- mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
- mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
- mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
- srv := http.Server{
- Addr: ":6061",
- Handler: mux,
- }
-
- if err := srv.ListenAndServe(); err != nil {
- log.Fatal(err)
- }
-}
-
-func configureLogger(format string) {
- util.Colorize = false
- switch format {
- case "color", "default":
- util.Colorize = true
- Logger.Formatter = &logrus.TextFormatter{ForceColors: true}
- case "plain":
- Logger.Formatter = &logrus.TextFormatter{DisableColors: true}
- case "json":
- Logger.Formatter = &logrus.JSONFormatter{}
- }
-}
diff --git a/cmd/rr/cmd/serve.go b/cmd/rr/cmd/serve.go
deleted file mode 100644
index 70682780..00000000
--- a/cmd/rr/cmd/serve.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2018 SpiralScout
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-package cmd
-
-import (
- "os"
- "os/signal"
- "sync"
- "syscall"
-
- "github.com/spf13/cobra"
-)
-
-func init() {
- CLI.AddCommand(&cobra.Command{
- Use: "serve",
- Short: "Serve RoadRunner service(s)",
- RunE: serveHandler,
- })
-}
-
-func serveHandler(cmd *cobra.Command, args []string) error {
- // https://golang.org/pkg/os/signal/#Notify
- // should be of buffer size at least 1
- c := make(chan os.Signal, 1)
- signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
-
- wg := &sync.WaitGroup{}
-
- wg.Add(1)
- go func() {
- defer wg.Done()
- // get the signal
- <-c
- Container.Stop()
- }()
-
- // blocking operation
- if err := Container.Serve(); err != nil {
- return err
- }
-
- wg.Wait()
-
- return nil
-}
diff --git a/cmd/rr/cmd/stop.go b/cmd/rr/cmd/stop.go
deleted file mode 100644
index 7b4794e7..00000000
--- a/cmd/rr/cmd/stop.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2018 SpiralScout
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-package cmd
-
-import (
- "github.com/spf13/cobra"
- "github.com/spiral/roadrunner/cmd/util"
-)
-
-func init() {
- CLI.AddCommand(&cobra.Command{
- Use: "stop",
- Short: "Stop RoadRunner server",
- RunE: stopHandler,
- })
-}
-
-func stopHandler(cmd *cobra.Command, args []string) error {
- client, err := util.RPCClient(Container)
- if err != nil {
- return err
- }
-
- util.Printf("<green>Stopping RoadRunner</reset>: ")
-
- var r string
- if err := client.Call("system.Stop", true, &r); err != nil {
- return err
- }
-
- util.Printf("<green+hb>done</reset>\n")
- return client.Close()
-}
diff --git a/cmd/rr/http/debug.go b/cmd/rr/http/debug.go
deleted file mode 100644
index 02023e36..00000000
--- a/cmd/rr/http/debug.go
+++ /dev/null
@@ -1,139 +0,0 @@
-package http
-
-import (
- "fmt"
- "net"
- "net/http"
- "strings"
- "time"
-
- "github.com/sirupsen/logrus"
- "github.com/spf13/cobra"
- "github.com/spiral/roadrunner"
- rr "github.com/spiral/roadrunner/cmd/rr/cmd"
- "github.com/spiral/roadrunner/cmd/util"
- rrhttp "github.com/spiral/roadrunner/service/http"
-)
-
-func init() {
- cobra.OnInitialize(func() {
- if rr.Debug {
- svc, _ := rr.Container.Get(rrhttp.ID)
- if svc, ok := svc.(*rrhttp.Service); ok {
- svc.AddListener((&debugger{logger: rr.Logger}).listener)
- }
- }
- })
-}
-
-// listener provide debug callback for system events. With colors!
-type debugger struct{ logger *logrus.Logger }
-
-// listener listens to http events and generates nice looking output.
-func (s *debugger) listener(event int, ctx interface{}) {
- if util.LogEvent(s.logger, event, ctx) {
- // handler by default debug package
- return
- }
-
- // http events
- switch event {
- case rrhttp.EventResponse:
- e := ctx.(*rrhttp.ResponseEvent)
- s.logger.Info(util.Sprintf(
- "<cyan+h>%s</reset> %s %s <white+hb>%s</reset> %s",
- e.Request.RemoteAddr,
- elapsed(e.Elapsed()),
- statusColor(e.Response.Status),
- e.Request.Method,
- e.Request.URI,
- ))
-
- case rrhttp.EventError:
- e := ctx.(*rrhttp.ErrorEvent)
-
- if _, ok := e.Error.(roadrunner.JobError); ok {
- s.logger.Info(util.Sprintf(
- "<cyan+h>%s</reset> %s %s <white+hb>%s</reset> %s",
- addr(e.Request.RemoteAddr),
- elapsed(e.Elapsed()),
- statusColor(500),
- e.Request.Method,
- uri(e.Request),
- ))
- } else {
- s.logger.Info(util.Sprintf(
- "<cyan+h>%s</reset> %s %s <white+hb>%s</reset> %s <red>%s</reset>",
- addr(e.Request.RemoteAddr),
- elapsed(e.Elapsed()),
- statusColor(500),
- e.Request.Method,
- uri(e.Request),
- e.Error,
- ))
- }
- }
-}
-
-func statusColor(status int) string {
- if status < 300 {
- return util.Sprintf("<green>%v</reset>", status)
- }
-
- if status < 400 {
- return util.Sprintf("<cyan>%v</reset>", status)
- }
-
- if status < 500 {
- return util.Sprintf("<yellow>%v</reset>", status)
- }
-
- return util.Sprintf("<red>%v</reset>", status)
-}
-
-func uri(r *http.Request) string {
- if r.TLS != nil {
- return fmt.Sprintf("https://%s%s", r.Host, r.URL.String())
- }
-
- return fmt.Sprintf("http://%s%s", r.Host, r.URL.String())
-}
-
-// fits duration into 5 characters
-func elapsed(d time.Duration) string {
- var v string
- switch {
- case d > 100*time.Second:
- v = fmt.Sprintf("%.1fs", d.Seconds())
- case d > 10*time.Second:
- v = fmt.Sprintf("%.2fs", d.Seconds())
- case d > time.Second:
- v = fmt.Sprintf("%.3fs", d.Seconds())
- case d > 100*time.Millisecond:
- v = fmt.Sprintf("%.0fms", d.Seconds()*1000)
- case d > 10*time.Millisecond:
- v = fmt.Sprintf("%.1fms", d.Seconds()*1000)
- default:
- v = fmt.Sprintf("%.2fms", d.Seconds()*1000)
- }
-
- if d > time.Second {
- return util.Sprintf("<red>{%v}</reset>", v)
- }
-
- if d > time.Millisecond*500 {
- return util.Sprintf("<yellow>{%v}</reset>", v)
- }
-
- return util.Sprintf("<gray+hb>{%v}</reset>", v)
-}
-
-func addr(addr string) string {
- // otherwise, return remote address as is
- if !strings.ContainsRune(addr, ':') {
- return addr
- }
-
- addr, _, _ = net.SplitHostPort(addr)
- return addr
-}
diff --git a/cmd/rr/http/metrics.go b/cmd/rr/http/metrics.go
deleted file mode 100644
index 6aad560e..00000000
--- a/cmd/rr/http/metrics.go
+++ /dev/null
@@ -1,124 +0,0 @@
-package http
-
-import (
- "strconv"
- "time"
-
- "github.com/prometheus/client_golang/prometheus"
- "github.com/spf13/cobra"
- rr "github.com/spiral/roadrunner/cmd/rr/cmd"
- rrhttp "github.com/spiral/roadrunner/service/http"
- "github.com/spiral/roadrunner/service/metrics"
- "github.com/spiral/roadrunner/util"
-)
-
-func init() {
- cobra.OnInitialize(func() {
- svc, _ := rr.Container.Get(metrics.ID)
- mtr, ok := svc.(*metrics.Service)
- if !ok || !mtr.Enabled() {
- return
- }
-
- ht, _ := rr.Container.Get(rrhttp.ID)
- if ht, ok := ht.(*rrhttp.Service); ok {
- collector := newCollector()
-
- // register metrics
- mtr.MustRegister(collector.requestCounter)
- mtr.MustRegister(collector.requestDuration)
- mtr.MustRegister(collector.workersMemory)
-
- // collect events
- ht.AddListener(collector.listener)
-
- // update memory usage every 10 seconds
- go collector.collectMemory(ht, time.Second*10)
- }
- })
-}
-
-// listener provide debug callback for system events. With colors!
-type metricCollector struct {
- requestCounter *prometheus.CounterVec
- requestDuration *prometheus.HistogramVec
- workersMemory prometheus.Gauge
-}
-
-func newCollector() *metricCollector {
- return &metricCollector{
- requestCounter: prometheus.NewCounterVec(
- prometheus.CounterOpts{
- Name: "rr_http_request_total",
- Help: "Total number of handled http requests after server restart.",
- },
- []string{"status"},
- ),
- requestDuration: prometheus.NewHistogramVec(
- prometheus.HistogramOpts{
- Name: "rr_http_request_duration_seconds",
- Help: "HTTP request duration.",
- },
- []string{"status"},
- ),
- workersMemory: prometheus.NewGauge(
- prometheus.GaugeOpts{
- Name: "rr_http_workers_memory_bytes",
- Help: "Memory usage by HTTP workers.",
- },
- ),
- }
-}
-
-// listener listens to http events and generates nice looking output.
-func (c *metricCollector) listener(event int, ctx interface{}) {
- // http events
- switch event {
- case rrhttp.EventResponse:
- e := ctx.(*rrhttp.ResponseEvent)
-
- c.requestCounter.With(prometheus.Labels{
- "status": strconv.Itoa(e.Response.Status),
- }).Inc()
-
- c.requestDuration.With(prometheus.Labels{
- "status": strconv.Itoa(e.Response.Status),
- }).Observe(e.Elapsed().Seconds())
-
- case rrhttp.EventError:
- e := ctx.(*rrhttp.ErrorEvent)
-
- c.requestCounter.With(prometheus.Labels{
- "status": "500",
- }).Inc()
-
- c.requestDuration.With(prometheus.Labels{
- "status": "500",
- }).Observe(e.Elapsed().Seconds())
- }
-}
-
-// collect memory usage by server workers
-func (c *metricCollector) collectMemory(service *rrhttp.Service, tick time.Duration) {
- started := false
- for {
- server := service.Server()
- if server == nil && started {
- // stopped
- return
- }
-
- started = true
-
- if workers, err := util.ServerState(server); err == nil {
- sum := 0.0
- for _, w := range workers {
- sum = sum + float64(w.MemoryUsage)
- }
-
- c.workersMemory.Set(sum)
- }
-
- time.Sleep(tick)
- }
-}
diff --git a/cmd/rr/http/reset.go b/cmd/rr/http/reset.go
deleted file mode 100644
index 3008848a..00000000
--- a/cmd/rr/http/reset.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2018 SpiralScout
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-package http
-
-import (
- "github.com/spf13/cobra"
- rr "github.com/spiral/roadrunner/cmd/rr/cmd"
- "github.com/spiral/roadrunner/cmd/util"
-)
-
-func init() {
- rr.CLI.AddCommand(&cobra.Command{
- Use: "http:reset",
- Short: "Reload RoadRunner worker pool for the HTTP service",
- RunE: reloadHandler,
- })
-}
-
-func reloadHandler(cmd *cobra.Command, args []string) error {
- client, err := util.RPCClient(rr.Container)
- if err != nil {
- return err
- }
- defer client.Close()
-
- util.Printf("<green>Restarting http worker pool</reset>: ")
-
- var r string
- if err := client.Call("http.Reset", true, &r); err != nil {
- return err
- }
-
- util.Printf("<green+hb>done</reset>\n")
- return nil
-}
diff --git a/cmd/rr/http/workers.go b/cmd/rr/http/workers.go
deleted file mode 100644
index be6d4038..00000000
--- a/cmd/rr/http/workers.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2018 SpiralScout
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-package http
-
-import (
- "net/rpc"
- "os"
- "os/signal"
- "syscall"
- "time"
-
- tm "github.com/buger/goterm"
- "github.com/spf13/cobra"
- rr "github.com/spiral/roadrunner/cmd/rr/cmd"
- "github.com/spiral/roadrunner/cmd/util"
- "github.com/spiral/roadrunner/service/http"
-)
-
-var (
- interactive bool
- stopSignal = make(chan os.Signal, 1)
-)
-
-func init() {
- workersCommand := &cobra.Command{
- Use: "http:workers",
- Short: "List workers associated with RoadRunner HTTP service",
- RunE: workersHandler,
- }
-
- workersCommand.Flags().BoolVarP(
- &interactive,
- "interactive",
- "i",
- false,
- "render interactive workers table",
- )
-
- rr.CLI.AddCommand(workersCommand)
-
- signal.Notify(stopSignal, syscall.SIGTERM)
- signal.Notify(stopSignal, syscall.SIGINT)
-}
-
-func workersHandler(cmd *cobra.Command, args []string) (err error) {
- defer func() {
- if r, ok := recover().(error); ok {
- err = r
- }
- }()
-
- client, err := util.RPCClient(rr.Container)
- if err != nil {
- return err
- }
- defer client.Close()
-
- if !interactive {
- showWorkers(client)
- return nil
- }
-
- tm.Clear()
- for {
- select {
- case <-stopSignal:
- return nil
- case <-time.NewTicker(time.Millisecond * 500).C:
- tm.MoveCursor(1, 1)
- showWorkers(client)
- tm.Flush()
- }
- }
-}
-
-func showWorkers(client *rpc.Client) {
- var r http.WorkerList
- if err := client.Call("http.Workers", true, &r); err != nil {
- panic(err)
- }
-
- util.WorkerTable(r.Workers).Render()
-}
diff --git a/cmd/rr/limit/debug.go b/cmd/rr/limit/debug.go
deleted file mode 100644
index b9d919dc..00000000
--- a/cmd/rr/limit/debug.go
+++ /dev/null
@@ -1,71 +0,0 @@
-package limit
-
-import (
- "github.com/sirupsen/logrus"
- "github.com/spf13/cobra"
- "github.com/spiral/roadrunner"
- rr "github.com/spiral/roadrunner/cmd/rr/cmd"
- "github.com/spiral/roadrunner/cmd/util"
- "github.com/spiral/roadrunner/service/limit"
-)
-
-func init() {
- cobra.OnInitialize(func() {
- if rr.Debug {
- svc, _ := rr.Container.Get(limit.ID)
- if svc, ok := svc.(*limit.Service); ok {
- svc.AddListener((&debugger{logger: rr.Logger}).listener)
- }
- }
- })
-}
-
-// listener provide debug callback for system events. With colors!
-type debugger struct{ logger *logrus.Logger }
-
-// listener listens to http events and generates nice looking output.
-func (s *debugger) listener(event int, ctx interface{}) {
- if util.LogEvent(s.logger, event, ctx) {
- // handler by default debug package
- return
- }
-
- // watchers
- switch event {
- case limit.EventTTL:
- w := ctx.(roadrunner.WorkerError)
- s.logger.Debug(util.Sprintf(
- "<white+hb>worker.%v</reset> <yellow>%s</reset>",
- *w.Worker.Pid,
- w.Caused,
- ))
- return
-
- case limit.EventIdleTTL:
- w := ctx.(roadrunner.WorkerError)
- s.logger.Debug(util.Sprintf(
- "<white+hb>worker.%v</reset> <yellow>%s</reset>",
- *w.Worker.Pid,
- w.Caused,
- ))
- return
-
- case limit.EventMaxMemory:
- w := ctx.(roadrunner.WorkerError)
- s.logger.Error(util.Sprintf(
- "<white+hb>worker.%v</reset> <red>%s</reset>",
- *w.Worker.Pid,
- w.Caused,
- ))
- return
-
- case limit.EventExecTTL:
- w := ctx.(roadrunner.WorkerError)
- s.logger.Error(util.Sprintf(
- "<white+hb>worker.%v</reset> <red>%s</reset>",
- *w.Worker.Pid,
- w.Caused,
- ))
- return
- }
-}
diff --git a/cmd/rr/limit/metrics.go b/cmd/rr/limit/metrics.go
deleted file mode 100644
index 947f53fe..00000000
--- a/cmd/rr/limit/metrics.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package limit
-
-import (
- "github.com/prometheus/client_golang/prometheus"
- "github.com/spf13/cobra"
- rr "github.com/spiral/roadrunner/cmd/rr/cmd"
- rrlimit "github.com/spiral/roadrunner/service/limit"
- "github.com/spiral/roadrunner/service/metrics"
-)
-
-func init() {
- cobra.OnInitialize(func() {
- svc, _ := rr.Container.Get(metrics.ID)
- mtr, ok := svc.(*metrics.Service)
- if !ok || !mtr.Enabled() {
- return
- }
-
- ht, _ := rr.Container.Get(rrlimit.ID)
- if ht, ok := ht.(*rrlimit.Service); ok {
- collector := newCollector()
-
- // register metrics
- mtr.MustRegister(collector.maxMemory)
-
- // collect events
- ht.AddListener(collector.listener)
- }
- })
-}
-
-// listener provide debug callback for system events. With colors!
-type metricCollector struct {
- maxMemory prometheus.Counter
- maxExecutionTime prometheus.Counter
-}
-
-func newCollector() *metricCollector {
- return &metricCollector{
- maxMemory: prometheus.NewCounter(
- prometheus.CounterOpts{
- Name: "rr_limit_max_memory",
- Help: "Total number of workers that was killed because they reached max memory limit.",
- },
- ),
- maxExecutionTime: prometheus.NewCounter(
- prometheus.CounterOpts{
- Name: "rr_limit_max_execution_time",
- Help: "Total number of workers that was killed because they reached max execution time limit.",
- },
- ),
- }
-}
-
-// listener listens to http events and generates nice looking output.
-func (c *metricCollector) listener(event int, ctx interface{}) {
- switch event {
- case rrlimit.EventMaxMemory:
- c.maxMemory.Inc()
- case rrlimit.EventExecTTL:
- c.maxExecutionTime.Inc()
- }
-}
diff --git a/cmd/rr/main.go b/cmd/rr/main.go
deleted file mode 100644
index 54a1f060..00000000
--- a/cmd/rr/main.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// MIT License
-//
-// Copyright (c) 2018 SpiralScout
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-package main
-
-import (
- rr "github.com/spiral/roadrunner/cmd/rr/cmd"
-
- // services (plugins)
- "github.com/spiral/roadrunner/service/env"
- "github.com/spiral/roadrunner/service/gzip"
- "github.com/spiral/roadrunner/service/headers"
- "github.com/spiral/roadrunner/service/health"
- "github.com/spiral/roadrunner/service/http"
- "github.com/spiral/roadrunner/service/limit"
- "github.com/spiral/roadrunner/service/metrics"
- "github.com/spiral/roadrunner/service/reload"
- "github.com/spiral/roadrunner/service/rpc"
- "github.com/spiral/roadrunner/service/static"
-
- // additional commands and debug handlers
- _ "github.com/spiral/roadrunner/cmd/rr/http"
- _ "github.com/spiral/roadrunner/cmd/rr/limit"
-)
-
-func main() {
- rr.Container.Register(env.ID, &env.Service{})
- rr.Container.Register(rpc.ID, &rpc.Service{})
- rr.Container.Register(http.ID, &http.Service{})
- rr.Container.Register(metrics.ID, &metrics.Service{})
- rr.Container.Register(headers.ID, &headers.Service{})
- rr.Container.Register(static.ID, &static.Service{})
- rr.Container.Register(limit.ID, &limit.Service{})
- rr.Container.Register(health.ID, &health.Service{})
- rr.Container.Register(gzip.ID, &gzip.Service{})
- rr.Container.Register(reload.ID, &reload.Service{})
-
- // you can register additional commands using cmd.CLI
- rr.Execute()
-}
diff --git a/cmd/util/config.go b/cmd/util/config.go
deleted file mode 100644
index 674260a8..00000000
--- a/cmd/util/config.go
+++ /dev/null
@@ -1,182 +0,0 @@
-package util
-
-import (
- "bytes"
- "fmt"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/spf13/viper"
- "github.com/spiral/roadrunner/service"
-)
-
-// ConfigWrapper provides interface bridge between v configs and service.Config.
-type ConfigWrapper struct {
- v *viper.Viper
-}
-
-// Get nested config section (sub-map), returns nil if section not found.
-func (w *ConfigWrapper) Get(key string) service.Config {
- sub := w.v.Sub(key)
- if sub == nil {
- return nil
- }
-
- return &ConfigWrapper{sub}
-}
-
-// Unmarshal unmarshal config data into given struct.
-func (w *ConfigWrapper) Unmarshal(out interface{}) error {
- return w.v.Unmarshal(out)
-}
-
-// LoadConfig config and merge it's values with set of flags.
-func LoadConfig(cfgFile string, path []string, name string, flags []string, jsonConfig string) (*ConfigWrapper, error) {
- cfg := viper.New()
-
- if cfgFile != "" {
- if absPath, err := filepath.Abs(cfgFile); err == nil {
- cfgFile = absPath
-
- // force working absPath related to config file
- if err := os.Chdir(filepath.Dir(absPath)); err != nil {
- return nil, err
- }
- }
-
- // Use cfg file from the flag.
- cfg.SetConfigFile(cfgFile)
-
- if dir, err := filepath.Abs(cfgFile); err == nil {
- // force working absPath related to config file
- if err := os.Chdir(filepath.Dir(dir)); err != nil {
- return nil, err
- }
- }
- } else {
- // automatic location
- for _, p := range path {
- cfg.AddConfigPath(p)
- }
-
- cfg.SetConfigName(name)
- }
-
- // read in environment variables that match
- cfg.AutomaticEnv()
- cfg.SetEnvPrefix("rr")
- cfg.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
-
- // If a cfg file is found, read it in.
- if err := cfg.ReadInConfig(); err != nil {
- if len(flags) == 0 && jsonConfig == "" {
- return nil, err
- }
- }
-
- // merge included configs
- if include, ok := cfg.Get("include").([]interface{}); ok {
- for _, file := range include {
- filename, ok := file.(string)
- if !ok {
- continue
- }
-
- partial := viper.New()
- partial.AutomaticEnv()
- partial.SetEnvPrefix("rr")
- partial.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
- partial.SetConfigFile(filename)
-
- if err := partial.ReadInConfig(); err != nil {
- return nil, err
- }
-
- // merging
- if err := cfg.MergeConfigMap(partial.AllSettings()); err != nil {
- return nil, err
- }
- }
- }
-
- // automatically inject ENV variables using ${ENV} pattern
- for _, key := range cfg.AllKeys() {
- val := cfg.Get(key)
- cfg.Set(key, parseEnv(val))
- }
-
- // merge with console flags
- if len(flags) != 0 {
- for _, f := range flags {
- k, v, err := parseFlag(f)
- if err != nil {
- return nil, err
- }
-
- cfg.Set(k, v)
- }
- }
-
- if jsonConfig != "" {
- jConfig := viper.New()
- jConfig.AutomaticEnv()
- jConfig.SetEnvPrefix("rr")
- jConfig.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
-
- jConfig.SetConfigType("json")
- if err := jConfig.ReadConfig(bytes.NewBufferString(jsonConfig)); err != nil {
- return nil, err
- }
-
- // merging
- if err := cfg.MergeConfigMap(jConfig.AllSettings()); err != nil {
- return nil, err
- }
- }
-
- merged := viper.New()
-
- // we have to copy all the merged values into new config in order normalize it (viper bug?)
- if err := merged.MergeConfigMap(cfg.AllSettings()); err != nil {
- return nil, err
- }
-
- return &ConfigWrapper{merged}, nil
-}
-
-func parseFlag(flag string) (string, string, error) {
- if !strings.Contains(flag, "=") {
- return "", "", fmt.Errorf("invalid flag `%s`", flag)
- }
-
- parts := strings.SplitN(strings.TrimLeft(flag, " \"'`"), "=", 2)
-
- return strings.Trim(parts[0], " \n\t"), parseValue(strings.Trim(parts[1], " \n\t")), nil
-}
-
-func parseValue(value string) string {
- escape := []rune(value)[0]
-
- if escape == '"' || escape == '\'' || escape == '`' {
- value = strings.Trim(value, string(escape))
- value = strings.Replace(value, fmt.Sprintf("\\%s", string(escape)), string(escape), -1)
- }
-
- return value
-}
-
-func parseEnv(value interface{}) interface{} {
- str, ok := value.(string)
- if !ok || len(str) <= 3 {
- return value
- }
-
- if str[0:2] == "${" && str[len(str)-1:] == "}" {
- if v, ok := os.LookupEnv(str[2 : len(str)-1]); ok {
- return v
- }
- }
-
- return str
-}
diff --git a/cmd/util/cprint.go b/cmd/util/cprint.go
deleted file mode 100644
index 37cb0bc5..00000000
--- a/cmd/util/cprint.go
+++ /dev/null
@@ -1,48 +0,0 @@
-package util
-
-import (
- "fmt"
- "os"
- "regexp"
- "strings"
-
- "github.com/mgutz/ansi"
-)
-
-var (
- reg *regexp.Regexp
-
- // Colorize enables colors support.
- Colorize = true
-)
-
-func init() {
- reg, _ = regexp.Compile(`<([^>]+)>`)
-}
-
-// Printf works identically to fmt.Print but adds `<white+hb>color formatting support for CLI</reset>`.
-func Printf(format string, args ...interface{}) {
- fmt.Print(Sprintf(format, args...))
-}
-
-// Sprintf works identically to fmt.Sprintf but adds `<white+hb>color formatting support for CLI</reset>`.
-func Sprintf(format string, args ...interface{}) string {
- format = reg.ReplaceAllStringFunc(format, func(s string) string {
- if !Colorize {
- return ""
- }
-
- return ansi.ColorCode(strings.Trim(s, "<>/"))
- })
-
- return fmt.Sprintf(format, args...)
-}
-
-// Panicf prints `<white+hb>color formatted message to STDERR</reset>`.
-func Panicf(format string, args ...interface{}) error {
- _, err := fmt.Fprint(os.Stderr, Sprintf(format, args...))
- if err != nil {
- return err
- }
- return nil
-}
diff --git a/cmd/util/debug.go b/cmd/util/debug.go
deleted file mode 100644
index c5cf68bb..00000000
--- a/cmd/util/debug.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package util
-
-import (
- "strings"
-
- "github.com/sirupsen/logrus"
- "github.com/spiral/roadrunner"
-)
-
-// LogEvent outputs rr event into given logger and return false if event was not handled.
-func LogEvent(logger *logrus.Logger, event int, ctx interface{}) bool {
- switch event {
- case roadrunner.EventWorkerKill:
- w := ctx.(*roadrunner.Worker)
- logger.Warning(Sprintf(
- "<white+hb>worker.%v</reset> <yellow>killed</reset>",
- *w.Pid,
- ))
- return true
- case roadrunner.EventWorkerError:
- err := ctx.(roadrunner.WorkerError)
- logger.Error(Sprintf(
- "<white+hb>worker.%v</reset> <red>%s</reset>",
- *err.Worker.Pid,
- err.Caused,
- ))
- return true
- }
-
- // outputs
- switch event {
- case roadrunner.EventStderrOutput:
- for _, line := range strings.Split(string(ctx.([]byte)), "\n") {
- if line == "" {
- continue
- }
-
- logger.Warning(strings.Trim(line, "\r\n"))
- }
-
- return true
- }
-
- // rr server events
- switch event {
- case roadrunner.EventServerFailure:
- logger.Error(Sprintf("<red>server is dead</reset>"))
- return true
- }
-
- // pool events
- switch event {
- case roadrunner.EventPoolConstruct:
- logger.Debug(Sprintf("<cyan>new worker pool</reset>"))
- return true
- case roadrunner.EventPoolError:
- logger.Error(Sprintf("<red>%s</reset>", ctx))
- return true
- }
-
- return false
-}
diff --git a/cmd/util/exit.go b/cmd/util/exit.go
deleted file mode 100644
index 8871a483..00000000
--- a/cmd/util/exit.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package util
-
-import (
- "os"
-)
-
-// ExitWithError prints error and exits with error code`.
-func ExitWithError(err error) {
- errP := Panicf("<red+hb>Error:</reset> <red>%s</reset>\n", err)
- if errP != nil {
- // in case of error during Panicf, print this error via build-int print function
- println("error occurred during fmt.Fprint: " + err.Error())
- }
- os.Exit(1)
-}
diff --git a/cmd/util/rpc.go b/cmd/util/rpc.go
deleted file mode 100644
index cb88943e..00000000
--- a/cmd/util/rpc.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package util
-
-import (
- "errors"
- "net/rpc"
-
- "github.com/spiral/roadrunner/service"
- rrpc "github.com/spiral/roadrunner/service/rpc"
-)
-
-// RPCClient returns RPC client associated with given rr service container.
-func RPCClient(container service.Container) (*rpc.Client, error) {
- svc, st := container.Get(rrpc.ID)
- if st < service.StatusOK {
- return nil, errors.New("RPC service is not configured")
- }
-
- return svc.(*rrpc.Service).Client()
-}
diff --git a/cmd/util/table.go b/cmd/util/table.go
deleted file mode 100644
index 4f76be2c..00000000
--- a/cmd/util/table.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package util
-
-import (
- "os"
- "strconv"
- "time"
-
- "github.com/dustin/go-humanize"
- "github.com/olekukonko/tablewriter"
- rrutil "github.com/spiral/roadrunner/util"
-)
-
-// WorkerTable renders table with information about rr server workers.
-func WorkerTable(workers []*rrutil.State) *tablewriter.Table {
- tw := tablewriter.NewWriter(os.Stdout)
- tw.SetHeader([]string{"PID", "Status", "Execs", "Memory", "Created"})
- tw.SetColMinWidth(0, 7)
- tw.SetColMinWidth(1, 9)
- tw.SetColMinWidth(2, 7)
- tw.SetColMinWidth(3, 7)
- tw.SetColMinWidth(4, 18)
-
- for _, w := range workers {
- tw.Append([]string{
- strconv.Itoa(w.Pid),
- renderStatus(w.Status),
- renderJobs(w.NumJobs),
- humanize.Bytes(w.MemoryUsage),
- renderAlive(time.Unix(0, w.Created)),
- })
- }
-
- return tw
-}
-
-func renderStatus(status string) string {
- switch status {
- case "inactive":
- return Sprintf("<yellow>inactive</reset>")
- case "ready":
- return Sprintf("<cyan>ready</reset>")
- case "working":
- return Sprintf("<green>working</reset>")
- case "invalid":
- return Sprintf("<yellow>invalid</reset>")
- case "stopped":
- return Sprintf("<red>stopped</reset>")
- case "errored":
- return Sprintf("<red>errored</reset>")
- }
-
- return status
-}
-
-func renderJobs(number int64) string {
- return humanize.Comma(int64(number))
-}
-
-func renderAlive(t time.Time) string {
- return humanize.RelTime(t, time.Now(), "ago", "")
-}