Refactor storage to support shallow types.
Add Client to storage. Fix client resizing issues.
This commit is contained in:
@@ -2,7 +2,6 @@ package pwd
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/play-with-docker/play-with-docker/event"
|
||||
@@ -11,9 +10,10 @@ import (
|
||||
|
||||
func (p *pwd) ClientNew(id string, session *types.Session) *types.Client {
|
||||
defer observeAction("ClientNew", time.Now())
|
||||
c := &types.Client{Id: id, Session: session}
|
||||
session.Clients = append(session.Clients, c)
|
||||
p.clientCount = atomic.AddInt32(&p.clientCount, 1)
|
||||
c := &types.Client{Id: id, SessionId: session.Id}
|
||||
if err := p.storage.ClientPut(c); err != nil {
|
||||
log.Println("Error saving client", err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -22,38 +22,46 @@ func (p *pwd) ClientResizeViewPort(c *types.Client, cols, rows uint) {
|
||||
c.ViewPort.Rows = rows
|
||||
c.ViewPort.Cols = cols
|
||||
|
||||
p.notifyClientSmallestViewPort(c.Session)
|
||||
if err := p.storage.ClientPut(c); err != nil {
|
||||
log.Println("Error saving client", err)
|
||||
return
|
||||
}
|
||||
p.notifyClientSmallestViewPort(c.SessionId)
|
||||
}
|
||||
|
||||
func (p *pwd) ClientClose(client *types.Client) {
|
||||
defer observeAction("ClientClose", time.Now())
|
||||
// Client has disconnected. Remove from session and recheck terminal sizes.
|
||||
session := client.Session
|
||||
for i, cl := range session.Clients {
|
||||
if cl.Id == client.Id {
|
||||
session.Clients = append(session.Clients[:i], session.Clients[i+1:]...)
|
||||
p.clientCount = atomic.AddInt32(&p.clientCount, -1)
|
||||
break
|
||||
}
|
||||
if err := p.storage.ClientDelete(client.Id); err != nil {
|
||||
log.Println("Error deleting client", err)
|
||||
return
|
||||
}
|
||||
if len(session.Clients) > 0 {
|
||||
p.notifyClientSmallestViewPort(session)
|
||||
}
|
||||
p.setGauges()
|
||||
p.notifyClientSmallestViewPort(client.SessionId)
|
||||
}
|
||||
|
||||
func (p *pwd) ClientCount() int {
|
||||
return int(atomic.LoadInt32(&p.clientCount))
|
||||
count, err := p.storage.ClientCount()
|
||||
if err != nil {
|
||||
log.Println("Error counting clients", err)
|
||||
return 0
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func (p *pwd) notifyClientSmallestViewPort(session *types.Session) {
|
||||
vp := p.SessionGetSmallestViewPort(session)
|
||||
func (p *pwd) notifyClientSmallestViewPort(sessionId string) {
|
||||
instances, err := p.storage.InstanceFindBySessionId(sessionId)
|
||||
if err != nil {
|
||||
log.Printf("Error finding instances for session [%s]. Got: %v\n", sessionId, err)
|
||||
return
|
||||
}
|
||||
|
||||
vp := p.SessionGetSmallestViewPort(sessionId)
|
||||
// Resize all terminals in the session
|
||||
p.event.Emit(event.INSTANCE_VIEWPORT_RESIZE, session.Id, vp.Cols, vp.Rows)
|
||||
for _, instance := range session.Instances {
|
||||
for _, instance := range instances {
|
||||
err := p.InstanceResizeTerminal(instance, vp.Rows, vp.Cols)
|
||||
if err != nil {
|
||||
log.Println("Error resizing terminal", err)
|
||||
}
|
||||
}
|
||||
p.event.Emit(event.INSTANCE_VIEWPORT_RESIZE, sessionId, vp.Cols, vp.Rows)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ func TestClientNew(t *testing.T) {
|
||||
_d := &docker.Mock{}
|
||||
_e := &event.Mock{}
|
||||
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f))
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f, _s))
|
||||
sp := provisioner.NewOverlaySessionProvisioner(_f)
|
||||
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
@@ -33,6 +33,8 @@ func TestClientNew(t *testing.T) {
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
_s.On("InstanceCount").Return(0, nil)
|
||||
_s.On("ClientCount").Return(1, nil)
|
||||
_s.On("ClientPut", mock.AnythingOfType("*types.Client")).Return(nil)
|
||||
|
||||
var nilArgs []interface{}
|
||||
_e.M.On("Emit", event.SESSION_NEW, "aaaabbbbcccc", nilArgs).Return()
|
||||
@@ -45,8 +47,7 @@ func TestClientNew(t *testing.T) {
|
||||
|
||||
client := p.ClientNew("foobar", session)
|
||||
|
||||
assert.Equal(t, types.Client{Id: "foobar", Session: session, ViewPort: types.ViewPort{Cols: 0, Rows: 0}}, *client)
|
||||
assert.Contains(t, session.Clients, client)
|
||||
assert.Equal(t, types.Client{Id: "foobar", SessionId: session.Id, ViewPort: types.ViewPort{Cols: 0, Rows: 0}}, *client)
|
||||
|
||||
_d.AssertExpectations(t)
|
||||
_f.AssertExpectations(t)
|
||||
@@ -61,7 +62,7 @@ func TestClientCount(t *testing.T) {
|
||||
_g := &mockGenerator{}
|
||||
_d := &docker.Mock{}
|
||||
_e := &event.Mock{}
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f))
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f, _s))
|
||||
sp := provisioner.NewOverlaySessionProvisioner(_f)
|
||||
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
@@ -70,6 +71,8 @@ func TestClientCount(t *testing.T) {
|
||||
_d.On("GetDaemonHost").Return("localhost")
|
||||
_d.On("ConnectNetwork", config.L2ContainerName, "aaaabbbbcccc", "").Return("10.0.0.1", nil)
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("ClientPut", mock.AnythingOfType("*types.Client")).Return(nil)
|
||||
_s.On("ClientCount").Return(1, nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
_s.On("InstanceCount").Return(-1, nil)
|
||||
var nilArgs []interface{}
|
||||
@@ -98,7 +101,7 @@ func TestClientResizeViewPort(t *testing.T) {
|
||||
_g := &mockGenerator{}
|
||||
_d := &docker.Mock{}
|
||||
_e := &event.Mock{}
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f))
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f, _s))
|
||||
sp := provisioner.NewOverlaySessionProvisioner(_f)
|
||||
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
@@ -109,6 +112,9 @@ func TestClientResizeViewPort(t *testing.T) {
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
_s.On("InstanceCount").Return(0, nil)
|
||||
_s.On("InstanceFindBySessionId", "aaaabbbbcccc").Return([]*types.Instance{}, nil)
|
||||
_s.On("ClientPut", mock.AnythingOfType("*types.Client")).Return(nil)
|
||||
_s.On("ClientCount").Return(1, nil)
|
||||
var nilArgs []interface{}
|
||||
_e.M.On("Emit", event.SESSION_NEW, "aaaabbbbcccc", nilArgs).Return()
|
||||
|
||||
@@ -119,6 +125,7 @@ func TestClientResizeViewPort(t *testing.T) {
|
||||
session, err := p.SessionNew(time.Hour, "", "", "")
|
||||
assert.Nil(t, err)
|
||||
client := p.ClientNew("foobar", session)
|
||||
_s.On("ClientFindBySessionId", "aaaabbbbcccc").Return([]*types.Client{client}, nil)
|
||||
|
||||
p.ClientResizeViewPort(client, 80, 24)
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ func (p *pwd) InstanceUploadFromReader(instance *types.Instance, fileName, dest
|
||||
|
||||
func (p *pwd) InstanceGet(session *types.Session, name string) *types.Instance {
|
||||
defer observeAction("InstanceGet", time.Now())
|
||||
instance, err := p.storage.InstanceGet(session.Id, name)
|
||||
instance, err := p.storage.InstanceGet(name)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return nil
|
||||
@@ -59,14 +59,14 @@ func (p *pwd) InstanceGet(session *types.Session, name string) *types.Instance {
|
||||
return instance
|
||||
}
|
||||
|
||||
func (p *pwd) InstanceFindByIP(sessionId, ip string) *types.Instance {
|
||||
defer observeAction("InstanceFindByIP", time.Now())
|
||||
i, err := p.storage.InstanceFindByIP(sessionId, ip)
|
||||
func (p *pwd) InstanceFindBySession(session *types.Session) ([]*types.Instance, error) {
|
||||
defer observeAction("InstanceFindBySession", time.Now())
|
||||
instances, err := p.storage.InstanceFindBySessionId(session.Id)
|
||||
if err != nil {
|
||||
return nil
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return i
|
||||
return instances, nil
|
||||
}
|
||||
|
||||
func (p *pwd) InstanceDelete(session *types.Session, instance *types.Instance) error {
|
||||
@@ -83,7 +83,7 @@ func (p *pwd) InstanceDelete(session *types.Session, instance *types.Instance) e
|
||||
return err
|
||||
}
|
||||
|
||||
if err := p.storage.InstanceDelete(session.Id, instance.Name); err != nil {
|
||||
if err := p.storage.InstanceDelete(instance.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -99,6 +99,16 @@ func (p *pwd) InstanceNew(session *types.Session, conf types.InstanceConfig) (*t
|
||||
session.Lock()
|
||||
defer session.Unlock()
|
||||
|
||||
instances, err := p.storage.InstanceFindBySessionId(session.Id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(instances) >= 5 {
|
||||
return nil, sessionComplete
|
||||
}
|
||||
|
||||
prov, err := p.getProvisioner(conf.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -109,12 +119,7 @@ func (p *pwd) InstanceNew(session *types.Session, conf types.InstanceConfig) (*t
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if session.Instances == nil {
|
||||
session.Instances = make(map[string]*types.Instance)
|
||||
}
|
||||
session.Instances[instance.Name] = instance
|
||||
|
||||
err = p.storage.InstanceCreate(session.Id, instance)
|
||||
err = p.storage.InstancePut(instance)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func TestInstanceResizeTerminal(t *testing.T) {
|
||||
_s := &storage.Mock{}
|
||||
_g := &mockGenerator{}
|
||||
_e := &event.Mock{}
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f))
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f, _s))
|
||||
sp := provisioner.NewOverlaySessionProvisioner(_f)
|
||||
|
||||
_d.On("ContainerResize", "foobar", uint(24), uint(80)).Return(nil)
|
||||
@@ -47,7 +47,7 @@ func TestInstanceNew(t *testing.T) {
|
||||
_s := &storage.Mock{}
|
||||
_g := &mockGenerator{}
|
||||
_e := &event.Mock{}
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f))
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f, _s))
|
||||
sp := provisioner.NewOverlaySessionProvisioner(_f)
|
||||
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
@@ -57,7 +57,9 @@ func TestInstanceNew(t *testing.T) {
|
||||
_d.On("ConnectNetwork", config.L2ContainerName, "aaaabbbbcccc", "").Return("10.0.0.1", nil)
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
_s.On("ClientCount").Return(0, nil)
|
||||
_s.On("InstanceCount").Return(0, nil)
|
||||
_s.On("InstanceFindBySessionId", "aaaabbbbcccc").Return([]*types.Instance{}, nil)
|
||||
|
||||
var nilArgs []interface{}
|
||||
_e.M.On("Emit", event.SESSION_NEW, "aaaabbbbcccc", nilArgs).Return()
|
||||
@@ -75,7 +77,6 @@ func TestInstanceNew(t *testing.T) {
|
||||
RoutableIP: "10.0.0.1",
|
||||
Image: config.GetDindImageName(),
|
||||
SessionId: session.Id,
|
||||
Session: session,
|
||||
SessionHost: session.Host,
|
||||
ProxyHost: router.EncodeHost(session.Id, "10.0.0.1", router.HostOpts{}),
|
||||
}
|
||||
@@ -94,7 +95,7 @@ func TestInstanceNew(t *testing.T) {
|
||||
}
|
||||
_d.On("CreateContainer", expectedContainerOpts).Return(nil)
|
||||
_d.On("GetContainerIPs", expectedInstance.Name).Return(map[string]string{session.Id: "10.0.0.1"}, nil)
|
||||
_s.On("InstanceCreate", "aaaabbbbcccc", mock.AnythingOfType("*types.Instance")).Return(nil)
|
||||
_s.On("InstancePut", mock.AnythingOfType("*types.Instance")).Return(nil)
|
||||
_e.M.On("Emit", event.INSTANCE_NEW, "aaaabbbbcccc", []interface{}{"aaaabbbb_node1", "10.0.0.1", "node1", "ip10-0-0-1-aaaabbbbcccc"}).Return()
|
||||
|
||||
instance, err := p.InstanceNew(session, types.InstanceConfig{Host: "something.play-with-docker.com"})
|
||||
@@ -115,7 +116,7 @@ func TestInstanceNew_WithNotAllowedImage(t *testing.T) {
|
||||
_s := &storage.Mock{}
|
||||
_g := &mockGenerator{}
|
||||
_e := &event.Mock{}
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f))
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f, _s))
|
||||
sp := provisioner.NewOverlaySessionProvisioner(_f)
|
||||
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
@@ -125,7 +126,9 @@ func TestInstanceNew_WithNotAllowedImage(t *testing.T) {
|
||||
_d.On("ConnectNetwork", config.L2ContainerName, "aaaabbbbcccc", "").Return("10.0.0.1", nil)
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
_s.On("ClientCount").Return(0, nil)
|
||||
_s.On("InstanceCount").Return(0, nil)
|
||||
_s.On("InstanceFindBySessionId", "aaaabbbbcccc").Return([]*types.Instance{}, nil)
|
||||
|
||||
var nilArgs []interface{}
|
||||
_e.M.On("Emit", event.SESSION_NEW, "aaaabbbbcccc", nilArgs).Return()
|
||||
@@ -144,7 +147,6 @@ func TestInstanceNew_WithNotAllowedImage(t *testing.T) {
|
||||
RoutableIP: "10.0.0.1",
|
||||
Image: "redis",
|
||||
SessionId: session.Id,
|
||||
Session: session,
|
||||
SessionHost: session.Host,
|
||||
ProxyHost: router.EncodeHost(session.Id, "10.0.0.1", router.HostOpts{}),
|
||||
}
|
||||
@@ -162,7 +164,7 @@ func TestInstanceNew_WithNotAllowedImage(t *testing.T) {
|
||||
}
|
||||
_d.On("CreateContainer", expectedContainerOpts).Return(nil)
|
||||
_d.On("GetContainerIPs", expectedInstance.Name).Return(map[string]string{session.Id: "10.0.0.1"}, nil)
|
||||
_s.On("InstanceCreate", "aaaabbbbcccc", mock.AnythingOfType("*types.Instance")).Return(nil)
|
||||
_s.On("InstancePut", mock.AnythingOfType("*types.Instance")).Return(nil)
|
||||
_e.M.On("Emit", event.INSTANCE_NEW, "aaaabbbbcccc", []interface{}{"aaaabbbb_node1", "10.0.0.1", "node1", "ip10-0-0-1-aaaabbbbcccc"}).Return()
|
||||
|
||||
instance, err := p.InstanceNew(session, types.InstanceConfig{ImageName: "redis"})
|
||||
@@ -184,7 +186,7 @@ func TestInstanceNew_WithCustomHostname(t *testing.T) {
|
||||
_g := &mockGenerator{}
|
||||
_e := &event.Mock{}
|
||||
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f))
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f, _s))
|
||||
sp := provisioner.NewOverlaySessionProvisioner(_f)
|
||||
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
@@ -194,7 +196,9 @@ func TestInstanceNew_WithCustomHostname(t *testing.T) {
|
||||
_d.On("ConnectNetwork", config.L2ContainerName, "aaaabbbbcccc", "").Return("10.0.0.1", nil)
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
_s.On("ClientCount").Return(0, nil)
|
||||
_s.On("InstanceCount").Return(0, nil)
|
||||
_s.On("InstanceFindBySessionId", "aaaabbbbcccc").Return([]*types.Instance{}, nil)
|
||||
|
||||
var nilArgs []interface{}
|
||||
_e.M.On("Emit", event.SESSION_NEW, "aaaabbbbcccc", nilArgs).Return()
|
||||
@@ -211,7 +215,6 @@ func TestInstanceNew_WithCustomHostname(t *testing.T) {
|
||||
IP: "10.0.0.1",
|
||||
RoutableIP: "10.0.0.1",
|
||||
Image: "redis",
|
||||
Session: session,
|
||||
SessionHost: session.Host,
|
||||
SessionId: session.Id,
|
||||
ProxyHost: router.EncodeHost(session.Id, "10.0.0.1", router.HostOpts{}),
|
||||
@@ -231,7 +234,7 @@ func TestInstanceNew_WithCustomHostname(t *testing.T) {
|
||||
|
||||
_d.On("CreateContainer", expectedContainerOpts).Return(nil)
|
||||
_d.On("GetContainerIPs", expectedInstance.Name).Return(map[string]string{session.Id: "10.0.0.1"}, nil)
|
||||
_s.On("InstanceCreate", "aaaabbbbcccc", mock.AnythingOfType("*types.Instance")).Return(nil)
|
||||
_s.On("InstancePut", mock.AnythingOfType("*types.Instance")).Return(nil)
|
||||
_e.M.On("Emit", event.INSTANCE_NEW, "aaaabbbbcccc", []interface{}{"aaaabbbb_redis-master", "10.0.0.1", "redis-master", "ip10-0-0-1-aaaabbbbcccc"}).Return()
|
||||
|
||||
instance, err := p.InstanceNew(session, types.InstanceConfig{ImageName: "redis", Hostname: "redis-master"})
|
||||
|
||||
11
pwd/mock.go
11
pwd/mock.go
@@ -23,8 +23,8 @@ func (m *Mock) SessionClose(session *types.Session) error {
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (m *Mock) SessionGetSmallestViewPort(session *types.Session) types.ViewPort {
|
||||
args := m.Called(session)
|
||||
func (m *Mock) SessionGetSmallestViewPort(sessionId string) types.ViewPort {
|
||||
args := m.Called(sessionId)
|
||||
return args.Get(0).(types.ViewPort)
|
||||
}
|
||||
|
||||
@@ -72,10 +72,9 @@ func (m *Mock) InstanceGet(session *types.Session, name string) *types.Instance
|
||||
args := m.Called(session, name)
|
||||
return args.Get(0).(*types.Instance)
|
||||
}
|
||||
|
||||
func (m *Mock) InstanceFindByIP(session, ip string) *types.Instance {
|
||||
args := m.Called(session, ip)
|
||||
return args.Get(0).(*types.Instance)
|
||||
func (m *Mock) InstanceFindBySession(session *types.Session) ([]*types.Instance, error) {
|
||||
args := m.Called(session)
|
||||
return args.Get(0).([]*types.Instance), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *Mock) InstanceDelete(session *types.Session, instance *types.Instance) error {
|
||||
|
||||
17
pwd/pwd.go
17
pwd/pwd.go
@@ -1,6 +1,7 @@
|
||||
package pwd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
@@ -79,10 +80,22 @@ func (m *mockGenerator) NewId() string {
|
||||
return args.String(0)
|
||||
}
|
||||
|
||||
var sessionComplete = errors.New("Session is complete")
|
||||
|
||||
func SessionComplete(e error) bool {
|
||||
return e == sessionComplete
|
||||
}
|
||||
|
||||
var sessionNotEmpty = errors.New("Session is not empty")
|
||||
|
||||
func SessionNotEmpty(e error) bool {
|
||||
return e == sessionNotEmpty
|
||||
}
|
||||
|
||||
type PWDApi interface {
|
||||
SessionNew(duration time.Duration, stack string, stackName, imageName string) (*types.Session, error)
|
||||
SessionClose(session *types.Session) error
|
||||
SessionGetSmallestViewPort(session *types.Session) types.ViewPort
|
||||
SessionGetSmallestViewPort(sessionId string) types.ViewPort
|
||||
SessionDeployStack(session *types.Session) error
|
||||
SessionGet(id string) *types.Session
|
||||
SessionSetup(session *types.Session, conf SessionSetupConf) error
|
||||
@@ -93,7 +106,7 @@ type PWDApi interface {
|
||||
InstanceUploadFromUrl(instance *types.Instance, fileName, dest, url string) error
|
||||
InstanceUploadFromReader(instance *types.Instance, fileName, dest string, reader io.Reader) error
|
||||
InstanceGet(session *types.Session, name string) *types.Instance
|
||||
InstanceFindByIP(sessionId, ip string) *types.Instance
|
||||
InstanceFindBySession(session *types.Session) ([]*types.Instance, error)
|
||||
InstanceDelete(session *types.Session, instance *types.Instance) error
|
||||
InstanceExec(instance *types.Instance, cmd []string) (int, error)
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"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"
|
||||
)
|
||||
|
||||
var preparedSessions = map[string]bool{}
|
||||
@@ -46,7 +45,6 @@ func (p *pwd) SessionNew(duration time.Duration, stack, stackName, imageName str
|
||||
|
||||
s := &types.Session{}
|
||||
s.Id = p.generator.NewId()
|
||||
s.Instances = map[string]*types.Instance{}
|
||||
s.CreatedAt = time.Now()
|
||||
s.ExpiresAt = s.CreatedAt.Add(duration)
|
||||
s.Ready = true
|
||||
@@ -81,21 +79,14 @@ func (p *pwd) SessionNew(duration time.Duration, stack, stackName, imageName str
|
||||
func (p *pwd) SessionClose(s *types.Session) error {
|
||||
defer observeAction("SessionClose", time.Now())
|
||||
|
||||
updatedSession, err := p.storage.SessionGet(s.Id)
|
||||
if err != nil {
|
||||
if storage.NotFound(err) {
|
||||
log.Printf("Session with id [%s] was not found in storage.\n", s.Id)
|
||||
return err
|
||||
} else {
|
||||
log.Printf("Couldn't close session. Got: %s\n", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
s = updatedSession
|
||||
|
||||
log.Printf("Starting clean up of session [%s]\n", s.Id)
|
||||
g, _ := errgroup.WithContext(context.Background())
|
||||
for _, i := range s.Instances {
|
||||
instances, err := p.storage.InstanceFindBySessionId(s.Id)
|
||||
if err != nil {
|
||||
log.Printf("Could not find instances in session %s. Got %v\n", s.Id, err)
|
||||
return err
|
||||
}
|
||||
for _, i := range instances {
|
||||
i := i
|
||||
g.Go(func() error {
|
||||
return p.InstanceDelete(s, i)
|
||||
@@ -124,13 +115,22 @@ func (p *pwd) SessionClose(s *types.Session) error {
|
||||
|
||||
}
|
||||
|
||||
func (p *pwd) SessionGetSmallestViewPort(s *types.Session) types.ViewPort {
|
||||
func (p *pwd) SessionGetSmallestViewPort(sessionId string) types.ViewPort {
|
||||
defer observeAction("SessionGetSmallestViewPort", time.Now())
|
||||
|
||||
minRows := s.Clients[0].ViewPort.Rows
|
||||
minCols := s.Clients[0].ViewPort.Cols
|
||||
clients, err := p.storage.ClientFindBySessionId(sessionId)
|
||||
if err != nil {
|
||||
log.Printf("Error finding clients for session [%s]. Got: %v\n", sessionId, err)
|
||||
return types.ViewPort{Rows: 24, Cols: 80}
|
||||
}
|
||||
if len(clients) == 0 {
|
||||
log.Printf("Session [%s] doesn't have clients. Returning default viewport\n", sessionId)
|
||||
return types.ViewPort{Rows: 24, Cols: 80}
|
||||
}
|
||||
minRows := clients[0].ViewPort.Rows
|
||||
minCols := clients[0].ViewPort.Cols
|
||||
|
||||
for _, c := range s.Clients {
|
||||
for _, c := range clients {
|
||||
minRows = uint(math.Min(float64(minRows), float64(c.ViewPort.Rows)))
|
||||
minCols = uint(math.Min(float64(minCols), float64(c.ViewPort.Cols)))
|
||||
}
|
||||
@@ -206,6 +206,15 @@ func (p *pwd) SessionSetup(session *types.Session, conf SessionSetupConf) error
|
||||
var tokens *docker.SwarmTokens = nil
|
||||
var firstSwarmManager *types.Instance = nil
|
||||
|
||||
instances, err := p.storage.InstanceFindBySessionId(session.Id)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
if len(instances) > 0 {
|
||||
return sessionNotEmpty
|
||||
}
|
||||
|
||||
// first look for a swarm manager and create it
|
||||
for _, conf := range conf.Instances {
|
||||
if conf.IsSwarmManager {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"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/provisioner"
|
||||
"github.com/play-with-docker/play-with-docker/pwd/types"
|
||||
"github.com/play-with-docker/play-with-docker/storage"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
@@ -23,7 +24,7 @@ func TestSessionNew(t *testing.T) {
|
||||
_g := &mockGenerator{}
|
||||
_e := &event.Mock{}
|
||||
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f))
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f, _s))
|
||||
sp := provisioner.NewOverlaySessionProvisioner(_f)
|
||||
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
@@ -34,6 +35,7 @@ func TestSessionNew(t *testing.T) {
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
_s.On("InstanceCount").Return(0, nil)
|
||||
_s.On("ClientCount").Return(0, nil)
|
||||
|
||||
var nilArgs []interface{}
|
||||
_e.M.On("Emit", event.SESSION_NEW, "aaaabbbbcccc", nilArgs).Return()
|
||||
@@ -77,7 +79,7 @@ func TestSessionSetup(t *testing.T) {
|
||||
_s := &storage.Mock{}
|
||||
_g := &mockGenerator{}
|
||||
_e := &event.Mock{}
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f))
|
||||
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(_f, _s), provisioner.NewDinD(_f, _s))
|
||||
sp := provisioner.NewOverlaySessionProvisioner(_f)
|
||||
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
@@ -86,9 +88,11 @@ func TestSessionSetup(t *testing.T) {
|
||||
_d.On("GetDaemonHost").Return("localhost")
|
||||
_d.On("ConnectNetwork", config.L2ContainerName, "aaaabbbbcccc", "").Return("10.0.0.1", nil)
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("InstanceCreate", "aaaabbbbcccc", mock.AnythingOfType("*types.Instance")).Return(nil)
|
||||
_s.On("InstancePut", mock.AnythingOfType("*types.Instance")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
_s.On("ClientCount").Return(1, nil)
|
||||
_s.On("InstanceCount").Return(0, nil)
|
||||
_s.On("InstanceFindBySessionId", "aaaabbbbcccc").Return([]*types.Instance{}, nil)
|
||||
|
||||
_d.On("CreateContainer", docker.CreateContainerOpts{Image: "franela/dind", SessionId: "aaaabbbbcccc", PwdIpAddress: "10.0.0.1", ContainerName: "aaaabbbb_manager1", Hostname: "manager1", Privileged: true, HostFQDN: "localhost", Networks: []string{"aaaabbbbcccc"}}).Return(nil)
|
||||
_d.On("GetContainerIPs", "aaaabbbb_manager1").Return(map[string]string{"aaaabbbbcccc": "10.0.0.2"}, nil)
|
||||
@@ -153,8 +157,6 @@ func TestSessionSetup(t *testing.T) {
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 5, len(s.Instances))
|
||||
|
||||
_d.AssertExpectations(t)
|
||||
_f.AssertExpectations(t)
|
||||
_s.AssertExpectations(t)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package types
|
||||
|
||||
type Client struct {
|
||||
Id string
|
||||
ViewPort ViewPort
|
||||
Session *Session
|
||||
Id string `json:"id" bson:"id"`
|
||||
SessionId string `json:"session_id"`
|
||||
ViewPort ViewPort `json:"viewport"`
|
||||
}
|
||||
|
||||
type ViewPort struct {
|
||||
Rows uint
|
||||
Cols uint
|
||||
Rows uint `json:"rows"`
|
||||
Cols uint `json:"cols"`
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package types
|
||||
import "context"
|
||||
|
||||
type Instance struct {
|
||||
Image string `json:"image" bson:"image"`
|
||||
Name string `json:"name" bson:"name"`
|
||||
Image string `json:"image" bson:"image"`
|
||||
Hostname string `json:"hostname" bson:"hostname"`
|
||||
IP string `json:"ip" bson:"ip"`
|
||||
RoutableIP string `json:"routable_ip" bson:"routable_id"`
|
||||
@@ -17,13 +17,12 @@ type Instance struct {
|
||||
ProxyHost string `json:"proxy_host" bson:"proxy_host"`
|
||||
SessionHost string `json:"session_host" bson:"session_host"`
|
||||
Type string `json:"type" bson:"type"`
|
||||
Session *Session `json:"-" bson:"-"`
|
||||
ctx context.Context `json:"-" bson:"-"`
|
||||
WindowsId string `json:"-" bson:"windows_id"`
|
||||
ctx context.Context `json:"-" bson:"-"`
|
||||
}
|
||||
|
||||
type WindowsInstance struct {
|
||||
ID string `bson:"id"`
|
||||
Id string `bson:"id"`
|
||||
SessionId string `bson:"session_id"`
|
||||
}
|
||||
|
||||
|
||||
@@ -6,19 +6,16 @@ import (
|
||||
)
|
||||
|
||||
type Session struct {
|
||||
Id string `json:"id"`
|
||||
Instances map[string]*Instance `json:"instances" bson:"-"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
PwdIpAddress string `json:"pwd_ip_address"`
|
||||
Ready bool `json:"ready"`
|
||||
Stack string `json:"stack"`
|
||||
StackName string `json:"stack_name"`
|
||||
ImageName string `json:"image_name"`
|
||||
Host string `json:"host"`
|
||||
Clients []*Client `json:"-" bson:"-"`
|
||||
WindowsAssigned []*WindowsInstance `json:"-" bson:"-"`
|
||||
rw sync.Mutex `json:"-"`
|
||||
Id string `json:"id" bson:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
PwdIpAddress string `json:"pwd_ip_address"`
|
||||
Ready bool `json:"ready"`
|
||||
Stack string `json:"stack"`
|
||||
StackName string `json:"stack_name"`
|
||||
ImageName string `json:"image_name"`
|
||||
Host string `json:"host"`
|
||||
rw sync.Mutex `json:"-"`
|
||||
}
|
||||
|
||||
func (s *Session) Lock() {
|
||||
|
||||
Reference in New Issue
Block a user