Event refactor

This commit is contained in:
Jonathan Leibiusky @xetorthio
2017-07-18 10:45:05 -03:00
parent 6eaece99c5
commit 4731d8ec98
17 changed files with 198 additions and 125 deletions

View File

@@ -1,34 +0,0 @@
package pwd
import (
"net/http"
"github.com/googollee/go-socket.io"
)
type BroadcastApi interface {
BroadcastTo(sessionId, eventName string, args ...interface{})
GetHandler() http.Handler
}
type broadcast struct {
sio *socketio.Server
}
func (b *broadcast) BroadcastTo(sessionId, eventName string, args ...interface{}) {
b.sio.BroadcastTo(sessionId, eventName, args...)
}
func (b *broadcast) GetHandler() http.Handler {
return b.sio
}
func NewBroadcast(connectionEvent, errorEvent interface{}) (*broadcast, error) {
server, err := socketio.NewServer(nil)
if err != nil {
return nil, err
}
server.On("connection", connectionEvent)
server.On("error", errorEvent)
return &broadcast{sio: server}, nil
}

View File

@@ -1,20 +0,0 @@
package pwd
import "net/http"
type mockBroadcast struct {
broadcastTo func(sessionId, eventName string, args ...interface{})
getHandler func() http.Handler
}
func (m *mockBroadcast) BroadcastTo(sessionId, eventName string, args ...interface{}) {
if m.broadcastTo != nil {
m.broadcastTo(sessionId, eventName, args...)
}
}
func (m *mockBroadcast) GetHandler() http.Handler {
if m.getHandler != nil {
return m.getHandler()
}
return nil
}

View File

