diff --git a/docker/docker.go b/docker/docker.go new file mode 100644 index 0000000..b8d485c --- /dev/null +++ b/docker/docker.go @@ -0,0 +1,5 @@ +package docker + +type Docker interface { + CreateNetwork(id string) error +} diff --git a/pwd/docker_mock_test.go b/pwd/docker_mock_test.go new file mode 100644 index 0000000..325af4e --- /dev/null +++ b/pwd/docker_mock_test.go @@ -0,0 +1,9 @@ +package pwd + +type mockDocker struct { + createNetwork func(string) error +} + +func (m *mockDocker) CreateNetwork(id string) error { + return m.createNetwork(id) +} diff --git a/pwd/pwd.go b/pwd/pwd.go new file mode 100644 index 0000000..9338b53 --- /dev/null +++ b/pwd/pwd.go @@ -0,0 +1,41 @@ +package pwd + +import ( + "sync" + "time" + + "github.com/play-with-docker/play-with-docker/docker" +) + +type Session struct { + rw sync.Mutex + Id string `json:"id"` + Instances map[string]*Instance `json:"instances"` + clients []*Client `json:"-"` + CreatedAt time.Time `json:"created_at"` + ExpiresAt time.Time `json:"expires_at"` + scheduled bool `json:"-"` + ticker *time.Ticker `json:"-"` + PwdIpAddress string `json:"pwd_ip_address"` + Ready bool `json:"ready"` + Stack string `json:"stack"` + closingTimer *time.Timer `json:"-"` +} + +type Instance struct { +} + +type Client struct { +} + +type pwd struct { + docker docker.Docker `json:"-"` +} + +type PWDApi interface { + NewSession(duration time.Duration, stack string) (*Session, error) +} + +func NewPWD(d docker.Docker) pwd { + return pwd{docker: d} +} diff --git a/pwd/session.go b/pwd/session.go new file mode 100644 index 0000000..b64cb9d --- /dev/null +++ b/pwd/session.go @@ -0,0 +1,66 @@ +package pwd + +import ( + "log" + "time" + + "github.com/franela/play-with-docker.old/config" + "github.com/twinj/uuid" +) + +func (p *pwd) NewSession(duration time.Duration, stack, stackName string) (*Session, error) { + s := &Session{} + s.Id = uuid.NewV4().String() + s.Instances = map[string]*Instance{} + s.CreatedAt = time.Now() + s.ExpiresAt = s.CreatedAt.Add(duration) + /* + if stack == "" { + s.Ready = true + } + s.Stack = stack + */ + log.Printf("NewSession id=[%s]\n", s.Id) + + if err := p.docker.CreateNetwork(s.Id); err != nil { + log.Println("ERROR NETWORKING") + return nil, err + } + log.Printf("Network [%s] created for session [%s]\n", s.Id, s.Id) + + s.Prepare() + + return s, 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 +func (s *Session) Prepare() error { + s.scheduleSessionClose() + + // Connect PWD daemon to the new network + s.connectToNetwork() + + return nil +} + +func (s *Session) scheduleSessionClose() { + timeLeft := s.ExpiresAt.Sub(time.Now()) + s.closingTimer = time.AfterFunc(timeLeft, func() { + s.Close() + }) +} + +func (s *Session) Close() { +} + +func (s *Session) connectToNetwork() { + ip, err := ConnectNetwork(config.PWDContainerName, s.Id, "") + if err != nil { + log.Println("ERROR NETWORKING") + return nil, err + } + s.PwdIpAddress = ip + log.Printf("Connected %s to network [%s]\n", config.PWDContainerName, s.Id) +} diff --git a/pwd/session_test.go b/pwd/session_test.go new file mode 100644 index 0000000..ed5aea3 --- /dev/null +++ b/pwd/session_test.go @@ -0,0 +1,33 @@ +package pwd + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestNewSession_WithoutStack(t *testing.T) { + createdNetworkId := "" + + mock := &mockDocker{} + mock.createNetwork = func(id string) error { + createdNetworkId = id + return nil + } + + p := NewPWD(mock) + + before := time.Now() + s, e := p.NewSession(time.Hour, "", "") + + assert.Nil(t, e) + assert.NotNil(t, s) + + assert.NotEmpty(t, s.Id) + assert.WithinDuration(t, s.CreatedAt, before, time.Since(before)) + assert.WithinDuration(t, s.ExpiresAt, before.Add(time.Hour), time.Second) + assert.Equal(t, s.Id, createdNetworkId) + + assert.NotNil(t, s.closingTimer) +}