Skip to content

Commit

Permalink
implement server command
Browse files Browse the repository at this point in the history
  • Loading branch information
et-nik committed Feb 16, 2024
1 parent 91ae4ba commit 5f4a2bf
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 16 deletions.
4 changes: 4 additions & 0 deletions internal/app/components/customhandlers/get_tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ func NewGetTool(cfg *config.Config) *GetTool {
}

func (g *GetTool) Handle(ctx context.Context, args []string, out io.Writer, _ contracts.ExecutorOptions) (int, error) {
if len(args) < 1 {
return int(domain.ErrorResult), errors.New("no source provided")
}

source := args[0]
fileName := filepath.Base(source)
destination := filepath.Join(g.cfg.ToolsPath, fileName)
Expand Down
109 changes: 94 additions & 15 deletions internal/app/components/customhandlers/server_console.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,125 @@ package customhandlers
import (
"context"
"io"
"strconv"
"strings"

"github.com/gameap/daemon/internal/app/config"
"github.com/gameap/daemon/internal/app/contracts"
"github.com/gameap/daemon/internal/app/domain"
"github.com/pkg/errors"
)

type outputReader interface {
GetOutput(ctx context.Context, server *domain.Server, out io.Writer) (domain.Result, error)
}

type serverRepo interface {
FindByID(ctx context.Context, id int) (*domain.Server, error)
}

type OutputReader struct {
cfg *config.Config
getter outputReader
cfg *config.Config
getter outputReader
serverRepo serverRepo
}

func NewOutputReader(cfg *config.Config, getter outputReader) *OutputReader {
return &OutputReader{cfg: cfg, getter: getter}
func NewOutputReader(
cfg *config.Config,
getter outputReader,
serverRepo serverRepo,
) *OutputReader {
return &OutputReader{
cfg: cfg,
getter: getter,
serverRepo: serverRepo,
}
}

func (g *OutputReader) Handle(
_ context.Context, _ []string, _ io.Writer, _ contracts.ExecutorOptions,
func (or *OutputReader) Handle(
ctx context.Context, args []string, out io.Writer, _ contracts.ExecutorOptions,
) (int, error) {
return 0, nil
if len(args) < 1 {
return int(domain.ErrorResult), errors.New("no server id provided")
}

serverID, err := strconv.Atoi(args[0])
if err != nil {
return int(domain.ErrorResult), errors.New("invalid server id, should be integer")
}

server, err := or.serverRepo.FindByID(ctx, serverID)
if err != nil {
return int(domain.ErrorResult), errors.WithMessage(err, "failed to get server")
}

if server == nil {
return int(domain.ErrorResult), errors.New("server not found")
}

result, err := or.getter.GetOutput(ctx, server, out)
if err != nil {
return int(domain.ErrorResult), errors.WithMessage(err, "failed to get output")
}

return int(result), nil
}

type commandSender interface {
SendCommand(ctx context.Context, server *domain.Server, out io.Writer) (domain.Result, error)
SendInput(ctx context.Context, input string, server *domain.Server, out io.Writer) (domain.Result, error)
}

type CommandSender struct {
cfg *config.Config
sender commandSender
cfg *config.Config
sender commandSender
serverRepo serverRepo
}

func NewCommandSender(cfg *config.Config, sender commandSender) *CommandSender {
return &CommandSender{cfg: cfg, sender: sender}
func NewCommandSender(
cfg *config.Config,
sender commandSender,
serverRepo serverRepo,
) *CommandSender {
return &CommandSender{
cfg: cfg,
sender: sender,
serverRepo: serverRepo,
}
}

func (g *CommandSender) Handle(
_ context.Context, _ []string, _ io.Writer, _ contracts.ExecutorOptions,
func (cs *CommandSender) Handle(
ctx context.Context, args []string, out io.Writer, _ contracts.ExecutorOptions,
) (int, error) {
return 0, nil
if len(args) < 2 {
return int(domain.ErrorResult), errors.New("not enough arguments")
}

serverID, err := strconv.Atoi(args[0])
if err != nil {
return int(domain.ErrorResult), errors.New("invalid server id, should be integer")
}

server, err := cs.serverRepo.FindByID(ctx, serverID)
if err != nil {
return int(domain.ErrorResult), errors.WithMessage(err, "failed to get server")
}

if server == nil {
return int(domain.ErrorResult), errors.New("server not found")
}

b := strings.Builder{}
b.Grow(len(args) * 10)

for _, arg := range args[1:] {
b.WriteString(arg)
b.WriteString(" ")
}

result, err := cs.sender.SendInput(ctx, b.String(), server, out)
if err != nil {
return int(domain.ErrorResult), errors.WithMessage(err, "failed to send input")
}

return int(result), nil
}
19 changes: 18 additions & 1 deletion internal/app/di/internal/definitions/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,29 @@ func CreateServiceExtendableExecutor(ctx context.Context, c Container) contracts
executor := components.NewDefaultExtendableExecutor(c.Services().Executor(ctx))

executor.RegisterHandler("get-tool", customhandlers.NewGetTool(c.Cfg(ctx)).Handle)
executor.RegisterHandler(
"server-output",
customhandlers.NewOutputReader(
c.Cfg(ctx),
c.Services().ProcessManager(ctx),
c.Repositories().ServerRepository(ctx),
).Handle,
)

executor.RegisterHandler(
"server-command",
customhandlers.NewCommandSender(
c.Cfg(ctx),
c.Services().ProcessManager(ctx),
c.Repositories().ServerRepository(ctx),
).Handle,
)

return executor
}

func CreateServicesProcessManager(ctx context.Context, c Container) contracts.ProcessManager {
return processmanager.NewTmux(
return processmanager.NewSystemD(
c.Cfg(ctx),
c.Services().Executor(ctx),
)
Expand Down

0 comments on commit 5f4a2bf

Please sign in to comment.