summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/linux.yml15
-rw-r--r--.github/workflows/windows.yml15
-rw-r--r--CHANGELOG.md12
-rwxr-xr-xMakefile2
-rw-r--r--go.mod3
-rw-r--r--go.sum4
-rw-r--r--plugins/server/command.go33
-rw-r--r--plugins/server/command_test.go43
-rw-r--r--plugins/server/plugin.go19
-rw-r--r--tests/plugins/gzip/configs/.rr-http-middlewareNotExist.yaml6
-rw-r--r--tests/plugins/gzip/plugin_test.go1
-rw-r--r--tests/plugins/metrics/metrics_test.go1
-rw-r--r--tests/plugins/reload/reload_plugin_test.go7
-rw-r--r--tests/plugins/server/configs/.rr.yaml2
-rw-r--r--tests/plugins/server/plugin_pipes.go2
-rw-r--r--tests/plugins/server/server_plugin_test.go21
16 files changed, 145 insertions, 41 deletions
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 041e6b6e..3b3f7e9f 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -1,6 +1,18 @@
name: Linux
-on: [ push, pull_request ]
+on:
+ push:
+ branches:
+ - master
+ - beta
+ - stable
+ tags-ignore:
+ - '**'
+ paths-ignore:
+ - '**.md'
+ pull_request:
+ paths-ignore:
+ - '**.md'
jobs:
golang:
@@ -63,6 +75,7 @@ jobs:
go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage-ci/bst.txt -covermode=atomic ./pkg/bst
go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage-ci/worker_stack.txt -covermode=atomic ./pkg/worker_watcher
go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage-ci/http_config.txt -covermode=atomic ./plugins/http/config
+ go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage-ci/server_cmd.txt -covermode=atomic ./plugins/server
go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage-ci/http.txt -covermode=atomic ./tests/plugins/http
go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage-ci/informer.txt -covermode=atomic ./tests/plugins/informer
go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage-ci/reload.txt -covermode=atomic ./tests/plugins/reload
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 759137b5..92d76d2c 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -1,6 +1,18 @@
name: Windows
-on: [ push, pull_request ]
+on:
+ push:
+ branches:
+ - master
+ - beta
+ - stable
+ tags-ignore:
+ - '**'
+ paths-ignore:
+ - '**.md'
+ pull_request:
+ paths-ignore:
+ - '**.md'
jobs:
golang:
@@ -63,6 +75,7 @@ jobs:
go test -v -race ./pkg/bst
go test -v -race ./pkg/worker_watcher
go test -v -race ./plugins/http/config
+ go test -v -race ./plugins/server
go test -v -race ./tests/plugins/http
go test -v -race ./tests/plugins/informer
go test -v -race ./tests/plugins/reload
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6f4eb607..3584f9f0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,13 +8,13 @@ v2.3.0 (08.06.2021)
- ✏️ Brand new `broadcast` plugin now has the name - `websockets` with broadcast capabilities. It can handle hundreds of
thousands websocket connections very efficiently (~300k messages per second with 1k connected clients, in-memory bus
- on 2CPU cores and 1GB of RAM)
-- ✏️ Protobuf binary messages for the `websockets` RPC calls under the hood.
-- ✏️ Json-schemas for the config file v1.0 (it also registered
- in [schemastore.org](https://github.com/SchemaStore/schemastore/pull/1614))
+ on 2CPU cores and 1GB of RAM) [Issue](https://github.com/spiral/roadrunner/issues/513)
+- ✏️ Protobuf binary messages for the `websockets` RPC calls under the hood. [Issue](https://github.com/spiral/roadrunner/issues/711)
+- ✏️ Json-schemas for the config file v1.0 (it also registered in [schemastore.org](https://github.com/SchemaStore/schemastore/pull/1614))
- ✏️ `latest` docker image tag supported now (but we strongly recommend using a versioned tag (like `0.2.3`) instead)
-- ✏️ Add new option to the `http` config section: `internal_error_code` to override default (500) internal error code.
-- ✏️ Expose HTTP plugin metrics (workers memory, requests count, requests duration).
+- ✏️ Add new option to the `http` config section: `internal_error_code` to override default (500) internal error code. [Issue](https://github.com/spiral/roadrunner/issues/659)
+- ✏️ Expose HTTP plugin metrics (workers memory, requests count, requests duration). [Issue](https://github.com/spiral/roadrunner/issues/489)
+- ✏️ Scan `server.command` and find errors related to the wrong path to a `PHP` file, or `.ph`, `.sh` scripts. [Issue](https://github.com/spiral/roadrunner/issues/658)
## 🩹 Fixes:
diff --git a/Makefile b/Makefile
index 9cd0531d..431cb017 100755
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,7 @@ test_coverage:
go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage/bst.out -covermode=atomic ./pkg/bst
go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage/http.out -covermode=atomic ./tests/plugins/http
go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage/http_config.out -covermode=atomic ./plugins/http/config
+ go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage/server_cmd.out -covermode=atomic ./plugins/server
go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage/informer.out -covermode=atomic ./tests/plugins/informer
go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage/reload.out -covermode=atomic ./tests/plugins/reload
go test -v -race -cover -tags=debug -coverpkg=./... -coverprofile=./coverage/server.out -covermode=atomic ./tests/plugins/server
@@ -44,6 +45,7 @@ test: ## Run application tests
go test -v -race -tags=debug ./pkg/bst
go test -v -race -tags=debug ./tests/plugins/http
go test -v -race -tags=debug ./plugins/http/config
+ go test -v -race -tags=debug ./plugins/server
go test -v -race -tags=debug ./tests/plugins/informer
go test -v -race -tags=debug ./tests/plugins/reload
go test -v -race -tags=debug ./tests/plugins/server
diff --git a/go.mod b/go.mod
index 0b8661c0..026a7d7d 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,6 @@ require (
github.com/go-redis/redis/v8 v8.9.0
github.com/gofiber/fiber/v2 v2.10.0
github.com/golang/mock v1.4.4
- github.com/golang/protobuf v1.4.3
github.com/google/uuid v1.2.0
github.com/json-iterator/go v1.1.11
github.com/klauspost/compress v1.13.0
@@ -22,7 +21,7 @@ require (
github.com/spf13/viper v1.7.1
// SPIRAL ====
github.com/spiral/endure v1.0.1
- github.com/spiral/errors v1.0.10
+ github.com/spiral/errors v1.0.11
github.com/spiral/goridge/v3 v3.0.1
// ===========
github.com/stretchr/testify v1.7.0
diff --git a/go.sum b/go.sum
index f0b99003..3b4461a2 100644
--- a/go.sum
+++ b/go.sum
@@ -387,8 +387,8 @@ github.com/spiral/endure v1.0.1 h1:JHXHHPDiet5Cfx8i2KiC+ayqACmK5Sw0fxNE/QpIuWM=
github.com/spiral/endure v1.0.1/go.mod h1:+gB0/jI9tXdHgv0x4P9vXLER8fLgwt9a7aPi0QZeJHE=
github.com/spiral/errors v1.0.5/go.mod h1:SwMSZVdZkkJVgXNNafccqOaxWg0XPzVU/dEdUEInE0o=
github.com/spiral/errors v1.0.9/go.mod h1:SwMSZVdZkkJVgXNNafccqOaxWg0XPzVU/dEdUEInE0o=
-github.com/spiral/errors v1.0.10 h1:pmntzYn0iXZTQ/2OQRYDRR/x/SQWpPk/tQ6GflmbK5E=
-github.com/spiral/errors v1.0.10/go.mod h1:SwMSZVdZkkJVgXNNafccqOaxWg0XPzVU/dEdUEInE0o=
+github.com/spiral/errors v1.0.11 h1:TGG+t3mNouLuRW54Ph7nHo4X3u4WhbxqEQmnIybi7Go=
+github.com/spiral/errors v1.0.11/go.mod h1:SwMSZVdZkkJVgXNNafccqOaxWg0XPzVU/dEdUEInE0o=
github.com/spiral/goridge/v3 v3.0.1 h1:mWo6hVEDJV3nRwsszx9y262CtrLQNojbONF4ikvKCBg=
github.com/spiral/goridge/v3 v3.0.1/go.mod h1:rYfsBwigGneLgYJTIh5urotnH63I5O+p6ZcVq7xc1lY=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
diff --git a/plugins/server/command.go b/plugins/server/command.go
new file mode 100644
index 00000000..e0b61896
--- /dev/null
+++ b/plugins/server/command.go
@@ -0,0 +1,33 @@
+package server
+
+import (
+ "os"
+ "regexp"
+
+ "github.com/spiral/errors"
+)
+
+// pattern for the path finding
+const pattern string = `^\/*([A-z/.:-]+\.(php|sh|ph))$`
+
+func (server *Plugin) scanCommand(cmd []string) error {
+ const op = errors.Op("server_command_scan")
+ r, err := regexp.Compile(pattern)
+ if err != nil {
+ return err
+ }
+
+ for i := 0; i < len(cmd); i++ {
+ if r.MatchString(cmd[i]) {
+ // try to stat
+ _, err := os.Stat(cmd[i])
+ if err != nil {
+ return errors.E(op, errors.FileNotFound, err)
+ }
+
+ // stat successful
+ return nil
+ }
+ }
+ return errors.E(errors.Str("scan failed, possible path not found"), op)
+}
diff --git a/plugins/server/command_test.go b/plugins/server/command_test.go
new file mode 100644
index 00000000..74762ccd
--- /dev/null
+++ b/plugins/server/command_test.go
@@ -0,0 +1,43 @@
+package server
+
+import (
+ "strings"
+ "testing"
+
+ "github.com/spiral/errors"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestServerCommandChecker(t *testing.T) {
+ s := &Plugin{}
+ cmd1 := "php ../../tests/client.php"
+ assert.NoError(t, s.scanCommand(strings.Split(cmd1, " ")))
+
+ cmd2 := "C:/../../abcdef/client.php"
+ assert.Error(t, s.scanCommand(strings.Split(cmd2, " ")))
+
+ cmd3 := "sh ./script.sh"
+ err := s.scanCommand(strings.Split(cmd3, " "))
+ assert.Error(t, err)
+ if !errors.Is(errors.FileNotFound, err) {
+ t.Fatal("should be of filenotfound type")
+ }
+
+ cmd4 := "php ../../tests/client.php --option1 --option2"
+ err = s.scanCommand(strings.Split(cmd4, " "))
+ assert.NoError(t, err)
+
+ cmd5 := "php ../../tests/cluent.php --option1 --option2"
+ err = s.scanCommand(strings.Split(cmd5, " "))
+ assert.Error(t, err)
+ if !errors.Is(errors.FileNotFound, err) {
+ t.Fatal("should be of filenotfound type")
+ }
+
+ cmd6 := "php 0/../../tests/cluent.php --option1 --option2"
+ err = s.scanCommand(strings.Split(cmd6, " "))
+ assert.Error(t, err)
+ if errors.Is(errors.FileNotFound, err) {
+ t.Fatal("should be of filenotfound type")
+ }
+}
diff --git a/plugins/server/plugin.go b/plugins/server/plugin.go
index 7f694f3c..00639f43 100644
--- a/plugins/server/plugin.go
+++ b/plugins/server/plugin.go
@@ -24,10 +24,11 @@ import (
// PluginName for the server
const PluginName = "server"
-// RR_RELAY env variable key (internal)
-const RR_RELAY = "RR_RELAY" //nolint:stylecheck
-// RR_RPC env variable key (internal) if the RPC presents
-const RR_RPC = "RR_RPC" //nolint:stylecheck
+// RrRelay env variable key (internal)
+const RrRelay = "RR_RELAY"
+
+// RrRPC env variable key (internal) if the RPC presents
+const RrRPC = "RR_RPC"
// Plugin manages worker
type Plugin struct {
@@ -93,6 +94,12 @@ func (server *Plugin) CmdFactory(env Env) (func() *exec.Cmd, error) {
return nil, errors.E(op, errors.Str("minimum command should be `<executable> <script>"))
}
+ // try to find a path here
+ err := server.scanCommand(cmdArgs)
+ if err != nil {
+ server.log.Info("scan command", "error", err)
+ }
+
return func() *exec.Cmd {
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) //nolint:gosec
utils.IsolateProcess(cmd)
@@ -183,13 +190,13 @@ func (server *Plugin) initFactory() (transport.Factory, error) {
}
func (server *Plugin) setEnv(e Env) []string {
- env := append(os.Environ(), fmt.Sprintf(RR_RELAY+"=%s", server.cfg.Server.Relay))
+ env := append(os.Environ(), fmt.Sprintf(RrRelay+"=%s", server.cfg.Server.Relay))
for k, v := range e {
env = append(env, fmt.Sprintf("%s=%s", strings.ToUpper(k), v))
}
if server.cfg.RPC != nil && server.cfg.RPC.Listen != "" {
- env = append(env, fmt.Sprintf("%s=%s", RR_RPC, server.cfg.RPC.Listen))
+ env = append(env, fmt.Sprintf("%s=%s", RrRPC, server.cfg.RPC.Listen))
}
// set env variables from the config
diff --git a/tests/plugins/gzip/configs/.rr-http-middlewareNotExist.yaml b/tests/plugins/gzip/configs/.rr-http-middlewareNotExist.yaml
index 9e5b9c60..73e4f6e6 100644
--- a/tests/plugins/gzip/configs/.rr-http-middlewareNotExist.yaml
+++ b/tests/plugins/gzip/configs/.rr-http-middlewareNotExist.yaml
@@ -1,9 +1,5 @@
server:
command: "php ../../psr-worker.php"
- user: ""
- group: ""
- env:
- "RR_HTTP": "true"
relay: "pipes"
relay_timeout: "20s"
@@ -21,4 +17,4 @@ http:
destroy_timeout: 60s
logs:
mode: development
- level: error \ No newline at end of file
+ level: error
diff --git a/tests/plugins/gzip/plugin_test.go b/tests/plugins/gzip/plugin_test.go
index 844fd411..b254fad5 100644
--- a/tests/plugins/gzip/plugin_test.go
+++ b/tests/plugins/gzip/plugin_test.go
@@ -120,6 +120,7 @@ func TestMiddlewareNotExist(t *testing.T) {
mockLogger.EXPECT().Warn("requested middleware does not exist", "requested", "foo").AnyTimes()
mockLogger.EXPECT().Debug("worker constructed", "pid", gomock.Any()).AnyTimes()
mockLogger.EXPECT().Debug("worker destructed", "pid", gomock.Any()).AnyTimes()
+ mockLogger.EXPECT().Info("scan command", gomock.Any()).Times(1)
mockLogger.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() // placeholder for the workerlogerror
err = cont.RegisterAll(
diff --git a/tests/plugins/metrics/metrics_test.go b/tests/plugins/metrics/metrics_test.go
index 84c60592..3d900fcc 100644
--- a/tests/plugins/metrics/metrics_test.go
+++ b/tests/plugins/metrics/metrics_test.go
@@ -136,6 +136,7 @@ func TestMetricsIssue571(t *testing.T) {
mockLogger.EXPECT().Info("metric successfully added", "name", "test", "labels", []string{}, "value", gomock.Any()).MinTimes(1)
mockLogger.EXPECT().Info("adding metric", "name", "test", "value", gomock.Any(), "labels", []string{}).MinTimes(1)
mockLogger.EXPECT().Error("metric with provided name already exist", "name", "test", "type", gomock.Any(), "namespace", gomock.Any()).MinTimes(3)
+ mockLogger.EXPECT().Info("scan command", gomock.Any()).AnyTimes()
err = cont.RegisterAll(
cfg,
diff --git a/tests/plugins/reload/reload_plugin_test.go b/tests/plugins/reload/reload_plugin_test.go
index 6db7b6d0..04c9849f 100644
--- a/tests/plugins/reload/reload_plugin_test.go
+++ b/tests/plugins/reload/reload_plugin_test.go
@@ -53,6 +53,7 @@ func TestReloadInit(t *testing.T) {
mockLogger.EXPECT().Debug("file was created", "path", gomock.Any(), "name", "file.txt", "size", gomock.Any()).Times(2)
mockLogger.EXPECT().Debug("file was added to watcher", "path", gomock.Any(), "name", "file.txt", "size", gomock.Any()).Times(2)
mockLogger.EXPECT().Info("HTTP plugin got restart request. Restarting...").Times(1)
+ mockLogger.EXPECT().Info("scan command", gomock.Any()).Times(1)
mockLogger.EXPECT().Info("HTTP workers Pool successfully restarted").Times(1)
mockLogger.EXPECT().Info("HTTP handler listeners successfully re-added").Times(1)
mockLogger.EXPECT().Info("HTTP plugin successfully restarted").Times(1)
@@ -150,6 +151,7 @@ func TestReloadHugeNumberOfFiles(t *testing.T) {
mockLogger.EXPECT().Debug("file was added to watcher", "path", gomock.Any(), "name", gomock.Any(), "size", gomock.Any()).MinTimes(1)
mockLogger.EXPECT().Info("HTTP plugin got restart request. Restarting...").MinTimes(1)
mockLogger.EXPECT().Info("HTTP workers Pool successfully restarted").MinTimes(1)
+ mockLogger.EXPECT().Info("scan command", gomock.Any()).Times(1)
mockLogger.EXPECT().Info("HTTP handler listeners successfully re-added").MinTimes(1)
mockLogger.EXPECT().Info("HTTP plugin successfully restarted").MinTimes(1)
mockLogger.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() // placeholder for the workerlogerror
@@ -259,6 +261,7 @@ func TestReloadFilterFileExt(t *testing.T) {
mockLogger.EXPECT().Debug("file added to the list of removed files", "path", gomock.Any(), "name", gomock.Any(), "size", gomock.Any()).AnyTimes()
mockLogger.EXPECT().Info("HTTP plugin got restart request. Restarting...").Times(1)
mockLogger.EXPECT().Info("HTTP workers Pool successfully restarted").Times(1)
+ mockLogger.EXPECT().Info("scan command", gomock.Any()).AnyTimes()
mockLogger.EXPECT().Info("HTTP handler listeners successfully re-added").MinTimes(1)
mockLogger.EXPECT().Info("HTTP plugin successfully restarted").Times(1)
mockLogger.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() // placeholder for the workerlogerror
@@ -387,7 +390,8 @@ func TestReloadCopy100(t *testing.T) {
mockLogger.EXPECT().Debug("file added to the list of removed files", "path", gomock.Any(), "name", gomock.Any(), "size", gomock.Any()).MinTimes(50)
mockLogger.EXPECT().Debug("file was removed from watcher", "path", gomock.Any(), "name", gomock.Any(), "size", gomock.Any()).MinTimes(50)
mockLogger.EXPECT().Debug("file was updated", "path", gomock.Any(), "name", gomock.Any(), "size", gomock.Any()).MinTimes(50)
- mockLogger.EXPECT().Info("HTTP plugin got restart request. Restarting...").MinTimes(1)
+ mockLogger.EXPECT().Info("HTTP plugin got restart request. Restarting...").AnyTimes()
+ mockLogger.EXPECT().Info("scan command", gomock.Any()).Times(1)
mockLogger.EXPECT().Info("HTTP workers Pool successfully restarted").MinTimes(1)
mockLogger.EXPECT().Info("HTTP handler listeners successfully re-added").MinTimes(1)
mockLogger.EXPECT().Info("HTTP plugin successfully restarted").MinTimes(1)
@@ -668,6 +672,7 @@ func TestReloadNoRecursion(t *testing.T) {
mockLogger.EXPECT().Debug("worker constructed", "pid", gomock.Any()).MinTimes(1)
mockLogger.EXPECT().Debug("http handler response received", "elapsed", gomock.Any(), "remote address", "127.0.0.1").Times(1)
mockLogger.EXPECT().Debug("file added to the list of removed files", "path", gomock.Any(), "name", gomock.Any(), "size", gomock.Any()).MinTimes(1)
+ mockLogger.EXPECT().Info("scan command", gomock.Any()).Times(1)
mockLogger.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() // placeholder for the workerlogerror
err = cont.RegisterAll(
diff --git a/tests/plugins/server/configs/.rr.yaml b/tests/plugins/server/configs/.rr.yaml
index d28265d5..a1484c02 100644
--- a/tests/plugins/server/configs/.rr.yaml
+++ b/tests/plugins/server/configs/.rr.yaml
@@ -9,4 +9,4 @@ server:
relay_timeout: "20s"
logs:
mode: development
- level: error
+ level: info
diff --git a/tests/plugins/server/plugin_pipes.go b/tests/plugins/server/plugin_pipes.go
index af34b4d3..f1c13734 100644
--- a/tests/plugins/server/plugin_pipes.go
+++ b/tests/plugins/server/plugin_pipes.go
@@ -67,7 +67,7 @@ func (f *Foo) Serve() chan error {
return errCh
}
if cmd == nil {
- errCh <- errors.E(op, "command is nil")
+ errCh <- errors.E(op, errors.Str("command is nil"))
return errCh
}
diff --git a/tests/plugins/server/server_plugin_test.go b/tests/plugins/server/server_plugin_test.go
index c0c3c993..06c9eb50 100644
--- a/tests/plugins/server/server_plugin_test.go
+++ b/tests/plugins/server/server_plugin_test.go
@@ -23,22 +23,13 @@ func TestAppPipes(t *testing.T) {
vp := &config.Viper{}
vp.Path = "configs/.rr.yaml"
vp.Prefix = "rr"
- err = container.Register(vp)
- if err != nil {
- t.Fatal(err)
- }
-
- err = container.Register(&server.Plugin{})
- if err != nil {
- t.Fatal(err)
- }
- err = container.Register(&Foo{})
- if err != nil {
- t.Fatal(err)
- }
-
- err = container.Register(&logger.ZapLogger{})
+ err = container.RegisterAll(
+ vp,
+ &server.Plugin{},
+ &Foo{},
+ &logger.ZapLogger{},
+ )
if err != nil {
t.Fatal(err)
}