From 080d9b3133e8dd6261c547117f34512ad68148c8 Mon Sep 17 00:00:00 2001 From: "Jonathan Leibiusky @xetorthio" Date: Wed, 7 Jun 2017 10:13:46 -0300 Subject: [PATCH] Parallel implementation of the setup, makes each around 3 times faster --- pwd/session.go | 100 +++++++++++++++++++++++++++++--------------- pwd/session_test.go | 19 ++++++--- 2 files changed, 81 insertions(+), 38 deletions(-) diff --git a/pwd/session.go b/pwd/session.go index c151a63..e64cb28 100644 --- a/pwd/session.go +++ b/pwd/session.go @@ -225,18 +225,17 @@ 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 + // first look for a swarm manager and create it 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 conf.IsSwarmManager { + instanceConf := InstanceConfig{ + ImageName: conf.Image, + Hostname: conf.Hostname, + } + i, err := p.InstanceNew(session, instanceConf) + if err != nil { + return err + } if i.docker == nil { dock, err := p.docker.New(i.IP, i.Cert, i.Key) if err != nil { @@ -244,34 +243,69 @@ func (p *pwd) SessionSetup(session *Session, conf SessionSetupConf) error { } 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) + tkns, err := i.docker.SwarmInit() if err != nil { return err } + tokens = tkns + firstSwarmManager = i + break } } + // now create the rest in parallel + + wg := sync.WaitGroup{} + for _, c := range conf.Instances { + if firstSwarmManager != nil && c.Hostname != firstSwarmManager.Hostname { + wg.Add(1) + go func(c SessionSetupInstanceConf) { + defer wg.Done() + instanceConf := InstanceConfig{ + ImageName: c.Image, + Hostname: c.Hostname, + } + i, err := p.InstanceNew(session, instanceConf) + if err != nil { + log.Println(err) + return + } + if c.IsSwarmManager || c.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 { + log.Println(err) + return + } + i.docker = dock + } + } + + if firstSwarmManager != nil { + if c.IsSwarmManager { + // this is a swarm manager + // cluster has already been initiated, join as manager + err := i.docker.SwarmJoin(fmt.Sprintf("%s:2377", firstSwarmManager.IP), tokens.Manager) + if err != nil { + log.Println(err) + return + } + } + if c.IsSwarmWorker { + // this is a swarm worker + err := i.docker.SwarmJoin(fmt.Sprintf("%s:2377", firstSwarmManager.IP), tokens.Worker) + if err != nil { + log.Println(err) + return + } + } + } + }(c) + } + } + wg.Wait() + return nil } diff --git a/pwd/session_test.go b/pwd/session_test.go index 316c81e..9533e2c 100644 --- a/pwd/session_test.go +++ b/pwd/session_test.go @@ -84,8 +84,6 @@ func TestSessionNew(t *testing.T) { } 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 @@ -93,9 +91,20 @@ func TestSessionSetup(t *testing.T) { dock := &mockDocker{} dock.createContainer = func(opts docker.CreateContainerOpts) (string, error) { - ip := ips[nextIp] - nextIp++ - return ip, nil + if opts.Hostname == "manager1" { + return "10.0.0.1", nil + } else if opts.Hostname == "manager2" { + return "10.0.0.2", nil + } else if opts.Hostname == "manager3" { + return "10.0.0.3", nil + } else if opts.Hostname == "worker1" { + return "10.0.0.4", nil + } else if opts.Hostname == "other" { + return "10.0.0.5", nil + } else { + assert.Fail(t, "Should not have reached here") + } + return "", nil } dock.new = func(ip string, cert, key []byte) (docker.DockerApi, error) { if ip == "10.0.0.1" {