1
0
mirror of https://github.com/bingohuang/docker-labs.git synced 2025-07-14 01:57:32 +08:00
docker-labs/services/instance.go
Jonathan Leibiusky (@xetorthio) 8e4981d24f Huge refactor to have everything working with socket.io
It fixes lots of bugs, can fallback to long polling, resize viewport of
terminals and share clients state of the session, so they all see the
same thing.
2016-11-10 10:42:08 -03:00

114 lines
2.3 KiB
Go

package services
import (
"context"
"io"
"log"
"os"
"golang.org/x/text/encoding"
"github.com/docker/docker/api/types"
)
type Instance struct {
Session *Session `json:"-"`
Name string `json:"name"`
IP string `json:"ip"`
Conn *types.HijackedResponse `json:"-"`
ExecId string `json:"-"`
Ctx context.Context `json:"-"`
}
var dindImage string
var defaultDindImageName string
func init() {
dindImage = getDindImageName()
}
func getDindImageName() string {
dindImage := os.Getenv("DIND_IMAGE")
defaultDindImageName = "docker:1.12.2-rc2-dind"
if len(dindImage) == 0 {
dindImage = defaultDindImageName
}
return dindImage
}
func NewInstance(session *Session) (*Instance, error) {
//TODO: Validate that a session can only have 5 instances
log.Printf("NewInstance - using image: [%s]\n", dindImage)
instance, err := CreateInstance(session.Id, dindImage)
instance.Session = session
if err != nil {
return nil, err
}
if session.Instances == nil {
session.Instances = make(map[string]*Instance)
}
session.Instances[instance.Name] = instance
go instance.Exec()
wsServer.BroadcastTo(session.Id, "new instance", instance.Name, instance.IP)
return instance, nil
}
type sessionWriter struct {
instance *Instance
}
func (s *sessionWriter) Write(p []byte) (n int, err error) {
wsServer.BroadcastTo(s.instance.Session.Id, "terminal out", s.instance.Name, string(p))
return len(p), nil
}
func (i *Instance) ResizeTerminal(cols, rows uint) {
ResizeExecConnection(i.ExecId, i.Ctx, cols, rows)
}
func (i *Instance) Exec() {
i.Ctx = context.Background()
id, err := CreateExecConnection(i.Name, i.Ctx)
if err != nil {
return
}
i.ExecId = id
conn, err := AttachExecConnection(id, i.Ctx)
if err != nil {
return
}
i.Conn = conn
go func() {
encoder := encoding.Replacement.NewEncoder()
sw := &sessionWriter{instance: i}
io.Copy(encoder.Writer(sw), conn.Reader)
}()
select {
case <-i.Ctx.Done():
}
}
func GetInstance(session *Session, name string) *Instance {
//TODO: Use redis
return session.Instances[name]
}
func DeleteInstance(session *Session, instance *Instance) error {
//TODO: Use redis
delete(session.Instances, instance.Name)
err := DeleteContainer(instance.Name)
wsServer.BroadcastTo(session.Id, "delete instance", instance.Name)
return err
}