@@ -4,6 +4,7 @@ import (
"log"
"time"
"github.com/play-with-docker/play-with-docker/event"
"github.com/play-with-docker/play-with-docker/pwd/types"
)
@@ -41,7 +42,7 @@ func (p *pwd) ClientClose(client *types.Client) {
func (p *pwd) notifyClientSmallestViewPort(session *types.Session) {
vp := p.SessionGetSmallestViewPort(session)
// Resize all terminals in the session
p.broadcast.BroadcastTo(session.Id, "viewport resize", vp.Cols, vp.Rows)
p.event.Emit(event.INSTANCE_VIEWPORT_RESIZE, session.Id, vp.Cols, vp.Rows)
for _, instance := range session.Instances {
err := p.InstanceResizeTerminal(instance, vp.Rows, vp.Cols)
if err != nil {

View File

@@ -1,9 +1,11 @@
package pwd
import (
"sync"
"testing"
"time"
"github.com/play-with-docker/play-with-docker/event"
"github.com/play-with-docker/play-with-docker/pwd/types"
"github.com/stretchr/testify/assert"
)
@@ -11,10 +13,10 @@ import (
func TestClientNew(t *testing.T) {
docker := &mockDocker{}
tasks := &mockTasks{}
broadcast := &mockBroadcast{}
e := event.NewLocalBroker()
storage := &mockStorage{}
p := NewPWD(docker, tasks, broadcast, storage)
p := NewPWD(docker, tasks, e, storage)
session, err := p.SessionNew(time.Hour, "", "", "")
assert.Nil(t, err)
@@ -26,33 +28,34 @@ func TestClientNew(t *testing.T) {
}
func TestClientResizeViewPort(t *testing.T) {
wg := sync.WaitGroup{}
wg.Add(1)
docker := &mockDocker{}
tasks := &mockTasks{}
broadcast := &mockBroadcast{}
e := event.NewLocalBroker()
broadcastedSessionId := ""
broadcastedEventName := ""
broadcastedArgs := []interface{}{}
broadcast.broadcastTo = func(sessionId, eventName string, args ...interface{}) {
e.On(event.INSTANCE_VIEWPORT_RESIZE, func(sessionId string, args ...interface{}) {
broadcastedSessionId = sessionId
broadcastedEventName = eventName
broadcastedArgs = args
}
wg.Done()
})
storage := &mockStorage{}
p := NewPWD(docker, tasks, broadcast, storage)
p := NewPWD(docker, tasks, e, storage)
session, err := p.SessionNew(time.Hour, "", "", "")
assert.Nil(t, err)
client := p.ClientNew("foobar", session)
p.ClientResizeViewPort(client, 80, 24)
wg.Wait()
assert.Equal(t, types.ViewPort{Cols: 80, Rows: 24}, client.ViewPort)
assert.Equal(t, session.Id, broadcastedSessionId)
assert.Equal(t, "viewport resize", broadcastedEventName)
assert.Equal(t, uint(80), broadcastedArgs[0])
assert.Equal(t, uint(24), broadcastedArgs[1])
}

View File

@@ -11,6 +11,7 @@ import (
"github.com/play-with-docker/play-with-docker/config"
"github.com/play-with-docker/play-with-docker/docker"
"github.com/play-with-docker/play-with-docker/event"
"github.com/play-with-docker/play-with-docker/pwd/types"
"golang.org/x/text/encoding"
@@ -19,11 +20,11 @@ import (
type sessionWriter struct {
sessionId string
instanceName string
broadcast BroadcastApi
event event.EventApi
}
func (s *sessionWriter) Write(p []byte) (n int, err error) {
s.broadcast.BroadcastTo(s.sessionId, "terminal out", s.instanceName, string(p))
s.event.Emit(event.INSTANCE_TERMINAL_OUT, s.sessionId, s.instanceName, string(p))
return len(p), nil
}
@@ -52,7 +53,7 @@ func (p *pwd) InstanceAttachTerminal(instance *types.Instance) error {
}
encoder := encoding.Replacement.NewEncoder()
sw := &sessionWriter{sessionId: instance.Session.Id, instanceName: instance.Name, broadcast: p.broadcast}
sw := &sessionWriter{sessionId: instance.Session.Id, instanceName: instance.Name, event: p.event}
instance.Terminal = conn
io.Copy(encoder.Writer(sw), conn)
@@ -139,7 +140,7 @@ func (p *pwd) InstanceDelete(session *types.Session, instance *types.Instance) e
return err
}
p.broadcast.BroadcastTo(session.Id, "delete instance", instance.Name)
p.event.Emit(event.INSTANCE_DELETE, session.Id, instance.Name)
delete(session.Instances, instance.Name)
if err := p.storage.SessionPut(session); err != nil {
@@ -238,7 +239,7 @@ func (p *pwd) InstanceNew(session *types.Session, conf InstanceConfig) (*types.I
return nil, err
}
p.broadcast.BroadcastTo(session.Id, "new instance", instance.Name, instance.IP, instance.Hostname)
p.event.Emit(event.INSTANCE_NEW, session.Id, instance.Name, instance.IP, instance.Hostname)
p.setGauges()

View File

@@ -8,6 +8,7 @@ import (
"github.com/play-with-docker/play-with-docker/config"
"github.com/play-with-docker/play-with-docker/docker"
"github.com/play-with-docker/play-with-docker/event"
"github.com/play-with-docker/play-with-docker/pwd/types"
"github.com/stretchr/testify/assert"
)
@@ -27,10 +28,10 @@ func TestInstanceResizeTerminal(t *testing.T) {
}
tasks := &mockTasks{}
broadcast := &mockBroadcast{}
e := event.NewLocalBroker()
storage := &mockStorage{}
p := NewPWD(docker, tasks, broadcast, storage)
p := NewPWD(docker, tasks, e, storage)
err := p.InstanceResizeTerminal(&types.Instance{Name: "foobar"}, 24, 80)
@@ -49,10 +50,10 @@ func TestInstanceNew(t *testing.T) {
}
tasks := &mockTasks{}
broadcast := &mockBroadcast{}
e := event.NewLocalBroker()
storage := &mockStorage{}
p := NewPWD(dock, tasks, broadcast, storage)
p := NewPWD(dock, tasks, e, storage)
session, err := p.SessionNew(time.Hour, "", "", "")
@@ -99,10 +100,10 @@ func TestInstanceNew_Concurrency(t *testing.T) {
}
tasks := &mockTasks{}
broadcast := &mockBroadcast{}
e := event.NewLocalBroker()
storage := &mockStorage{}
p := NewPWD(dock, tasks, broadcast, storage)
p := NewPWD(dock, tasks, e, storage)
session, err := p.SessionNew(time.Hour, "", "", "")
@@ -140,10 +141,10 @@ func TestInstanceNew_WithNotAllowedImage(t *testing.T) {
}
tasks := &mockTasks{}
broadcast := &mockBroadcast{}
e := event.NewLocalBroker()
storage := &mockStorage{}
p := NewPWD(dock, tasks, broadcast, storage)
p := NewPWD(dock, tasks, e, storage)
session, err := p.SessionNew(time.Hour, "", "", "")
@@ -188,10 +189,10 @@ func TestInstanceNew_WithCustomHostname(t *testing.T) {
}
tasks := &mockTasks{}
broadcast := &mockBroadcast{}
e := event.NewLocalBroker()
storage := &mockStorage{}
p := NewPWD(dock, tasks, broadcast, storage)
p := NewPWD(dock, tasks, e, storage)
session, err := p.SessionNew(time.Hour, "", "", "")
@@ -230,10 +231,10 @@ func TestInstanceNew_WithCustomHostname(t *testing.T) {
func TestInstanceAllowedImages(t *testing.T) {
dock := &mockDocker{}
tasks := &mockTasks{}
broadcast := &mockBroadcast{}
e := event.NewLocalBroker()
storage := &mockStorage{}
p := NewPWD(dock, tasks, broadcast, storage)
p := NewPWD(dock, tasks, e, storage)
expectedImages := []string{config.GetDindImageName(), "franela/dind:overlay2-dev", "franela/ucp:2.4.1"}

View File

@@ -5,6 +5,7 @@ import (
"time"
"github.com/play-with-docker/play-with-docker/docker"
"github.com/play-with-docker/play-with-docker/event"
"github.com/play-with-docker/play-with-docker/pwd/types"
"github.com/play-with-docker/play-with-docker/storage"
"github.com/prometheus/client_golang/prometheus"
@@ -43,10 +44,10 @@ func init() {
}
type pwd struct {
docker docker.DockerApi
tasks SchedulerApi
broadcast BroadcastApi
storage storage.StorageApi
docker docker.DockerApi
tasks SchedulerApi
event event.EventApi
storage storage.StorageApi
}
type PWDApi interface {
@@ -76,8 +77,8 @@ type PWDApi interface {
ClientClose(client *types.Client)
}
func NewPWD(d docker.DockerApi, t SchedulerApi, b BroadcastApi, s storage.StorageApi) *pwd {
return &pwd{docker: d, tasks: t, broadcast: b, storage: s}
func NewPWD(d docker.DockerApi, t SchedulerApi, e event.EventApi, s storage.StorageApi) *pwd {
return &pwd{docker: d, tasks: t, event: e, storage: s}
}
func (p *pwd) setGauges() {

View File

@@ -11,17 +11,18 @@ import (
"github.com/play-with-docker/play-with-docker/config"
"github.com/play-with-docker/play-with-docker/docker"
"github.com/play-with-docker/play-with-docker/event"
"github.com/play-with-docker/play-with-docker/pwd/types"
"github.com/twinj/uuid"
)
type sessionBuilderWriter struct {
sessionId string
broadcast BroadcastApi
event event.EventApi
}
func (s *sessionBuilderWriter) Write(p []byte) (n int, err error) {
s.broadcast.BroadcastTo(s.sessionId, "session builder out", string(p))
s.event.Emit(event.SESSION_BUILDER_OUT, s.sessionId, string(p))
return len(p), nil
}
@@ -87,8 +88,7 @@ func (p *pwd) SessionClose(s *types.Session) error {
s.StopTicker()
p.broadcast.BroadcastTo(s.Id, "session end")
p.broadcast.BroadcastTo(s.Id, "disconnect")
p.event.Emit(event.SESSION_END, s.Id)
log.Printf("Starting clean up of session [%s]\n", s.Id)
for _, i := range s.Instances {
err := p.InstanceDelete(s, i)
@@ -146,7 +146,7 @@ func (p *pwd) SessionDeployStack(s *types.Session) error {
}
s.Ready = false
p.broadcast.BroadcastTo(s.Id, "session ready", false)
p.event.Emit(event.SESSION_READY, s.Id, false)
i, err := p.InstanceNew(s, InstanceConfig{ImageName: s.ImageName, Host: s.Host})
if err != nil {
log.Printf("Error creating instance for stack [%s]: %s\n", s.Stack, err)
@@ -162,7 +162,7 @@ func (p *pwd) SessionDeployStack(s *types.Session) error {
file := fmt.Sprintf("/var/run/pwd/uploads/%s", fileName)
cmd := fmt.Sprintf("docker swarm init --advertise-addr eth0 && docker-compose -f %s pull && docker stack deploy -c %s %s", file, file, s.StackName)
w := sessionBuilderWriter{sessionId: s.Id, broadcast: p.broadcast}
w := sessionBuilderWriter{sessionId: s.Id, event: p.event}
code, err := p.docker.ExecAttach(i.Name, []string{"sh", "-c", cmd}, &w)
if err != nil {
log.Printf("Error executing stack [%s]: %s\n", s.Stack, err)
@@ -171,7 +171,7 @@ func (p *pwd) SessionDeployStack(s *types.Session) error {
log.Printf("Stack execution finished with code %d\n", code)
s.Ready = true
p.broadcast.BroadcastTo(s.Id, "session ready", true)
p.event.Emit(event.SESSION_READY, s.Id, true)
if err := p.storage.SessionPut(s); err != nil {
return err
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/play-with-docker/play-with-docker/config"
"github.com/play-with-docker/play-with-docker/docker"
"github.com/play-with-docker/play-with-docker/event"
"github.com/play-with-docker/play-with-docker/pwd/types"
"github.com/stretchr/testify/assert"
)
@@ -36,14 +37,14 @@ func TestSessionNew(t *testing.T) {
scheduledSession = s
}
broadcast := &mockBroadcast{}
ev := event.NewLocalBroker()
storage := &mockStorage{}
storage.sessionPut = func(s *types.Session) error {
saveCalled = true
return nil
}
p := NewPWD(docker, tasks, broadcast, storage)
p := NewPWD(docker, tasks, ev, storage)
before := time.Now()
@@ -166,10 +167,10 @@ func TestSessionSetup(t *testing.T) {
return nil, nil
}
tasks := &mockTasks{}
broadcast := &mockBroadcast{}
ev := event.NewLocalBroker()
storage := &mockStorage{}
p := NewPWD(dock, tasks, broadcast, storage)
p := NewPWD(dock, tasks, ev, storage)
s, e := p.SessionNew(time.Hour, "", "", "")
assert.Nil(t, e)

View File

@@ -15,6 +15,7 @@ import (
"github.com/docker/docker/client"
"github.com/docker/go-connections/tlsconfig"
"github.com/play-with-docker/play-with-docker/docker"
"github.com/play-with-docker/play-with-docker/event"
"github.com/play-with-docker/play-with-docker/pwd/types"
)
@@ -28,7 +29,7 @@ type SchedulerApi interface {
}
type scheduler struct {
broadcast BroadcastApi
event event.EventApi
periodicTasks []periodicTask
}
@@ -102,7 +103,7 @@ func (sch *scheduler) Schedule(s *types.Session) {
sort.Sort(ins.Ports)
ins.CleanUsedPorts()
sch.broadcast.BroadcastTo(ins.Session.Id, "instance stats", ins.Name, ins.Mem, ins.Cpu, ins.IsManager, ins.Ports)
sch.event.Emit(event.INSTANCE_STATS, ins.Session.Id, ins.Name, ins.Mem, ins.Cpu, ins.IsManager, ins.Ports)
}
}
}()
@@ -111,8 +112,8 @@ func (sch *scheduler) Schedule(s *types.Session) {
func (sch *scheduler) Unschedule(s *types.Session) {
}
func NewScheduler(b BroadcastApi, d docker.DockerApi) *scheduler {
s := &scheduler{broadcast: b}
func NewScheduler(e event.EventApi, d docker.DockerApi) *scheduler {
s := &scheduler{event: e}
s.periodicTasks = []periodicTask{&collectStatsTask{docker: d}, &checkSwarmStatusTask{}, &checkUsedPortsTask{}, &checkSwarmUsedPortsTask{}}
return s
}