diff options
author | Wolfy-J <[email protected]> | 2018-06-06 13:39:07 +0300 |
---|---|---|
committer | Wolfy-J <[email protected]> | 2018-06-06 13:39:07 +0300 |
commit | 7067d593f243e86a54f4ffd87a06c744e5636e07 (patch) | |
tree | 83ba4ab9503059e2383fe40a04be6f1e7d2b9f2f | |
parent | b49a888579be9dfc33069d168083c54fb354e24c (diff) |
command factory
-rw-r--r-- | cmd/_____/factory.go | 37 | ||||
-rw-r--r-- | server_config.go | 64 | ||||
-rw-r--r-- | server_config_test.go | 10 | ||||
-rw-r--r-- | user.go | 31 | ||||
-rw-r--r-- | user_test.go | 81 |
5 files changed, 180 insertions, 43 deletions
diff --git a/cmd/_____/factory.go b/cmd/_____/factory.go deleted file mode 100644 index cee962e2..00000000 --- a/cmd/_____/factory.go +++ /dev/null @@ -1,37 +0,0 @@ -package _____ - -import ( - "github.com/spiral/roadrunner" - "os/exec" - "strings" - "time" -) - -// todo: move out -type PoolConfig struct { - Command string - Relay string - - Number uint64 - MaxJobs uint64 - - Timeouts struct { - Construct int - Allocate int - Destroy int - } -} - -func (f *PoolConfig) rrConfig() roadrunner.Config { - return roadrunner.Config{ - NumWorkers: f.Number, - MaxExecutions: f.MaxJobs, - AllocateTimeout: time.Second * time.Duration(f.Timeouts.Allocate), - DestroyTimeout: time.Second * time.Duration(f.Timeouts.Destroy), - } -} - -func (f *PoolConfig) cmd() func() *exec.Cmd { - cmd := strings.Split(f.Command, " ") - return func() *exec.Cmd { return exec.Command(cmd[0], cmd[1:]...) } -} diff --git a/server_config.go b/server_config.go index 99eaa678..0a06d749 100644 --- a/server_config.go +++ b/server_config.go @@ -6,6 +6,9 @@ import ( "strings" "time" "os/exec" + "syscall" + "os/user" + "strconv" ) const ( @@ -41,17 +44,66 @@ type ServerConfig struct { Pool *Config } -func (f *ServerConfig) makeCommand() (func() *exec.Cmd, error) { - return nil, nil +func (cfg *ServerConfig) makeCommand() (func() *exec.Cmd, error) { + var ( + err error + u *user.User + g *user.Group + crd *syscall.Credential + cmd = strings.Split(cfg.Command, " ") + ) + + if cfg.User != "" { + if u, err = resolveUser(cfg.User); err != nil { + return nil, err + } + } + + if cfg.Group != "" { + if g, err = resolveGroup(cfg.Group); err != nil { + return nil, err + } + } + + if u != nil || g != nil { + crd = &syscall.Credential{} + + if u != nil { + uid, err := strconv.ParseUint(u.Uid, 10, 32) + if err != nil { + return nil, err + } + + crd.Uid = uint32(uid) + } + + if g != nil { + gid, err := strconv.ParseUint(g.Gid, 10, 32) + if err != nil { + return nil, err + } + + crd.Gid = uint32(gid) + } + } + + return func() *exec.Cmd { + cmd := exec.Command(cmd[0], cmd[1:]...) + if crd != nil { + cmd.SysProcAttr.Credential = crd + } + + return cmd + }, nil } // makeFactory creates and connects new factory instance based on given parameters. -func (f *ServerConfig) makeFactory() (Factory, error) { - if f.Relay == "pipes" || f.Relay == "pipe" { +func (cfg *ServerConfig) makeFactory() (Factory, error) { + if cfg.Relay == "pipes" || cfg.Relay == "pipe" { return NewPipeFactory(), nil } - dsn := strings.Split(f.Relay, "://") + dsn := strings.Split(cfg.Relay, "://") if len(dsn) != 2 { return nil, errors.New("invalid relay DSN (pipes, tcp://:6001, unix://rr.sock)") } @@ -61,5 +113,5 @@ func (f *ServerConfig) makeFactory() (Factory, error) { return nil, nil } - return NewSocketFactory(ln, time.Second*f.FactoryTimeout), nil + return NewSocketFactory(ln, time.Second*cfg.FactoryTimeout), nil } diff --git a/server_config_test.go b/server_config_test.go index 667cfced..bd3ee76b 100644 --- a/server_config_test.go +++ b/server_config_test.go @@ -58,3 +58,13 @@ func Test_ServerConfig_ErrorFactory(t *testing.T) { assert.Error(t, err) assert.Equal(t, "invalid relay DSN (pipes, tcp://:6001, unix://rr.sock)", err.Error()) } + +func Test_ServerConfig_Cmd(t *testing.T) { + cfg := &ServerConfig{ + Command: "php php-src/tests/client.php pipes", + } + + cmd, err := cfg.makeCommand() + assert.NoError(t, err) + assert.NotNil(t, cmd) +} diff --git a/user.go b/user.go new file mode 100644 index 00000000..1d47b5fb --- /dev/null +++ b/user.go @@ -0,0 +1,31 @@ +package roadrunner + +import ( + "os/user" + "fmt" +) + +// resolveUser attempt to find system user by it's name or uid. +func resolveUser(u string) (usr *user.User, err error) { + usr, err = user.LookupId(u) + if usr != nil { + return usr, nil + } + + return user.Lookup(u) +} + +// resolveUser attempt to find system group by it's name or uid. +func resolveGroup(g string) (grp *user.Group, err error) { + grp, err = user.LookupGroupId(g) + if grp != nil && grp.Name != "nogroup" { + return grp, nil + } + + grp, err = user.LookupGroup(g) + if grp != nil && grp.Name != "nogroup" { + return grp, nil + } + + return nil, fmt.Errorf("no such group %s", g) +} diff --git a/user_test.go b/user_test.go new file mode 100644 index 00000000..3a9f6da9 --- /dev/null +++ b/user_test.go @@ -0,0 +1,81 @@ +package roadrunner + +import ( + "testing" + "runtime" + "github.com/stretchr/testify/assert" + "os/user" +) + +func Test_ResolveUser_Error(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("not supported on " + runtime.GOOS) + } + + u, err := resolveUser("-1") + assert.Nil(t, u) + assert.Error(t, err) + + u, err = resolveUser("random-user") + assert.Nil(t, u) + assert.Error(t, err) +} + +func Test_ResolveUser(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("not supported on " + runtime.GOOS) + } + + current, err := user.Current() + assert.NotNil(t, current) + assert.NoError(t, err) + + u, err := resolveUser(current.Uid) + assert.NoError(t, err) + assert.NotNil(t, u) + assert.Equal(t, current.Uid, u.Uid) + + u, err = resolveUser(current.Name) + assert.NoError(t, err) + assert.NotNil(t, u) + assert.Equal(t, current.Uid, u.Uid) + + u, err = resolveUser(current.Username) + assert.NoError(t, err) + assert.NotNil(t, u) + assert.Equal(t, current.Uid, u.Uid) +} + +func Test_ResolveGroup_Error(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("not supported on " + runtime.GOOS) + } + + g, err := resolveGroup("-1") + assert.Nil(t, g) + assert.Error(t, err) + + g, err = resolveGroup("random-group") + assert.Nil(t, g) + assert.Error(t, err) +} + +func Test_ResolveGroup(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("not supported on " + runtime.GOOS) + } + + current, err := user.Current() + assert.NotNil(t, current) + assert.NoError(t, err) + + g, err := resolveGroup(current.Gid) + assert.NoError(t, err) + assert.NotNil(t, g) + assert.Equal(t, current.Gid, g.Gid) + + g2, err := resolveGroup(g.Name) + assert.NoError(t, err) + assert.NotNil(t, g2) + assert.Equal(t, g2.Gid, g.Gid) +} |