Add session templates
This commit is contained in:
@@ -14,6 +14,10 @@ type mockDocker struct {
|
||||
connectNetwork func(container, network, ip string) (string, error)
|
||||
containerResize func(string, uint, uint) error
|
||||
createContainer func(opts docker.CreateContainerOpts) (string, error)
|
||||
execAttach func(instanceName string, command []string, out io.Writer) (int, error)
|
||||
new func(ip string, cert, key []byte) (docker.DockerApi, error)
|
||||
swarmInit func() (*docker.SwarmTokens, error)
|
||||
swarmJoin func(addr, token string) error
|
||||
}
|
||||
|
||||
func (m *mockDocker) CreateNetwork(id string) error {
|
||||
@@ -64,6 +68,9 @@ func (m *mockDocker) CreateContainer(opts docker.CreateContainerOpts) (string, e
|
||||
return "10.0.0.1", nil
|
||||
}
|
||||
func (m *mockDocker) ExecAttach(instanceName string, command []string, out io.Writer) (int, error) {
|
||||
if m.execAttach != nil {
|
||||
return m.execAttach(instanceName, command, out)
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
func (m *mockDocker) DisconnectNetwork(containerId, networkId string) error {
|
||||
@@ -75,6 +82,24 @@ func (m *mockDocker) DeleteNetwork(id string) error {
|
||||
func (m *mockDocker) Exec(instanceName string, command []string) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
func (m *mockDocker) New(ip string, cert, key []byte) (docker.DockerApi, error) {
|
||||
if m.new != nil {
|
||||
return m.new(ip, cert, key)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockDocker) SwarmInit() (*docker.SwarmTokens, error) {
|
||||
if m.swarmInit != nil {
|
||||
return m.swarmInit()
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockDocker) SwarmJoin(addr, token string) error {
|
||||
if m.swarmJoin != nil {
|
||||
return m.swarmJoin(addr, token)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type mockConn struct {
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ type PWDApi interface {
|
||||
SessionDeployStack(session *Session) error
|
||||
SessionGet(id string) *Session
|
||||
SessionLoadAndPrepare() error
|
||||
SessionSetup(session *Session, conf SessionSetupConf) error
|
||||
|
||||
InstanceNew(session *Session, conf InstanceConfig) (*Instance, error)
|
||||
InstanceResizeTerminal(instance *Instance, cols, rows uint) error
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/play-with-docker/play-with-docker/config"
|
||||
"github.com/play-with-docker/play-with-docker/docker"
|
||||
"github.com/twinj/uuid"
|
||||
)
|
||||
|
||||
@@ -23,6 +24,17 @@ func (s *sessionBuilderWriter) Write(p []byte) (n int, err error) {
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
type SessionSetupConf struct {
|
||||
Instances []SessionSetupInstanceConf `json:"instances"`
|
||||
}
|
||||
|
||||
type SessionSetupInstanceConf struct {
|
||||
Image string `json:"image"`
|
||||
Hostname string `json:"hostname"`
|
||||
IsSwarmManager bool `json:"is_swarm_manager"`
|
||||
IsSwarmWorker bool `json:"is_swarm_worker"`
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
rw sync.Mutex
|
||||
Id string `json:"id"`
|
||||
@@ -209,6 +221,60 @@ func (p *pwd) SessionLoadAndPrepare() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *pwd) SessionSetup(session *Session, conf SessionSetupConf) error {
|
||||
var tokens *docker.SwarmTokens = nil
|
||||
var firstSwarmManager *Instance = nil
|
||||
|
||||
// First create all instances and record who is a swarm manager and who is a swarm worker
|
||||
for _, conf := range conf.Instances {
|
||||
instanceConf := InstanceConfig{
|
||||
ImageName: conf.Image,
|
||||
Hostname: conf.Hostname,
|
||||
}
|
||||
i, err := p.InstanceNew(session, instanceConf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if conf.IsSwarmManager || conf.IsSwarmWorker {
|
||||
// check if we have connection to the daemon, if not, create it
|
||||
if i.docker == nil {
|
||||
dock, err := p.docker.New(i.IP, i.Cert, i.Key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.docker = dock
|
||||
}
|
||||
}
|
||||
if conf.IsSwarmManager {
|
||||
// this is a swarm manager
|
||||
// if no swarm cluster has been initiated, then initiate it!
|
||||
if firstSwarmManager == nil {
|
||||
tkns, err := i.docker.SwarmInit()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tokens = tkns
|
||||
firstSwarmManager = i
|
||||
} else {
|
||||
// cluster has already been initiated, join as manager
|
||||
err := i.docker.SwarmJoin(fmt.Sprintf("%s:2377", firstSwarmManager.IP), tokens.Manager)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if conf.IsSwarmWorker {
|
||||
// this is a swarm worker
|
||||
err := i.docker.SwarmJoin(fmt.Sprintf("%s:2377", firstSwarmManager.IP), tokens.Worker)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// This function should be called any time a session needs to be prepared:
|
||||
// 1. Like when it is created
|
||||
// 2. When it was loaded from storage
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package pwd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/play-with-docker/play-with-docker/config"
|
||||
"github.com/play-with-docker/play-with-docker/docker"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -80,3 +82,190 @@ func TestSessionNew(t *testing.T) {
|
||||
assert.Equal(t, expectedSessions, sessions)
|
||||
assert.True(t, saveCalled)
|
||||
}
|
||||
|
||||
func TestSessionSetup(t *testing.T) {
|
||||
ips := []string{"10.0.0.1", "10.0.0.2", "10.0.0.3", "10.0.0.4", "10.0.0.5"}
|
||||
nextIp := 0
|
||||
swarmInitOnMaster1 := false
|
||||
manager2JoinedHasManager := false
|
||||
manager3JoinedHasManager := false
|
||||
worker1JoinedHasWorker := false
|
||||
|
||||
dock := &mockDocker{}
|
||||
dock.createContainer = func(opts docker.CreateContainerOpts) (string, error) {
|
||||
ip := ips[nextIp]
|
||||
nextIp++
|
||||
return ip, nil
|
||||
}
|
||||
dock.new = func(ip string, cert, key []byte) (docker.DockerApi, error) {
|
||||
if ip == "10.0.0.1" {
|
||||
return &mockDocker{
|
||||
swarmInit: func() (*docker.SwarmTokens, error) {
|
||||
swarmInitOnMaster1 = true
|
||||
return &docker.SwarmTokens{Worker: "worker-join-token", Manager: "manager-join-token"}, nil
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
if ip == "10.0.0.2" {
|
||||
return &mockDocker{
|
||||
swarmInit: func() (*docker.SwarmTokens, error) {
|
||||
assert.Fail(t, "Shouldn't have reached here.")
|
||||
return nil, nil
|
||||
},
|
||||
swarmJoin: func(addr, token string) error {
|
||||
if addr == "10.0.0.1:2377" && token == "manager-join-token" {
|
||||
manager2JoinedHasManager = true
|
||||
return nil
|
||||
}
|
||||
assert.Fail(t, "Shouldn't have reached here.")
|
||||
return nil
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
if ip == "10.0.0.3" {
|
||||
return &mockDocker{
|
||||
swarmInit: func() (*docker.SwarmTokens, error) {
|
||||
assert.Fail(t, "Shouldn't have reached here.")
|
||||
return nil, nil
|
||||
},
|
||||
swarmJoin: func(addr, token string) error {
|
||||
if addr == "10.0.0.1:2377" && token == "manager-join-token" {
|
||||
manager3JoinedHasManager = true
|
||||
return nil
|
||||
}
|
||||
assert.Fail(t, "Shouldn't have reached here.")
|
||||
return nil
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
if ip == "10.0.0.4" {
|
||||
return &mockDocker{
|
||||
swarmInit: func() (*docker.SwarmTokens, error) {
|
||||
assert.Fail(t, "Shouldn't have reached here.")
|
||||
return nil, nil
|
||||
},
|
||||
swarmJoin: func(addr, token string) error {
|
||||
if addr == "10.0.0.1:2377" && token == "worker-join-token" {
|
||||
worker1JoinedHasWorker = true
|
||||
return nil
|
||||
}
|
||||
assert.Fail(t, "Shouldn't have reached here.")
|
||||
return nil
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
assert.Fail(t, "Shouldn't have reached here.")
|
||||
return nil, nil
|
||||
}
|
||||
tasks := &mockTasks{}
|
||||
broadcast := &mockBroadcast{}
|
||||
storage := &mockStorage{}
|
||||
|
||||
p := NewPWD(dock, tasks, broadcast, storage)
|
||||
s, e := p.SessionNew(time.Hour, "", "")
|
||||
assert.Nil(t, e)
|
||||
|
||||
err := p.SessionSetup(s, SessionSetupConf{
|
||||
Instances: []SessionSetupInstanceConf{
|
||||
{
|
||||
Image: "franela/dind",
|
||||
IsSwarmManager: true,
|
||||
Hostname: "manager1",
|
||||
},
|
||||
{
|
||||
IsSwarmManager: true,
|
||||
Hostname: "manager2",
|
||||
},
|
||||
{
|
||||
Image: "franela/dind:overlay2-dev",
|
||||
IsSwarmManager: true,
|
||||
Hostname: "manager3",
|
||||
},
|
||||
{
|
||||
IsSwarmWorker: true,
|
||||
Hostname: "worker1",
|
||||
},
|
||||
{
|
||||
Hostname: "other",
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 5, len(s.Instances))
|
||||
|
||||
manager1 := fmt.Sprintf("%s_manager1", s.Id[:8])
|
||||
manager1Received := *s.Instances[manager1]
|
||||
assert.Equal(t, Instance{
|
||||
Name: manager1,
|
||||
Image: "franela/dind",
|
||||
Hostname: "manager1",
|
||||
IP: "10.0.0.1",
|
||||
Alias: "",
|
||||
IsDockerHost: true,
|
||||
session: s,
|
||||
conn: manager1Received.conn,
|
||||
docker: manager1Received.docker,
|
||||
}, manager1Received)
|
||||
|
||||
manager2 := fmt.Sprintf("%s_manager2", s.Id[:8])
|
||||
manager2Received := *s.Instances[manager2]
|
||||
assert.Equal(t, Instance{
|
||||
Name: manager2,
|
||||
Image: "franela/dind",
|
||||
Hostname: "manager2",
|
||||
IP: "10.0.0.2",
|
||||
Alias: "",
|
||||
IsDockerHost: true,
|
||||
session: s,
|
||||
conn: manager2Received.conn,
|
||||
docker: manager2Received.docker,
|
||||
}, manager2Received)
|
||||
|
||||
manager3 := fmt.Sprintf("%s_manager3", s.Id[:8])
|
||||
manager3Received := *s.Instances[manager3]
|
||||
assert.Equal(t, Instance{
|
||||
Name: manager3,
|
||||
Image: "franela/dind:overlay2-dev",
|
||||
Hostname: "manager3",
|
||||
IP: "10.0.0.3",
|
||||
Alias: "",
|
||||
IsDockerHost: true,
|
||||
session: s,
|
||||
conn: manager3Received.conn,
|
||||
docker: manager3Received.docker,
|
||||
}, manager3Received)
|
||||
|
||||
worker1 := fmt.Sprintf("%s_worker1", s.Id[:8])
|
||||
worker1Received := *s.Instances[worker1]
|
||||
assert.Equal(t, Instance{
|
||||
Name: worker1,
|
||||
Image: "franela/dind",
|
||||
Hostname: "worker1",
|
||||
IP: "10.0.0.4",
|
||||
Alias: "",
|
||||
IsDockerHost: true,
|
||||
session: s,
|
||||
conn: worker1Received.conn,
|
||||
docker: worker1Received.docker,
|
||||
}, worker1Received)
|
||||
|
||||
other := fmt.Sprintf("%s_other", s.Id[:8])
|
||||
otherReceived := *s.Instances[other]
|
||||
assert.Equal(t, Instance{
|
||||
Name: other,
|
||||
Image: "franela/dind",
|
||||
Hostname: "other",
|
||||
IP: "10.0.0.5",
|
||||
Alias: "",
|
||||
IsDockerHost: true,
|
||||
session: s,
|
||||
conn: otherReceived.conn,
|
||||
docker: otherReceived.docker,
|
||||
}, otherReceived)
|
||||
|
||||
assert.True(t, swarmInitOnMaster1)
|
||||
assert.True(t, manager2JoinedHasManager)
|
||||
assert.True(t, manager3JoinedHasManager)
|
||||
assert.True(t, worker1JoinedHasWorker)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user