Skip to content
Snippets Groups Projects
Commit 78e1c9bc authored by Kamil Trzcinski's avatar Kamil Trzcinski
Browse files

Make Docker executor to concurrently start services and clone sources

This moves a check if services are started after cloning a sources giving a services sometimes just enough time to start and reduces a time spend on waiting.
parent f2a73aaf
No related branches found
No related tags found
No related merge requests found
......@@ -38,6 +38,8 @@ type executor struct {
options dockerOptions
}
type servicesLinks map[string]*docker.Container
const PrebuiltArchive = "prebuilt.tar.gz"
func (s *executor) getServiceVariables() []string {
......@@ -489,17 +491,17 @@ func (s *executor) getServiceNames() ([]string, error) {
return services, nil
}
func (s *executor) waitForServices() {
func (s *executor) waitForServices(services servicesLinks) {
waitForServicesTimeout := s.Config.Docker.WaitForServicesTimeout
if waitForServicesTimeout == 0 {
waitForServicesTimeout = common.DefaultWaitForServicesTimeout
}
// wait for all services to came up
if waitForServicesTimeout > 0 && len(s.services) > 0 {
if waitForServicesTimeout > 0 && len(servicesLinks) > 0 {
s.Println("Waiting for services to be up and running...")
wg := sync.WaitGroup{}
for _, service := range s.services {
for _, service := range servicesLinks {
wg.Add(1)
go func(service *docker.Container) {
s.waitForServiceContainer(service, time.Duration(waitForServicesTimeout)*time.Second)
......@@ -548,25 +550,38 @@ func (s *executor) createFromServiceDescription(description string, linksMap map
return
}
func (s *executor) createServices() ([]string, error) {
func (s *executor) startServices() (services servicesLinks, error) {
serviceNames, err := s.getServiceNames()
if err != nil {
return nil, err
}
linksMap := make(map[string]*docker.Container)
services = make(servicesLinks)
for _, serviceDescription := range serviceNames {
err = s.createFromServiceDescription(serviceDescription, linksMap)
err = s.createFromServiceDescription(serviceDescription, services)
if err != nil {
return nil, err
}
}
return
}
func (s *executor) finishServices(services servicesLinks) (links []string) {
s.waitForServices(services)
links = s.buildServiceLinks(services)
return
}
s.waitForServices()
func (s *executor) createServices() (links []string, err error) {
s.Debugln("Creating services...")
services, err := s.startServices()
if err != nil {
return
}
links := s.buildServiceLinks(linksMap)
return links, nil
links = s.finishServices(services)
return
}
func (s *executor) prepareBuildContainer() (options *docker.CreateContainerOptions, err error) {
......@@ -600,13 +615,6 @@ func (s *executor) prepareBuildContainer() (options *docker.CreateContainerOptio
}
options.HostConfig.Devices = devices
s.Debugln("Creating services...")
links, err := s.createServices()
if err != nil {
return options, err
}
options.HostConfig.Links = append(options.HostConfig.Links, links...)
s.Debugln("Creating cache directories...")
binds, volumesFrom, err := s.createVolumes()
if err != nil {
......
......@@ -11,8 +11,16 @@ import (
type commandExecutor struct {
executor
containerOptions *docker.CreateContainerOptions
predefinedContainer *docker.Container
predefinedImage *docker.Image
buildContainer *docker.Container
buildImage string
preparedServices servicesLinks
}
func (s *commandExecutor) Prepare(globalConfig *common.Config, config *common.RunnerConfig, build *common.Build) error {
......@@ -27,42 +35,70 @@ func (s *commandExecutor) Prepare(globalConfig *common.Config, config *common.Ru
return errors.New("Script is not compatible with Docker")
}
imageName, err := s.getImageName()
s.buildImage, err = s.getImageName()
if err != nil {
return err
}
options, err := s.prepareBuildContainer()
s.containerOptions, err = s.prepareBuildContainer()
if err != nil {
return err
}
buildImage, err := s.getPrebuiltImage("build")
s.preparedServices, err = s.startServices()
if err != nil {
return err
}
// Start pre-build container which will git clone changes
s.predefinedContainer, err = s.createContainer("predefined", buildImage.ID, nil, *options)
s.predefinedImage, err = s.getPrebuiltImage("build")
if err != nil {
return err
}
return nil
}
// Start build container which will run actual build
s.buildContainer, err = s.createContainer("build", imageName, s.BuildScript.DockerCommand, *options)
if err != nil {
return err
func (s *commandExecutor) getOrCreatePredefinedContainer() (container *docker.Container, err error) {
if s.predefinedContainer == nil {
// Create pre-build container which will git clone changes
s.predefinedContainer, err = s.createContainer("predefined", s.predefinedImage.ID, nil, *s.containerOptions)
if err != nil {
return
}
}
return nil
return s.predefinedContainer, nil
}
func (s *commandExecutor) Run(cmd common.ExecutorCommand) error {
func (s *commandExecutor) getOrCreateBuildContainer() (container *docker.Container, err error) {
if s.predefinedContainer == nil {
// Verify the state of services
links, err := s.finishServices(s.preparedServices)
if err != nil {
return nil, err
}
s.containerOptions.HostConfig.Links = append(s.containerOptions.HostConfig.Links, links...)
// Create build container which will run actual builds
s.buildContainer, err = s.createContainer("build", s.buildImage, s.BuildScript.DockerCommand, *s.containerOptions)
if err != nil {
return err
}
}
return s.predefinedContainer, nil
}
func (s *commandExecutor) Run(cmd common.ExecutorCommand) (err error) {
var container *docker.Container
if cmd.Predefined {
container = s.predefinedContainer
container, err = s.getOrCreatePredefinedContainer()
} else {
container = s.buildContainer
container, err = s.getOrCreateBuildContainer()
}
if err != nil {
return
}
s.Debugln("Executing on", container.Name, "the", cmd.Script)
......
......@@ -35,6 +35,12 @@ func (s *sshExecutor) Prepare(globalConfig *common.Config, config *common.Runner
return err
}
links, err := s.createServices()
if err != nil {
return err
}
options.HostConfig.Links = append(options.HostConfig.Links, links...)
// Start build container which will run actual build
container, err := s.createContainer("build", imageName, []string{}, *options)
if err != nil {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment