Skip to content

Commit

Permalink
Set session host
Browse files Browse the repository at this point in the history
Add ping to L2 router
  • Loading branch information
xetorthio committed Aug 8, 2017
1 parent ed7cefc commit 0e9716d
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 61 deletions.
3 changes: 2 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const (
var NameFilter = regexp.MustCompile(PWDHostPortGroupRegex)
var AliasFilter = regexp.MustCompile(AliasPortGroupRegex)

var SSLPortNumber, PortNumber, Key, Cert, SessionsFile, PWDContainerName, L2ContainerName, L2Subdomain, PWDCName, HashKey, SSHKeyPath string
var SSLPortNumber, PortNumber, Key, Cert, SessionsFile, PWDContainerName, L2ContainerName, L2Subdomain, PWDCName, HashKey, SSHKeyPath, L2RouterIP string
var MaxLoadAvg float64

func ParseFlags() {
Expand All @@ -31,6 +31,7 @@ func ParseFlags() {
flag.StringVar(&SessionsFile, "save", "./pwd/sessions", "Tell where to store sessions file")
flag.StringVar(&PWDContainerName, "name", "pwd", "Container name used to run PWD (used to be able to connect it to the networks it creates)")
flag.StringVar(&L2ContainerName, "l2", "l2", "Container name used to run L2 Router")
flag.StringVar(&L2RouterIP, "l2-ip", "", "Host IP address for L2 router ping response")
flag.StringVar(&L2Subdomain, "l2-subdomain", "direct", "Subdomain to the L2 Router")
flag.StringVar(&PWDCName, "cname", "", "CNAME given to this host")
flag.StringVar(&HashKey, "hash_key", "salmonrosado", "Hash key to use for cookies")
Expand Down
5 changes: 5 additions & 0 deletions docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type DockerApi interface {
CreateNetwork(id string) error
ConnectNetwork(container, network, ip string) (string, error)
GetDaemonInfo() (types.Info, error)
GetDaemonHost() string
GetSwarmPorts() ([]string, []uint16, error)
GetPorts() ([]uint16, error)
GetContainerStats(name string) (io.ReadCloser, error)
Expand Down Expand Up @@ -102,6 +103,10 @@ func (d *docker) GetDaemonInfo() (types.Info, error) {
return d.c.Info(context.Background())
}

func (d *docker) GetDaemonHost() string {
return d.c.DaemonHost()
}

func (d *docker) GetSwarmPorts() ([]string, []uint16, error) {
hosts := []string{}
ports := []uint16{}
Expand Down
5 changes: 5 additions & 0 deletions docker/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ func (m *Mock) GetDaemonInfo() (types.Info, error) {
return args.Get(0).(types.Info), args.Error(1)
}

func (m *Mock) GetDaemonHost() string {
args := m.Called()
return args.String(0)
}

func (m *Mock) GetSwarmPorts() ([]string, []uint16, error) {
args := m.Called()
return args.Get(0).([]string), args.Get(1).([]uint16), args.Error(2)
Expand Down
19 changes: 1 addition & 18 deletions handlers/ping.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,6 @@
package handlers

import (
"log"
"net/http"

"github.com/play-with-docker/play-with-docker/config"
"github.com/shirou/gopsutil/load"
)
import "net/http"

func Ping(rw http.ResponseWriter, req *http.Request) {
// Get system load average of the last 5 minutes and compare it against a threashold.

a, err := load.Avg()
if err != nil {
log.Println("Cannot get system load average!", err)
} else {
if a.Load5 > config.MaxLoadAvg {
log.Printf("System load average is too high [%f]\n", a.Load5)
rw.WriteHeader(http.StatusInsufficientStorage)
}
}
}
3 changes: 3 additions & 0 deletions pwd/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func TestClientNew(t *testing.T) {
_g.On("NewId").Return("aaaabbbbcccc")
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
_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("SessionCount").Return(1, nil)
Expand Down Expand Up @@ -59,6 +60,7 @@ func TestClientCount(t *testing.T) {
_g.On("NewId").Return("aaaabbbbcccc")
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
_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("SessionCount").Return(1, nil)
Expand Down Expand Up @@ -93,6 +95,7 @@ func TestClientResizeViewPort(t *testing.T) {
_g.On("NewId").Return("aaaabbbbcccc")
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
_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("SessionCount").Return(1, nil)
Expand Down
6 changes: 6 additions & 0 deletions pwd/instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func TestInstanceNew(t *testing.T) {
_g.On("NewId").Return("aaaabbbbcccc")
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
_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("SessionCount").Return(1, nil)
Expand All @@ -69,6 +70,7 @@ func TestInstanceNew(t *testing.T) {
IsDockerHost: true,
SessionId: session.Id,
Session: session,
SessionHost: session.Host,
ProxyHost: router.EncodeHost(session.Id, "10.0.0.1", router.HostOpts{}),
}
expectedContainerOpts := docker.CreateContainerOpts{
Expand Down Expand Up @@ -109,6 +111,7 @@ func TestInstanceNew_WithNotAllowedImage(t *testing.T) {
_g.On("NewId").Return("aaaabbbbcccc")
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
_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("SessionCount").Return(1, nil)
Expand All @@ -132,6 +135,7 @@ func TestInstanceNew_WithNotAllowedImage(t *testing.T) {
SessionId: session.Id,
IsDockerHost: false,
Session: session,
SessionHost: session.Host,
ProxyHost: router.EncodeHost(session.Id, "10.0.0.1", router.HostOpts{}),
}
expectedContainerOpts := docker.CreateContainerOpts{
Expand Down Expand Up @@ -171,6 +175,7 @@ func TestInstanceNew_WithCustomHostname(t *testing.T) {
_g.On("NewId").Return("aaaabbbbcccc")
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
_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("SessionCount").Return(1, nil)
Expand All @@ -192,6 +197,7 @@ func TestInstanceNew_WithCustomHostname(t *testing.T) {
Image: "redis",
IsDockerHost: false,
Session: session,
SessionHost: session.Host,
SessionId: session.Id,
ProxyHost: router.EncodeHost(session.Id, "10.0.0.1", router.HostOpts{}),
}
Expand Down
57 changes: 16 additions & 41 deletions pwd/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"log"
"math"
"net/url"
"path"
"path/filepath"
"strings"
Expand Down Expand Up @@ -61,15 +62,28 @@ func (p *pwd) SessionNew(duration time.Duration, stack, stackName, imageName str

log.Printf("NewSession id=[%s]\n", s.Id)

if err := p.docker(s.Id).CreateNetwork(s.Id); err != nil {
dockerClient := p.docker(s.Id)
u, _ := url.Parse(dockerClient.GetDaemonHost())
if u.Host == "" {
s.Host = "localhost"
} else {
chunks := strings.Split(u.Host, ":")
s.Host = chunks[0]
}

if err := dockerClient.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)

if err := p.connectToNetwork(s); err != nil {
ip, err := dockerClient.ConnectNetwork(config.L2ContainerName, s.Id, s.PwdIpAddress)
if err != nil {
log.Println(err)
return nil, err
}
s.PwdIpAddress = ip
log.Printf("Connected %s to network [%s]\n", config.PWDContainerName, s.Id)

if err := p.storage.SessionPut(s); err != nil {
log.Println(err)
Expand Down Expand Up @@ -278,42 +292,3 @@ func (p *pwd) SessionSetup(session *types.Session, conf SessionSetupConf) error

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
func (p *pwd) prepareSession(session *types.Session) (bool, error) {
session.Lock()
defer session.Unlock()
if isSessionPrepared(session.Id) {
return false, nil
}
// Connect PWD daemon to the new network
if err := p.connectToNetwork(session); err != nil {
return false, err
}
for _, i := range session.Instances {
// wire the session back to the instance
i.Session = session
go p.InstanceAttachTerminal(i)
}
preparedSessions[session.Id] = true
return true, nil
}
*/

func (p *pwd) connectToNetwork(s *types.Session) error {
ip, err := p.docker(s.Id).ConnectNetwork(config.L2ContainerName, s.Id, s.PwdIpAddress)
if err != nil {
log.Println("ERROR NETWORKING")
return err
}
s.PwdIpAddress = ip
log.Printf("Connected %s to network [%s]\n", config.PWDContainerName, s.Id)
return nil
}
5 changes: 4 additions & 1 deletion pwd/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func TestSessionNew(t *testing.T) {
_g.On("NewId").Return("aaaabbbbcccc")
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
_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("SessionCount").Return(1, nil)
Expand Down Expand Up @@ -53,6 +54,7 @@ func TestSessionNew(t *testing.T) {
assert.Equal(t, "stackPath", s.Stack)
assert.Equal(t, "stackName", s.StackName)
assert.Equal(t, "imageName", s.ImageName)
assert.Equal(t, "localhost", s.Host)
assert.False(t, s.Ready)

assert.Equal(t, "10.0.0.1", s.PwdIpAddress)
Expand All @@ -74,13 +76,14 @@ func TestSessionSetup(t *testing.T) {
_g.On("NewId").Return("aaaabbbbcccc")
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
_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("SessionCount").Return(1, nil)
_s.On("InstanceCount").Return(0, nil)

_d.On("CreateContainer", docker.CreateContainerOpts{Image: "franela/dind", SessionId: "aaaabbbbcccc", PwdIpAddress: "10.0.0.1", ContainerName: "aaaabbbb_manager1", Hostname: "manager1", Privileged: true}).Return("10.0.0.2", 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"}).Return("10.0.0.2", nil)
_f.On("GetForInstance", "aaaabbbbcccc", "aaaabbbb_manager1").Return(_d, nil)
_d.On("SwarmInit").Return(&docker.SwarmTokens{Manager: "managerToken", Worker: "workerToken"}, nil)
_e.M.On("Emit", event.INSTANCE_NEW, "aaaabbbbcccc", []interface{}{"aaaabbbb_manager1", "10.0.0.2", "manager1"}).Return()
Expand Down
34 changes: 34 additions & 0 deletions router/l2/l2.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@ import (
"fmt"
"log"
"net"
"net/http"
"os"
"time"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
"github.com/gorilla/mux"
"github.com/play-with-docker/play-with-docker/config"
"github.com/play-with-docker/play-with-docker/router"
"github.com/shirou/gopsutil/load"
"github.com/urfave/negroni"
)

func director(protocol router.Protocol, host string) (*net.TCPAddr, error) {
Expand Down Expand Up @@ -128,7 +133,36 @@ func main() {
}
go monitorNetworks()

ro := mux.NewRouter()
ro.HandleFunc("/ping", ping).Methods("GET")
n := negroni.Classic()
n.UseHandler(ro)

httpServer := http.Server{
Addr: "0.0.0.0:8080",
Handler: n,
IdleTimeout: 30 * time.Second,
ReadHeaderTimeout: 5 * time.Second,
}
go httpServer.ListenAndServe()

r := router.NewRouter(director, config.SSHKeyPath)
r.ListenAndWait(":443", ":53", ":22")
defer r.Close()
}

func ping(rw http.ResponseWriter, req *http.Request) {
// Get system load average of the last 5 minutes and compare it against a threashold.

a, err := load.Avg()
if err != nil {
log.Println("Cannot get system load average!", err)
} else {
if a.Load5 > config.MaxLoadAvg {
log.Printf("System load average is too high [%f]\n", a.Load5)
rw.WriteHeader(http.StatusInsufficientStorage)
}
}

fmt.Fprintf(rw, `{"ip": "%s"}`, config.L2RouterIP)
}

0 comments on commit 0e9716d

Please sign in to comment.