summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorValery Piashchynski <[email protected]>2022-05-31 13:56:34 +0200
committerValery Piashchynski <[email protected]>2022-05-31 13:56:34 +0200
commit467e427bf67bffe3dd0df41842dad797b93f56f9 (patch)
tree4c2fb253c753738674f9df73e1e4426d6b4a9b5f /internal
parentd35e5087b0dd4be258d78587ead9e12baf89c760 (diff)
feat: `rr stop` command
Signed-off-by: Valery Piashchynski <[email protected]>
Diffstat (limited to 'internal')
-rw-r--r--internal/cli/root.go64
-rw-r--r--internal/cli/serve/command.go2
-rw-r--r--internal/cli/stop/command.go53
-rw-r--r--internal/cli/stop/command_test.go27
4 files changed, 125 insertions, 21 deletions
diff --git a/internal/cli/root.go b/internal/cli/root.go
index 50f93795..0ea12814 100644
--- a/internal/cli/root.go
+++ b/internal/cli/root.go
@@ -5,10 +5,12 @@ import (
"os"
"path/filepath"
"runtime"
+ "strconv"
"github.com/roadrunner-server/errors"
"github.com/roadrunner-server/roadrunner/v2/internal/cli/reset"
"github.com/roadrunner-server/roadrunner/v2/internal/cli/serve"
+ "github.com/roadrunner-server/roadrunner/v2/internal/cli/stop"
"github.com/roadrunner-server/roadrunner/v2/internal/cli/workers"
dbg "github.com/roadrunner-server/roadrunner/v2/internal/debug"
"github.com/roadrunner-server/roadrunner/v2/internal/meta"
@@ -17,21 +19,29 @@ import (
"github.com/spf13/cobra"
)
-// NewCommand creates root command.
-func NewCommand(cmdName string) *cobra.Command { //nolint:funlen
- const (
- envDotenv string = "DOTENV_PATH" // env var name: path to the .env file
- )
+const (
+ // env var name: path to the .env file
+ envDotenv string = "DOTENV_PATH"
+ pidFileName string = ".pid"
+)
- var ( // flag values
- cfgFile = strPtr("") // path to the .rr.yaml
- workDir string // working directory
- dotenv string // path to the .env file
- debug bool // debug mode
- override = &[]string{} // override config values
- // do not print startup message
- silent = boolPtr(false)
- )
+// NewCommand creates root command.
+func NewCommand(cmdName string) *cobra.Command { //nolint:funlen,gocognit
+ // path to the .rr.yaml
+ cfgFile := toPtr("")
+ // pidfile path
+ pidFile := toPtr(false)
+ // override config values
+ override := &[]string{}
+ // do not print startup message
+ silent := toPtr(false)
+
+ // working directory
+ var workDir string
+ // path to the .env file
+ var dotenv string
+ // debug mode
+ var debug bool
cmd := &cobra.Command{
Use: cmdName,
@@ -81,12 +91,29 @@ func NewCommand(cmdName string) *cobra.Command { //nolint:funlen
go func() { _ = srv.Start(":6061") }() // TODO implement graceful server stopping
}
+ // user wanted to write a .pid file
+ if *pidFile {
+ f, err := os.Create(pidFileName)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ _ = f.Close()
+ }()
+
+ _, err = f.WriteString(strconv.Itoa(os.Getpid()))
+ if err != nil {
+ return err
+ }
+ }
+
return nil
},
}
f := cmd.PersistentFlags()
+ f.BoolVarP(pidFile, "pid", "p", false, "create a .pid file")
f.StringVarP(cfgFile, "config", "c", ".rr.yaml", "config file")
f.StringVarP(&workDir, "WorkDir", "w", "", "working directory")
f.StringVarP(&dotenv, "dotenv", "", "", fmt.Sprintf("dotenv file [$%s]", envDotenv))
@@ -98,15 +125,12 @@ func NewCommand(cmdName string) *cobra.Command { //nolint:funlen
workers.NewCommand(cfgFile, override),
reset.NewCommand(cfgFile, override, silent),
serve.NewCommand(override, cfgFile, silent),
+ stop.NewCommand(silent),
)
return cmd
}
-func strPtr(s string) *string {
- return &s
-}
-
-func boolPtr(b bool) *bool {
- return &b
+func toPtr[T any](val T) *T {
+ return &val
}
diff --git a/internal/cli/serve/command.go b/internal/cli/serve/command.go
index 3a1e945c..6cbdef44 100644
--- a/internal/cli/serve/command.go
+++ b/internal/cli/serve/command.go
@@ -98,7 +98,7 @@ func NewCommand(override *[]string, cfgFile *string, silent *bool) *cobra.Comman
case e := <-errCh:
return fmt.Errorf("error: %w\nplugin: %s", e.Error, e.VertexID)
case <-stop: // stop the container after first signal
- fmt.Printf("stop signal received, grace timeout is: %f seconds\n", containerCfg.GracePeriod.Seconds())
+ fmt.Printf("stop signal received, grace timeout is: %0.f seconds\n", containerCfg.GracePeriod.Seconds())
if err = endureContainer.Stop(); err != nil {
return fmt.Errorf("error: %w", err)
diff --git a/internal/cli/stop/command.go b/internal/cli/stop/command.go
new file mode 100644
index 00000000..8b4b589f
--- /dev/null
+++ b/internal/cli/stop/command.go
@@ -0,0 +1,53 @@
+package stop
+
+import (
+ "log"
+ "os"
+ "strconv"
+ "syscall"
+
+ "github.com/roadrunner-server/errors"
+ "github.com/spf13/cobra"
+)
+
+const (
+ // sync with root.go
+ pidFileName string = ".pid"
+)
+
+// NewCommand creates `serve` command.
+func NewCommand(silent *bool) *cobra.Command {
+ return &cobra.Command{
+ Use: "stop",
+ Short: "Stop RoadRunner server",
+ RunE: func(*cobra.Command, []string) error {
+ const op = errors.Op("rr_stop")
+
+ data, err := os.ReadFile(pidFileName)
+ if err != nil {
+ return errors.Errorf("%v, to create a .pid file, you must run RR with the following options: './rr serve -p'", err)
+ }
+
+ pid, err := strconv.Atoi(string(data))
+ if err != nil {
+ return errors.E(op, err)
+ }
+
+ process, err := os.FindProcess(pid)
+ if err != nil {
+ return errors.E(op, err)
+ }
+
+ if !*silent {
+ log.Printf("stopping process with PID: %d", pid)
+ }
+
+ err = process.Signal(syscall.SIGTERM)
+ if err != nil {
+ return errors.E(op, err)
+ }
+
+ return nil
+ },
+ }
+}
diff --git a/internal/cli/stop/command_test.go b/internal/cli/stop/command_test.go
new file mode 100644
index 00000000..8bbb29ea
--- /dev/null
+++ b/internal/cli/stop/command_test.go
@@ -0,0 +1,27 @@
+package stop_test
+
+import (
+ "testing"
+
+ "github.com/roadrunner-server/roadrunner/v2/internal/cli/stop"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestCommandProperties(t *testing.T) {
+ cmd := stop.NewCommand(toPtr(false))
+
+ assert.Equal(t, "stop", cmd.Use)
+ assert.NotNil(t, cmd.RunE)
+}
+
+func TestCommandTrue(t *testing.T) {
+ cmd := stop.NewCommand(toPtr(true))
+
+ assert.Equal(t, "stop", cmd.Use)
+ assert.NotNil(t, cmd.RunE)
+}
+
+func toPtr[T any](val T) *T {
+ return &val
+}