diff options
author | Valery Piashchynski <[email protected]> | 2022-01-15 12:08:20 +0300 |
---|---|---|
committer | Valery Piashchynski <[email protected]> | 2022-01-15 12:08:20 +0300 |
commit | 5254c8eb27311e2a8a53a4c90c3829cf1238c563 (patch) | |
tree | b51c9a4c1dd4c25adc511498ce0380a7078c5572 /internal/container | |
parent | 13609dd03dd0d2fa85b9fb850be787bf4e2ea67f (diff) |
Repository content update
Signed-off-by: Valery Piashchynski <[email protected]>
Diffstat (limited to 'internal/container')
-rw-r--r-- | internal/container/config.go | 83 | ||||
-rw-r--r-- | internal/container/config_test.go | 82 | ||||
-rw-r--r-- | internal/container/container.go | 21 | ||||
-rw-r--r-- | internal/container/container_test.go | 27 | ||||
-rw-r--r-- | internal/container/plugins.go | 104 | ||||
-rw-r--r-- | internal/container/plugins_test.go | 20 |
6 files changed, 337 insertions, 0 deletions
diff --git a/internal/container/config.go b/internal/container/config.go new file mode 100644 index 00000000..54e2bb5b --- /dev/null +++ b/internal/container/config.go @@ -0,0 +1,83 @@ +package container + +import ( + "fmt" + "time" + + endure "github.com/spiral/endure/pkg/container" + "github.com/spiral/roadrunner-plugins/v2/config" +) + +type Config struct { + GracePeriod time.Duration + PrintGraph bool + RetryOnFail bool // TODO check for races, disabled at this moment + LogLevel endure.Level +} + +const ( + endureKey = "endure" + defaultGracePeriod = time.Second * 30 +) + +// NewConfig creates endure container configuration. +func NewConfig(cfgPlugin *config.Plugin) (*Config, error) { + if !cfgPlugin.Has(endureKey) { + return &Config{ // return config with defaults + GracePeriod: defaultGracePeriod, + PrintGraph: false, + RetryOnFail: false, + LogLevel: endure.ErrorLevel, + }, nil + } + + rrCfgEndure := struct { + GracePeriod time.Duration `mapstructure:"grace_period"` + PrintGraph bool `mapstructure:"print_graph"` + RetryOnFail bool `mapstructure:"retry_on_fail"` + LogLevel string `mapstructure:"log_level"` + }{} + + if err := cfgPlugin.UnmarshalKey(endureKey, &rrCfgEndure); err != nil { + return nil, err + } + + if rrCfgEndure.GracePeriod == 0 { + rrCfgEndure.GracePeriod = defaultGracePeriod + } + + if rrCfgEndure.LogLevel == "" { + rrCfgEndure.LogLevel = "error" + } + + logLevel, err := parseLogLevel(rrCfgEndure.LogLevel) + if err != nil { + return nil, err + } + + return &Config{ + GracePeriod: rrCfgEndure.GracePeriod, + PrintGraph: rrCfgEndure.PrintGraph, + RetryOnFail: rrCfgEndure.RetryOnFail, + LogLevel: logLevel, + }, nil +} + +func parseLogLevel(s string) (endure.Level, error) { + switch s { + case "debug": + return endure.DebugLevel, nil + case "info": + return endure.InfoLevel, nil + case "warn", "warning": + return endure.WarnLevel, nil + case "error": + return endure.ErrorLevel, nil + case "panic": + return endure.PanicLevel, nil + case "fatal": + return endure.FatalLevel, nil + } + + return endure.DebugLevel, fmt.Errorf(`unknown log level "%s" (allowed: debug, info, warn, error, panic, fatal)`, s) +} diff --git a/internal/container/config_test.go b/internal/container/config_test.go new file mode 100644 index 00000000..9919def4 --- /dev/null +++ b/internal/container/config_test.go @@ -0,0 +1,82 @@ +package container_test + +import ( + "testing" + "time" + + "github.com/spiral/roadrunner-binary/v2/internal/container" + + endure "github.com/spiral/endure/pkg/container" + "github.com/spiral/roadrunner-plugins/v2/config" + "github.com/stretchr/testify/assert" +) + +func TestNewConfig_SuccessfulReading(t *testing.T) { + cfgPlugin := &config.Plugin{Type: "yaml", ReadInCfg: []byte(` +endure: + grace_period: 10s + print_graph: true + retry_on_fail: true + log_level: warn +`)} + assert.NoError(t, cfgPlugin.Init()) + + c, err := container.NewConfig(cfgPlugin) + assert.NoError(t, err) + assert.NotNil(t, c) + + assert.Equal(t, time.Second*10, c.GracePeriod) + assert.True(t, c.PrintGraph) + assert.True(t, c.RetryOnFail) + assert.Equal(t, endure.WarnLevel, c.LogLevel) +} + +func TestNewConfig_WithoutEndureKey(t *testing.T) { + cfgPlugin := &config.Plugin{Type: "yaml", ReadInCfg: []byte{}} + assert.NoError(t, cfgPlugin.Init()) + + c, err := container.NewConfig(cfgPlugin) + assert.NoError(t, err) + assert.NotNil(t, c) + + assert.Equal(t, time.Second*30, c.GracePeriod) + assert.False(t, c.PrintGraph) + assert.False(t, c.RetryOnFail) + assert.Equal(t, endure.ErrorLevel, c.LogLevel) +} + +func TestNewConfig_LoggingLevels(t *testing.T) { + for _, tt := range []struct { + giveLevel string + wantLevel endure.Level + wantError bool + }{ + {giveLevel: "debug", wantLevel: endure.DebugLevel}, + {giveLevel: "info", wantLevel: endure.InfoLevel}, + {giveLevel: "warn", wantLevel: endure.WarnLevel}, + {giveLevel: "warning", wantLevel: endure.WarnLevel}, + {giveLevel: "error", wantLevel: endure.ErrorLevel}, + {giveLevel: "panic", wantLevel: endure.PanicLevel}, + {giveLevel: "fatal", wantLevel: endure.FatalLevel}, + + {giveLevel: "foobar", wantError: true}, + } { + tt := tt + t.Run(tt.giveLevel, func(t *testing.T) { + cfgPlugin := &config.Plugin{Type: "yaml", ReadInCfg: []byte("endure:\n log_level: " + tt.giveLevel)} + assert.NoError(t, cfgPlugin.Init()) + + c, err := container.NewConfig(cfgPlugin) + + if tt.wantError { + assert.Nil(t, c) + assert.Error(t, err) + assert.Contains(t, err.Error(), "unknown log level") + } else { + assert.NoError(t, err) + assert.NotNil(t, c) + assert.Equal(t, tt.wantLevel, c.LogLevel) + } + }) + } +} diff --git a/internal/container/container.go b/internal/container/container.go new file mode 100644 index 00000000..aa767b2e --- /dev/null +++ b/internal/container/container.go @@ -0,0 +1,21 @@ +package container + +import ( + endure "github.com/spiral/endure/pkg/container" +) + +// NewContainer creates endure container with all required options (based on container Config). Logger is nil by +// default. +func NewContainer(cfg Config) (*endure.Endure, error) { + endureOptions := []endure.Options{ + endure.SetLogLevel(cfg.LogLevel), + endure.RetryOnFail(cfg.RetryOnFail), + endure.GracefulShutdownTimeout(cfg.GracePeriod), + } + + if cfg.PrintGraph { + endureOptions = append(endureOptions, endure.Visualize(endure.StdOut, "")) + } + + return endure.NewContainer(nil, endureOptions...) +} diff --git a/internal/container/container_test.go b/internal/container/container_test.go new file mode 100644 index 00000000..c6d613a0 --- /dev/null +++ b/internal/container/container_test.go @@ -0,0 +1,27 @@ +package container_test + +import ( + "testing" + "time" + + "github.com/spiral/roadrunner-binary/v2/internal/container" + + endure "github.com/spiral/endure/pkg/container" + "github.com/stretchr/testify/assert" +) + +func TestNewContainer(t *testing.T) { // there is no legal way to test container options + c, err := container.NewContainer(container.Config{}) + c2, err2 := container.NewContainer(container.Config{ + GracePeriod: time.Second, + PrintGraph: true, + RetryOnFail: true, + LogLevel: endure.WarnLevel, + }) + + assert.NoError(t, err) + assert.NotNil(t, c) + + assert.NoError(t, err2) + assert.NotNil(t, c2) +} diff --git a/internal/container/plugins.go b/internal/container/plugins.go new file mode 100644 index 00000000..6c962793 --- /dev/null +++ b/internal/container/plugins.go @@ -0,0 +1,104 @@ +package container + +import ( + "github.com/spiral/roadrunner-plugins/v2/amqp" + "github.com/spiral/roadrunner-plugins/v2/beanstalk" + "github.com/spiral/roadrunner-plugins/v2/boltdb" + "github.com/spiral/roadrunner-plugins/v2/broadcast" + "github.com/spiral/roadrunner-plugins/v2/fileserver" + grpcPlugin "github.com/spiral/roadrunner-plugins/v2/grpc" + httpPlugin "github.com/spiral/roadrunner-plugins/v2/http" + "github.com/spiral/roadrunner-plugins/v2/http/middleware/gzip" + "github.com/spiral/roadrunner-plugins/v2/http/middleware/headers" + newrelic "github.com/spiral/roadrunner-plugins/v2/http/middleware/new_relic" + "github.com/spiral/roadrunner-plugins/v2/http/middleware/prometheus" + "github.com/spiral/roadrunner-plugins/v2/http/middleware/static" + "github.com/spiral/roadrunner-plugins/v2/http/middleware/websockets" + "github.com/spiral/roadrunner-plugins/v2/informer" + "github.com/spiral/roadrunner-plugins/v2/jobs" + "github.com/spiral/roadrunner-plugins/v2/kv" + "github.com/spiral/roadrunner-plugins/v2/logger" + "github.com/spiral/roadrunner-plugins/v2/memcached" + "github.com/spiral/roadrunner-plugins/v2/memory" + "github.com/spiral/roadrunner-plugins/v2/metrics" + "github.com/spiral/roadrunner-plugins/v2/nats" + "github.com/spiral/roadrunner-plugins/v2/redis" + "github.com/spiral/roadrunner-plugins/v2/reload" + "github.com/spiral/roadrunner-plugins/v2/resetter" + rpcPlugin "github.com/spiral/roadrunner-plugins/v2/rpc" + "github.com/spiral/roadrunner-plugins/v2/server" + "github.com/spiral/roadrunner-plugins/v2/service" + "github.com/spiral/roadrunner-plugins/v2/sqs" + "github.com/spiral/roadrunner-plugins/v2/status" + "github.com/spiral/roadrunner-plugins/v2/tcp" + roadrunner_temporal "github.com/temporalio/roadrunner-temporal" +) + +// Plugins returns active plugins for the endure container. Feel free to add or remove any plugins. +func Plugins() []interface{} { //nolint:funlen + return []interface{}{ + // bundled + // informer plugin (./rr workers, ./rr workers -i) + &informer.Plugin{}, + // resetter plugin (./rr reset) + &resetter.Plugin{}, + + // logger plugin + &logger.ZapLogger{}, + // metrics plugin + &metrics.Plugin{}, + // reload plugin + &reload.Plugin{}, + // rpc plugin (workers, reset) + &rpcPlugin.Plugin{}, + // server plugin (NewWorker, NewWorkerPool) + &server.Plugin{}, + // service plugin + &service.Plugin{}, + + // ========= JOBS bundle + &jobs.Plugin{}, + &amqp.Plugin{}, + &sqs.Plugin{}, + &nats.Plugin{}, + &beanstalk.Plugin{}, + // ========= + + // http server plugin with middleware + &httpPlugin.Plugin{}, + &newrelic.Plugin{}, + &static.Plugin{}, + &headers.Plugin{}, + &status.Plugin{}, + &gzip.Plugin{}, + &prometheus.Plugin{}, + + &fileserver.Plugin{}, + // =================== + + &grpcPlugin.Plugin{}, + // kv + ws + jobs plugin + &memory.Plugin{}, + // KV + Jobs + &boltdb.Plugin{}, + + // broadcast via memory or redis + // used in conjunction with Websockets, memory and redis plugins + &broadcast.Plugin{}, + // ======== websockets broadcast bundle + &websockets.Plugin{}, + &redis.Plugin{}, + // ========= + + // ============== KV + &kv.Plugin{}, + &memcached.Plugin{}, + // ============== + + // raw TCP connections handling + &tcp.Plugin{}, + + // temporal plugins + &roadrunner_temporal.Plugin{}, + } +} diff --git a/internal/container/plugins_test.go b/internal/container/plugins_test.go new file mode 100644 index 00000000..da639f7d --- /dev/null +++ b/internal/container/plugins_test.go @@ -0,0 +1,20 @@ +package container_test + +import ( + "reflect" + "testing" + + "github.com/spiral/roadrunner-binary/v2/internal/container" +) + +func TestPlugins(t *testing.T) { + for _, p := range container.Plugins() { + if p == nil { + t.Error("plugin cannot be nil") + } + + if pk := reflect.TypeOf(p).Kind(); pk != reflect.Ptr && pk != reflect.Struct { + t.Errorf("plugin %v must be a structure or pointer to the structure", p) + } + } +} |