From c2b156d02a64b276879ffbe77462febadbe50e9b Mon Sep 17 00:00:00 2001 From: "Jonathan Leibiusky @xetorthio" Date: Wed, 2 Aug 2017 11:58:56 -0300 Subject: [PATCH] Add provisioners --- handlers/new_instance.go | 4 +- provisioner/dind.go | 206 +++++++++++++++++++++++++++++++++++++ provisioner/provisioner.go | 19 ++++ provisioner/windows.go | 42 ++++++++ pwd/instance.go | 192 +++++++--------------------------- pwd/instance_test.go | 18 +--- pwd/mock.go | 14 +-- pwd/pwd.go | 30 ++++-- pwd/session.go | 6 +- pwd/types/instance.go | 13 +++ 10 files changed, 352 insertions(+), 192 deletions(-) create mode 100644 provisioner/dind.go create mode 100644 provisioner/provisioner.go create mode 100644 provisioner/windows.go diff --git a/handlers/new_instance.go b/handlers/new_instance.go index 94470db..6aeda76 100644 --- a/handlers/new_instance.go +++ b/handlers/new_instance.go @@ -6,14 +6,14 @@ import ( "net/http" "github.com/gorilla/mux" - "github.com/play-with-docker/play-with-docker/pwd" + "github.com/play-with-docker/play-with-docker/pwd/types" ) func NewInstance(rw http.ResponseWriter, req *http.Request) { vars := mux.Vars(req) sessionId := vars["sessionId"] - body := pwd.InstanceConfig{Host: req.Host} + body := types.InstanceConfig{Host: req.Host} json.NewDecoder(req.Body).Decode(&body) diff --git a/provisioner/dind.go b/provisioner/dind.go new file mode 100644 index 0000000..24dd978 --- /dev/null +++ b/provisioner/dind.go @@ -0,0 +1,206 @@ +package provisioner + +import ( + "bytes" + "fmt" + "io" + "log" + "net" + "net/http" + "path/filepath" + "strings" + + "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/pwd/types" + "github.com/play-with-docker/play-with-docker/router" +) + +type DinD struct { + factory docker.FactoryApi +} + +func NewDinD(f docker.FactoryApi) *DinD { + return &DinD{factory: f} +} + +func checkHostnameExists(session *types.Session, hostname string) bool { + containerName := fmt.Sprintf("%s_%s", session.Id[:8], hostname) + exists := false + for _, instance := range session.Instances { + if instance.Name == containerName { + exists = true + break + } + } + return exists +} + +func (d *DinD) InstanceAllowedImages() []string { + return []string{ + config.GetDindImageName(), + "franela/dind:overlay2-dev", + "franela/ucp:2.4.1", + } +} + +func (d *DinD) InstanceNew(session *types.Session, conf types.InstanceConfig) (*types.Instance, error) { + if conf.ImageName == "" { + conf.ImageName = config.GetDindImageName() + } + log.Printf("NewInstance - using image: [%s]\n", conf.ImageName) + if conf.Hostname == "" { + var nodeName string + for i := 1; ; i++ { + nodeName = fmt.Sprintf("node%d", i) + exists := checkHostnameExists(session, nodeName) + if !exists { + break + } + } + conf.Hostname = nodeName + } + containerName := fmt.Sprintf("%s_%s", session.Id[:8], conf.Hostname) + opts := docker.CreateContainerOpts{ + Image: conf.ImageName, + SessionId: session.Id, + PwdIpAddress: session.PwdIpAddress, + ContainerName: containerName, + Hostname: conf.Hostname, + ServerCert: conf.ServerCert, + ServerKey: conf.ServerKey, + CACert: conf.CACert, + Privileged: false, + HostFQDN: conf.Host, + } + + for _, imageName := range d.InstanceAllowedImages() { + if conf.ImageName == imageName { + opts.Privileged = true + break + } + } + + dockerClient, err := d.factory.GetForSession(session.Id) + if err != nil { + return nil, err + } + ip, err := dockerClient.CreateContainer(opts) + if err != nil { + return nil, err + } + + instance := &types.Instance{} + instance.Image = opts.Image + instance.IP = ip + instance.SessionId = session.Id + instance.Name = containerName + instance.Hostname = conf.Hostname + instance.Cert = conf.Cert + instance.Key = conf.Key + instance.ServerCert = conf.ServerCert + instance.ServerKey = conf.ServerKey + instance.CACert = conf.CACert + instance.Session = session + instance.ProxyHost = router.EncodeHost(session.Id, ip, router.HostOpts{}) + instance.SessionHost = session.Host + // For now this condition holds through. In the future we might need a more complex logic. + instance.IsDockerHost = opts.Privileged + + return instance, nil +} + +func (d *DinD) InstanceDelete(session *types.Session, instance *types.Instance) error { + dockerClient, err := d.factory.GetForSession(session.Id) + if err != nil { + return err + } + err = dockerClient.DeleteContainer(instance.Name) + if err != nil && !strings.Contains(err.Error(), "No such container") { + return err + } + return nil +} + +func (d *DinD) InstanceResizeTerminal(instance *types.Instance, rows, cols uint) error { + dockerClient, err := d.factory.GetForSession(instance.SessionId) + if err != nil { + return err + } + return dockerClient.ContainerResize(instance.Name, rows, cols) +} + +func (d *DinD) InstanceGetTerminal(instance *types.Instance) (net.Conn, error) { + dockerClient, err := d.factory.GetForSession(instance.SessionId) + if err != nil { + return nil, err + } + return dockerClient.CreateAttachConnection(instance.Name) +} + +func (d *DinD) InstanceUploadFromUrl(instance *types.Instance, fileName, dest, url string) error { + log.Printf("Downloading file [%s]\n", url) + resp, err := http.Get(url) + if err != nil { + return fmt.Errorf("Could not download file [%s]. Error: %s\n", url, err) + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + return fmt.Errorf("Could not download file [%s]. Status code: %d\n", url, resp.StatusCode) + } + dockerClient, err := d.factory.GetForSession(instance.SessionId) + if err != nil { + return err + } + + copyErr := dockerClient.CopyToContainer(instance.Name, dest, fileName, resp.Body) + + if copyErr != nil { + return fmt.Errorf("Error while downloading file [%s]. Error: %s\n", url, copyErr) + } + + return nil +} + +func (d *DinD) getInstanceCWD(instance *types.Instance) (string, error) { + dockerClient, err := d.factory.GetForSession(instance.SessionId) + if err != nil { + return "", err + } + b := bytes.NewBufferString("") + + if c, err := dockerClient.ExecAttach(instance.Name, []string{"bash", "-c", `pwdx $( 0 { + return "", fmt.Errorf("Error %d trying to get CWD", c) + } else if err != nil { + return "", err + } + + cwd := strings.TrimSpace(strings.Split(b.String(), ":")[1]) + + return cwd, nil +} + +func (d *DinD) InstanceUploadFromReader(instance *types.Instance, fileName, dest string, reader io.Reader) error { + dockerClient, err := d.factory.GetForSession(instance.SessionId) + if err != nil { + return err + } + var finalDest string + if filepath.IsAbs(dest) { + finalDest = dest + } else { + if cwd, err := d.getInstanceCWD(instance); err != nil { + return err + } else { + finalDest = fmt.Sprintf("%s/%s", cwd, dest) + } + } + + copyErr := dockerClient.CopyToContainer(instance.Name, finalDest, fileName, reader) + + if copyErr != nil { + return fmt.Errorf("Error while uploading file [%s]. Error: %s\n", fileName, copyErr) + } + + return nil +} diff --git a/provisioner/provisioner.go b/provisioner/provisioner.go new file mode 100644 index 0000000..e453175 --- /dev/null +++ b/provisioner/provisioner.go @@ -0,0 +1,19 @@ +package provisioner + +import ( + "io" + "net" + + "github.com/play-with-docker/play-with-docker/pwd/types" +) + +type ProvisionerApi interface { + InstanceNew(session *types.Session, conf types.InstanceConfig) (*types.Instance, error) + InstanceDelete(session *types.Session, instance *types.Instance) error + + InstanceResizeTerminal(instance *types.Instance, cols, rows uint) error + InstanceGetTerminal(instance *types.Instance) (net.Conn, error) + + InstanceUploadFromUrl(instance *types.Instance, fileName, dest, url string) error + InstanceUploadFromReader(instance *types.Instance, fileName, dest string, reader io.Reader) error +} diff --git a/provisioner/windows.go b/provisioner/windows.go new file mode 100644 index 0000000..30c29f4 --- /dev/null +++ b/provisioner/windows.go @@ -0,0 +1,42 @@ +package provisioner + +import ( + "fmt" + "io" + "net" + + "github.com/play-with-docker/play-with-docker/docker" + "github.com/play-with-docker/play-with-docker/pwd/types" +) + +type windows struct { + factory docker.FactoryApi +} + +func NewWindows(f docker.FactoryApi) *windows { + return &windows{factory: f} +} + +func (d *windows) InstanceNew(session *types.Session, conf types.InstanceConfig) (*types.Instance, error) { + return nil, fmt.Errorf("Not implemented") +} + +func (d *windows) InstanceDelete(session *types.Session, instance *types.Instance) error { + return fmt.Errorf("Not implemented") +} + +func (d *windows) InstanceResizeTerminal(instance *types.Instance, cols, rows uint) error { + return fmt.Errorf("Not implemented") +} + +func (d *windows) InstanceGetTerminal(instance *types.Instance) (net.Conn, error) { + return nil, fmt.Errorf("Not implemented") +} + +func (d *windows) InstanceUploadFromUrl(instance *types.Instance, fileName, dest, url string) error { + return fmt.Errorf("Not implemented") +} + +func (d *windows) InstanceUploadFromReader(instance *types.Instance, fileName, dest string, reader io.Reader) error { + return fmt.Errorf("Not implemented") +} diff --git a/pwd/instance.go b/pwd/instance.go index 523b3c2..0953cd6 100644 --- a/pwd/instance.go +++ b/pwd/instance.go @@ -1,107 +1,53 @@ package pwd import ( - "bytes" - "fmt" "io" "log" "net" - "net/http" - "path/filepath" - "strings" "time" - "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/provisioner" "github.com/play-with-docker/play-with-docker/pwd/types" - "github.com/play-with-docker/play-with-docker/router" ) -type InstanceConfig struct { - ImageName string - Hostname string - ServerCert []byte - ServerKey []byte - CACert []byte - Cert []byte - Key []byte - Host string -} - func (p *pwd) InstanceResizeTerminal(instance *types.Instance, rows, cols uint) error { defer observeAction("InstanceResizeTerminal", time.Now()) - return p.docker(instance.SessionId).ContainerResize(instance.Name, rows, cols) + prov, err := p.getProvisioner(instance.Type) + if err != nil { + return err + } + return prov.InstanceResizeTerminal(instance, rows, cols) } func (p *pwd) InstanceGetTerminal(instance *types.Instance) (net.Conn, error) { defer observeAction("InstanceGetTerminal", time.Now()) - conn, err := p.docker(instance.SessionId).CreateAttachConnection(instance.Name) - + prov, err := p.getProvisioner(instance.Type) if err != nil { return nil, err } - - return conn, nil + return prov.InstanceGetTerminal(instance) } func (p *pwd) InstanceUploadFromUrl(instance *types.Instance, fileName, dest string, url string) error { defer observeAction("InstanceUploadFromUrl", time.Now()) - log.Printf("Downloading file [%s]\n", url) - resp, err := http.Get(url) + prov, err := p.getProvisioner(instance.Type) if err != nil { - return fmt.Errorf("Could not download file [%s]. Error: %s\n", url, err) - } - defer resp.Body.Close() - if resp.StatusCode != 200 { - return fmt.Errorf("Could not download file [%s]. Status code: %d\n", url, resp.StatusCode) + return err } - copyErr := p.docker(instance.SessionId).CopyToContainer(instance.Name, dest, fileName, resp.Body) - - if copyErr != nil { - return fmt.Errorf("Error while downloading file [%s]. Error: %s\n", url, copyErr) - } - - return nil -} - -func (p *pwd) getInstanceCWD(instance *types.Instance) (string, error) { - b := bytes.NewBufferString("") - - if c, err := p.docker(instance.SessionId).ExecAttach(instance.Name, []string{"bash", "-c", `pwdx $( 0 { - log.Println(b.String()) - return "", fmt.Errorf("Error %d trying to get CWD", c) - } else if err != nil { - return "", err - } - - cwd := strings.TrimSpace(strings.Split(b.String(), ":")[1]) - - return cwd, nil + return prov.InstanceUploadFromUrl(instance, fileName, dest, url) } func (p *pwd) InstanceUploadFromReader(instance *types.Instance, fileName, dest string, reader io.Reader) error { defer observeAction("InstanceUploadFromReader", time.Now()) - var finalDest string - if filepath.IsAbs(dest) { - finalDest = dest - } else { - if cwd, err := p.getInstanceCWD(instance); err != nil { - return err - } else { - finalDest = fmt.Sprintf("%s/%s", cwd, dest) - } + prov, err := p.getProvisioner(instance.Type) + if err != nil { + return err } - copyErr := p.docker(instance.SessionId).CopyToContainer(instance.Name, finalDest, fileName, reader) - - if copyErr != nil { - return fmt.Errorf("Error while uploading file [%s]. Error: %s\n", fileName, copyErr) - } - - return nil + return prov.InstanceUploadFromReader(instance, fileName, dest, reader) } func (p *pwd) InstanceGet(session *types.Session, name string) *types.Instance { @@ -109,8 +55,8 @@ func (p *pwd) InstanceGet(session *types.Session, name string) *types.Instance { return session.Instances[name] } -func (p *pwd) InstanceFind(sessionId, ip string) *types.Instance { - defer observeAction("InstanceFind", time.Now()) +func (p *pwd) InstanceFindByIP(sessionId, ip string) *types.Instance { + defer observeAction("InstanceFindByIP", time.Now()) i, err := p.storage.InstanceFindByIP(sessionId, ip) if err != nil { return nil @@ -122,8 +68,13 @@ func (p *pwd) InstanceFind(sessionId, ip string) *types.Instance { func (p *pwd) InstanceDelete(session *types.Session, instance *types.Instance) error { defer observeAction("InstanceDelete", time.Now()) - err := p.docker(session.Id).DeleteContainer(instance.Name) - if err != nil && !strings.Contains(err.Error(), "No such container") { + prov, err := p.getProvisioner(instance.Type) + if err != nil { + return err + } + + err = prov.InstanceDelete(session, instance) + if err != nil { log.Println(err) return err } @@ -139,90 +90,26 @@ func (p *pwd) InstanceDelete(session *types.Session, instance *types.Instance) e return nil } -func (p *pwd) checkHostnameExists(session *types.Session, hostname string) bool { - containerName := fmt.Sprintf("%s_%s", session.Id[:8], hostname) - exists := false - for _, instance := range session.Instances { - if instance.Name == containerName { - exists = true - break - } - } - return exists -} - -func (p *pwd) InstanceNew(session *types.Session, conf InstanceConfig) (*types.Instance, error) { +func (p *pwd) InstanceNew(session *types.Session, conf types.InstanceConfig) (*types.Instance, error) { defer observeAction("InstanceNew", time.Now()) session.Lock() defer session.Unlock() - if conf.ImageName == "" { - conf.ImageName = config.GetDindImageName() - } - log.Printf("NewInstance - using image: [%s]\n", conf.ImageName) - - if conf.Hostname == "" { - var nodeName string - for i := 1; ; i++ { - nodeName = fmt.Sprintf("node%d", i) - exists := p.checkHostnameExists(session, nodeName) - if !exists { - break - } - } - conf.Hostname = nodeName - } - containerName := fmt.Sprintf("%s_%s", session.Id[:8], conf.Hostname) - - opts := docker.CreateContainerOpts{ - Image: conf.ImageName, - SessionId: session.Id, - PwdIpAddress: session.PwdIpAddress, - ContainerName: containerName, - Hostname: conf.Hostname, - ServerCert: conf.ServerCert, - ServerKey: conf.ServerKey, - CACert: conf.CACert, - Privileged: false, - HostFQDN: conf.Host, - } - - for _, imageName := range p.InstanceAllowedImages() { - if conf.ImageName == imageName { - opts.Privileged = true - break - } - } - - ip, err := p.docker(session.Id).CreateContainer(opts) + prov, err := p.getProvisioner(conf.Type) if err != nil { return nil, err } - - instance := &types.Instance{} - instance.Image = opts.Image - instance.IP = ip - instance.SessionId = session.Id - instance.Name = containerName - instance.Hostname = conf.Hostname - instance.Cert = conf.Cert - instance.Key = conf.Key - instance.ServerCert = conf.ServerCert - instance.ServerKey = conf.ServerKey - instance.CACert = conf.CACert - instance.Session = session - instance.ProxyHost = router.EncodeHost(session.Id, ip, router.HostOpts{}) - instance.SessionHost = session.Host - // For now this condition holds through. In the future we might need a more complex logic. - instance.IsDockerHost = opts.Privileged + instance, err := prov.InstanceNew(session, conf) + if err != nil { + log.Println(err) + return nil, err + } if session.Instances == nil { session.Instances = make(map[string]*types.Instance) } session.Instances[instance.Name] = instance - // go p.InstanceAttachTerminal(instance) - err = p.storage.InstanceCreate(session.Id, instance) if err != nil { return nil, err @@ -235,18 +122,13 @@ func (p *pwd) InstanceNew(session *types.Session, conf InstanceConfig) (*types.I return instance, nil } -func (p *pwd) InstanceAllowedImages() []string { - defer observeAction("InstanceAllowedImages", time.Now()) - - return []string{ - config.GetDindImageName(), - "franela/dind:overlay2-dev", - "franela/ucp:2.4.1", - } - -} - func (p *pwd) InstanceExec(instance *types.Instance, cmd []string) (int, error) { defer observeAction("InstanceExec", time.Now()) return p.docker(instance.SessionId).Exec(instance.Name, cmd) } + +func (p *pwd) InstanceAllowedImages() []string { + defer observeAction("InstanceAllowedImages", time.Now()) + + return p.dindProvisioner.(*provisioner.DinD).InstanceAllowedImages() +} diff --git a/pwd/instance_test.go b/pwd/instance_test.go index 2c9347b..dc0a065 100644 --- a/pwd/instance_test.go +++ b/pwd/instance_test.go @@ -87,7 +87,7 @@ func TestInstanceNew(t *testing.T) { _s.On("InstanceCreate", "aaaabbbbcccc", mock.AnythingOfType("*types.Instance")).Return(nil) _e.M.On("Emit", event.INSTANCE_NEW, "aaaabbbbcccc", []interface{}{"aaaabbbb_node1", "10.0.0.1", "node1"}).Return() - instance, err := p.InstanceNew(session, InstanceConfig{Host: "something.play-with-docker.com"}) + instance, err := p.InstanceNew(session, types.InstanceConfig{Host: "something.play-with-docker.com"}) assert.Nil(t, err) assert.Equal(t, expectedInstance, *instance) @@ -149,7 +149,7 @@ func TestInstanceNew_WithNotAllowedImage(t *testing.T) { _s.On("InstanceCreate", "aaaabbbbcccc", mock.AnythingOfType("*types.Instance")).Return(nil) _e.M.On("Emit", event.INSTANCE_NEW, "aaaabbbbcccc", []interface{}{"aaaabbbb_node1", "10.0.0.1", "node1"}).Return() - instance, err := p.InstanceNew(session, InstanceConfig{ImageName: "redis"}) + instance, err := p.InstanceNew(session, types.InstanceConfig{ImageName: "redis"}) assert.Nil(t, err) assert.Equal(t, expectedInstance, *instance) @@ -211,7 +211,7 @@ func TestInstanceNew_WithCustomHostname(t *testing.T) { _s.On("InstanceCreate", "aaaabbbbcccc", mock.AnythingOfType("*types.Instance")).Return(nil) _e.M.On("Emit", event.INSTANCE_NEW, "aaaabbbbcccc", []interface{}{"aaaabbbb_redis-master", "10.0.0.1", "redis-master"}).Return() - instance, err := p.InstanceNew(session, InstanceConfig{ImageName: "redis", Hostname: "redis-master"}) + instance, err := p.InstanceNew(session, types.InstanceConfig{ImageName: "redis", Hostname: "redis-master"}) assert.Nil(t, err) @@ -223,15 +223,3 @@ func TestInstanceNew_WithCustomHostname(t *testing.T) { _g.AssertExpectations(t) _e.M.AssertExpectations(t) } - -func TestInstanceAllowedImages(t *testing.T) { - _f := &docker.FactoryMock{} - _s := &storage.Mock{} - _e := &event.Mock{} - - p := NewPWD(_f, _e, _s) - - expectedImages := []string{config.GetDindImageName(), "franela/dind:overlay2-dev", "franela/ucp:2.4.1"} - - assert.Equal(t, expectedImages, p.InstanceAllowedImages()) -} diff --git a/pwd/mock.go b/pwd/mock.go index 11dc9b4..cf6ec8b 100644 --- a/pwd/mock.go +++ b/pwd/mock.go @@ -43,7 +43,7 @@ func (m *Mock) SessionSetup(session *types.Session, conf SessionSetupConf) error return args.Error(0) } -func (m *Mock) InstanceNew(session *types.Session, conf InstanceConfig) (*types.Instance, error) { +func (m *Mock) InstanceNew(session *types.Session, conf types.InstanceConfig) (*types.Instance, error) { args := m.Called(session, conf) return args.Get(0).(*types.Instance), args.Error(1) } @@ -73,7 +73,7 @@ func (m *Mock) InstanceGet(session *types.Session, name string) *types.Instance return args.Get(0).(*types.Instance) } -func (m *Mock) InstanceFind(session, ip string) *types.Instance { +func (m *Mock) InstanceFindByIP(session, ip string) *types.Instance { args := m.Called(session, ip) return args.Get(0).(*types.Instance) } @@ -83,16 +83,16 @@ func (m *Mock) InstanceDelete(session *types.Session, instance *types.Instance) return args.Error(0) } -func (m *Mock) InstanceAllowedImages() []string { - args := m.Called() - return args.Get(0).([]string) -} - func (m *Mock) InstanceExec(instance *types.Instance, cmd []string) (int, error) { args := m.Called(instance, cmd) return args.Int(0), args.Error(1) } +func (m *Mock) InstanceAllowedImages() []string { + args := m.Called() + return args.Get(0).([]string) +} + func (m *Mock) ClientNew(id string, session *types.Session) *types.Client { args := m.Called(id, session) return args.Get(0).(*types.Client) diff --git a/pwd/pwd.go b/pwd/pwd.go index 557bb4c..72d777a 100644 --- a/pwd/pwd.go +++ b/pwd/pwd.go @@ -7,6 +7,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/prometheus/client_golang/prometheus" @@ -47,11 +48,13 @@ func init() { } type pwd struct { - dockerFactory docker.FactoryApi - event event.EventApi - storage storage.StorageApi - generator IdGenerator - clientCount int32 + dockerFactory docker.FactoryApi + event event.EventApi + storage storage.StorageApi + generator IdGenerator + clientCount int32 + windowsProvisioner provisioner.ProvisionerApi + dindProvisioner provisioner.ProvisionerApi } type IdGenerator interface { @@ -82,17 +85,16 @@ type PWDApi interface { SessionGet(id string) *types.Session SessionSetup(session *types.Session, conf SessionSetupConf) error - InstanceNew(session *types.Session, conf InstanceConfig) (*types.Instance, error) + InstanceNew(session *types.Session, conf types.InstanceConfig) (*types.Instance, error) InstanceResizeTerminal(instance *types.Instance, cols, rows uint) error InstanceGetTerminal(instance *types.Instance) (net.Conn, error) 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 - // TODO remove this function when we add the session prefix to the PWD url - InstanceFind(sessionId, ip string) *types.Instance + InstanceFindByIP(sessionId, ip string) *types.Instance InstanceDelete(session *types.Session, instance *types.Instance) error - InstanceAllowedImages() []string InstanceExec(instance *types.Instance, cmd []string) (int, error) + InstanceAllowedImages() []string ClientNew(id string, session *types.Session) *types.Client ClientResizeViewPort(client *types.Client, cols, rows uint) @@ -101,7 +103,15 @@ type PWDApi interface { } func NewPWD(f docker.FactoryApi, e event.EventApi, s storage.StorageApi) *pwd { - return &pwd{dockerFactory: f, event: e, storage: s, generator: xidGenerator{}} + return &pwd{dockerFactory: f, event: e, storage: s, generator: xidGenerator{}, windowsProvisioner: provisioner.NewWindows(f), dindProvisioner: provisioner.NewDinD(f)} +} + +func (p *pwd) getProvisioner(t string) (provisioner.ProvisionerApi, error) { + if t == "windows" { + return p.windowsProvisioner, nil + } else { + return p.dindProvisioner, nil + } } func (p *pwd) docker(sessionId string) docker.DockerApi { diff --git a/pwd/session.go b/pwd/session.go index 6165b1c..2f0cdbb 100644 --- a/pwd/session.go +++ b/pwd/session.go @@ -147,7 +147,7 @@ func (p *pwd) SessionDeployStack(s *types.Session) error { s.Ready = false p.event.Emit(event.SESSION_READY, s.Id, false) - i, err := p.InstanceNew(s, InstanceConfig{ImageName: s.ImageName, Host: s.Host}) + i, err := p.InstanceNew(s, types.InstanceConfig{ImageName: s.ImageName, Host: s.Host}) if err != nil { log.Printf("Error creating instance for stack [%s]: %s\n", s.Stack, err) return err @@ -201,7 +201,7 @@ func (p *pwd) SessionSetup(session *types.Session, conf SessionSetupConf) error // first look for a swarm manager and create it for _, conf := range conf.Instances { if conf.IsSwarmManager { - instanceConf := InstanceConfig{ + instanceConf := types.InstanceConfig{ ImageName: conf.Image, Hostname: conf.Hostname, Host: session.Host, @@ -232,7 +232,7 @@ func (p *pwd) SessionSetup(session *types.Session, conf SessionSetupConf) error wg.Add(1) go func(c SessionSetupInstanceConf) { defer wg.Done() - instanceConf := InstanceConfig{ + instanceConf := types.InstanceConfig{ ImageName: c.Image, Hostname: c.Hostname, } diff --git a/pwd/types/instance.go b/pwd/types/instance.go index 407f830..88d1299 100644 --- a/pwd/types/instance.go +++ b/pwd/types/instance.go @@ -16,6 +16,19 @@ type Instance struct { SessionId string `json:"session_id" bson:"session_id"` 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:"-"` } + +type InstanceConfig struct { + ImageName string + Hostname string + ServerCert []byte + ServerKey []byte + CACert []byte + Cert []byte + Key []byte + Host string + Type string +}