Skip to content

Commit

Permalink
Overhaul
Browse files Browse the repository at this point in the history
  • Loading branch information
kilgaloon committed Oct 6, 2018
1 parent 35f3746 commit d8b169e
Show file tree
Hide file tree
Showing 21 changed files with 377 additions and 400 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@
/var
/coverprofile
/tests/etc/leprechaun/recipes/schedule.lock
/**/coverage.txt
/**/coverage.txt
/tests/var/run/leprechaun/.pid
.DS_Store
18 changes: 9 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,21 @@ test-with-report:
cd recipe && go vet
cd recipe/schedule && go vet
mkdir -p coverprofile
go test client -coverprofile coverprofile/client.out
go test ./client -coverprofile coverprofile/client.out
go tool cover -html=coverprofile/client.out -o coverprofile/client.html
go test config -coverprofile coverprofile/config.out
go test ./config -coverprofile coverprofile/config.out
go tool cover -html=coverprofile/config.out -o coverprofile/config.html
go test context -coverprofile coverprofile/context.out
go test ./context -coverprofile coverprofile/context.out
go tool cover -html=coverprofile/context.out -o coverprofile/context.html
go test event -coverprofile coverprofile/event.out
go test ./event -coverprofile coverprofile/event.out
go tool cover -html=coverprofile/event.out -o coverprofile/event.html
go test log -coverprofile coverprofile/log.out
go test ./log -coverprofile coverprofile/log.out
go tool cover -html=coverprofile/log.out -o coverprofile/log.html
go test workers -coverprofile coverprofile/workers.out
go test ./workers -coverprofile coverprofile/workers.out
go tool cover -html=coverprofile/workers.out -o coverprofile/workers.html
go test server -coverprofile coverprofile/server.out
go test ./server -coverprofile coverprofile/server.out
go tool cover -html=coverprofile/server.out -o coverprofile/server.html
go test api -coverprofile coverprofile/api.out
go test ./api -coverprofile coverprofile/api.out
go tool cover -html=coverprofile/api.out -o coverprofile/api.html
go test agent -coverprofile coverprofile/agent.out
go test ./agent -coverprofile coverprofile/agent.out
go tool cover -html=coverprofile/agent.out -o coverprofile/agent.html
9 changes: 1 addition & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,7 @@ but in this case for example first task will block performing on any task and al

To start leprechaun just simply run it in background like this : `leprechaun &` and can be stoped with command like this `leprechaun --cmd="client:stop"`

Leprechaun provides some more commands that you can use:

`leprechaun --cmd="client info"` which will provide you with some basic informations about client that is running

`leprechaun --cmd="client workers:list"` which will show you list of workers that are currently working

`leprechaun --cmd="client workers:kill {name}"` `{name}` is a placeholder for name of a job you want to kill, all steps that are working async/sync will be terminated.

For more available commands run `leprechaun help`

# Lepretools

Expand Down
14 changes: 8 additions & 6 deletions api/commands.go → agent/commands.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
package api
package agent

import (
"time"
)

// WorkersList is default command for agents
func (r *Registrator) WorkersList(args ...string) ([][]string, error) {
workers := r.Agent.GetWorkers()
func (d Default) WorkersList(args ...string) ([][]string, error) {
workers := d.GetWorkers()
resp := [][]string{}

if workers.Size() < 1 {
resp = [][]string{
{"No workers currently working!"},
}

return resp, nil
}

for name, worker := range workers.GetAll() {
startedAt := worker.StartedAt.Format(time.UnixDate)
resp = append(resp, []string{name, startedAt, worker.WorkingOn, worker.Err.Error()})
resp = append(resp, []string{name, startedAt, worker.WorkingOn})
}

return resp, nil
}

// KillWorker kills worker by provided name
func (r *Registrator) KillWorker(args ...string) ([][]string, error) {
workers := r.Agent.GetWorkers()
func (d Default) KillWorker(args ...string) ([][]string, error) {
workers := d.GetWorkers()
resp := [][]string{}

worker, err := workers.GetByName(args[0])
Expand Down
62 changes: 61 additions & 1 deletion agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,29 @@ package agent
import (
"sync"

"github.com/kilgaloon/leprechaun/api"
"github.com/kilgaloon/leprechaun/context"
"github.com/kilgaloon/leprechaun/workers"

"github.com/kilgaloon/leprechaun/config"
"github.com/kilgaloon/leprechaun/log"
)

// Agent interface defines client that can be started/stop
// Agent interface defines service that can be started/stop
// that has workers, config, context and logs
type Agent interface {
GetName() string
GetWorkers() *workers.Workers
GetContext() *context.Context
GetConfig() *config.AgentConfig
GetLogs() log.Logs
GetSocket() *api.Socket
GetMutex() *sync.Mutex

SetPID(i int)
GetPID() int

DefaultCommands(map[string]api.Command) map[string]api.Command
}

// Default represents default agent
Expand All @@ -29,6 +37,7 @@ type Default struct {
Mu *sync.Mutex
Workers *workers.Workers
Context *context.Context
Socket *api.Socket
}

// GetName returns name of the client
Expand Down Expand Up @@ -56,6 +65,56 @@ func (d Default) GetConfig() *config.AgentConfig {
return d.Config
}

// GetSocket returns information about socket
// and commands available for internal communication
func (d Default) GetSocket() *api.Socket {
return d.Socket
}

// GetMutex for agent
func (d Default) GetMutex() *sync.Mutex {
return d.Mu
}

// SetPID sets process id for agent
func (d *Default) SetPID(i int) {
d.PID = i
}

// GetPID sets process id for agent
func (d Default) GetPID() int {
return d.PID
}

// DefaultCommands merge 2 maps into one
// it usability is if some of the agents
// wants to takeover default commands
func (d Default) DefaultCommands(commands map[string]api.Command) map[string]api.Command {
cmds := make(map[string]api.Command)

cmds["workers:list"] = api.Command{
Closure: d.WorkersList,
Definition: api.Definition{
Text: "List all currently active workers",
Usage: "{agent} workers:list",
},
}

cmds["workers:kill"] = api.Command{
Closure: d.KillWorker,
Definition: api.Definition{
Text: "Kills currently active worker by job name",
Usage: "{agent} workers:kill {job}",
},
}

for name, command := range commands {
cmds[name] = command
}

return cmds
}

// New default client
func New(name string, cfg *config.AgentConfig) *Default {
agent := &Default{}
Expand All @@ -73,6 +132,7 @@ func New(name string, cfg *config.AgentConfig) *Default {
agent.Logs,
agent.Context,
)
agent.Socket = api.New(cfg.GetCommandSocket())

return agent
}
84 changes: 62 additions & 22 deletions api/main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package api

import (
"fmt"
"errors"
"io"
"net"
"strings"
Expand All @@ -12,23 +12,51 @@ import (

// Socket defines socket on which we listen for commands
type Socket struct {
unixSock string
registry map[string]*Registrator
unixSock string
commands map[string]Command
readyChan chan bool
}

// This interface implements method
// that agents will use to register for command socket
type registry interface {
RegisterCommandSocket() *Registrator
// Closure is command that will be called to execute
type Closure func(args ...string) ([][]string, error)

// Command is definition of basic command that can be called with --cmd
type Command struct {
Definition
Closure Closure
}

// Definition of command
type Definition struct {
Text string
Usage string
}

func (c Command) String() string {
return c.Definition.Text + " - usage: " + c.Definition.Usage
}

// Registrator is agent that will be registered
type Registrator interface {
RegisterCommands() map[string]Command
}

func (s *Socket) ready() {
s.readyChan <- true
}

// GetCommands return array of commands
func (s *Socket) GetCommands() map[string]Command {
return s.commands
}

// Register agent to registry
func (s *Socket) Register(r registry) {
reg := r.RegisterCommandSocket()
s.registry[reg.Agent.GetName()] = reg
func (s *Socket) Register(r Registrator) {
s.commands = r.RegisterCommands()

syscall.Unlink(s.unixSock)
ln, err := net.Listen("unix", s.unixSock)
s.ready()
if err != nil {
panic(err)
}
Expand All @@ -44,7 +72,7 @@ func (s *Socket) Register(r registry) {
}

//Command sends command to socket and gets output
func (s *Socket) Command(cmd string) {
func (s *Socket) Command(cmd string) string {
c, err := net.Dial("unix", s.unixSock)
if err != nil {
panic(err)
Expand All @@ -62,13 +90,13 @@ func (s *Socket) Command(cmd string) {
n, err := c.Read(buf)
if err != nil {
if err == io.EOF {
return
return ""
}

panic(err)
}

fmt.Printf("%s", string(buf[0:n]))
return string(buf[0:n])
}

}
Expand All @@ -87,15 +115,15 @@ func (s Socket) resolver(c net.Conn) {
data := buf[0:nr]
req := strings.Fields(strings.Trim(string(data), "\n"))
if len(req) < 2 {
continue
c.Write([]byte("Invalid command"))
return
}

registry := req[0]
command := req[1]
args := req[2:]

if registry != "" || command != "" {
r, err := s.registry[registry].Call(command, args...)
if command != "" {
r, err := s.Call(command, args...)
if err != nil {
c.Write([]byte(err.Error()))
}
Expand All @@ -111,10 +139,22 @@ func (s Socket) resolver(c net.Conn) {
}
}

// BuildSocket create new socket instance
func BuildSocket(socketPath string) *Socket {
return &Socket{
unixSock: socketPath,
registry: make(map[string]*Registrator),
// Call specified command
func (s Socket) Call(name string, args ...string) ([][]string, error) {
if command, exist := s.commands[name]; exist {
return command.Closure(args...)
}

return nil, errors.New("Command does not exists, or it's not registered")
}

// New creates new socket
func New(socketPath string) *Socket {
sock := &Socket{
unixSock: socketPath,
commands: make(map[string]Command),
readyChan: make(chan bool),
}

return sock
}
Loading

0 comments on commit d8b169e

Please sign in to comment.