// StartDaemon starts a daemon using the provided binary returning // a client to the binary, a close function, and error. func StartDaemon(binary string, lc LogCapturer) (*dockerclient.Client, func() error, error) { // Get Docker version of process previousVersion, err := versionutil.BinaryVersion(binary) if err != nil { return nil, nil, fmt.Errorf("could not get binary version: %s", err) } logrus.Debugf("Starting daemon with %s", binary) binaryArgs := []string{} if previousVersion.LessThan(versionutil.StaticVersion(1, 8, 0)) { binaryArgs = append(binaryArgs, "--daemon") } else { binaryArgs = append(binaryArgs, "daemon") } binaryArgs = append(binaryArgs, "--log-level=debug") binaryArgs = append(binaryArgs, "--storage-driver="+getGraphDriver()) cmd := exec.Command(binary, binaryArgs...) cmd.Stdout = lc.Stdout() cmd.Stderr = lc.Stderr() if err := cmd.Start(); err != nil { return nil, nil, fmt.Errorf("could not start daemon: %s", err) } logrus.Debugf("Waiting for daemon to start") time.Sleep(2 * time.Second) client, err := dockerclient.NewClientFromEnv() if err != nil { return nil, nil, fmt.Errorf("could not initialize client: %s", err) } // Wait for it to start for i := 0; ; i++ { v, err := client.Version() if err == nil { logrus.Debugf("Established connection to daemon with version %s", v.Get("Version")) break } if i >= 10 { logrus.Fatalf("Failed to establish connection to daemon, check logs, quitting") } time.Sleep(time.Second) } kill := func() error { if err := cmd.Process.Kill(); err != nil { return err } time.Sleep(500 * time.Millisecond) return os.RemoveAll("/var/run/docker.pid") } return client, kill, nil }
// Setup does the test setup for the suite. This includes importing // any docker images, running setup scripts, and starting the docker // daemon used by the tests. func (sr *SuiteRunner) Setup() error { // Setup /var/lib/docker if sr.config.DockerInDocker { // Check if empty info, err := ioutil.ReadDir("/var/lib/docker") if err != nil { return fmt.Errorf("error reading /var/lib/docker: %v", err) } if len(info) != 0 { // TODO: Clean if configuration is set logrus.Debugf("/var/lib/docker is not clean") loadVersion, err := versionutil.BinaryVersion("/usr/bin/docker-load") if err != nil { return err } if err := cleanDockerGraph("/var/lib/docker", loadVersion); err != nil { return err } } // Load tag map logrus.Debugf("Loading docker images") pc, pk, err := StartDaemon("/usr/bin/docker-load", sr.config.DockerLoadLogCapturer) if err != nil { return fmt.Errorf("error starting daemon: %v", err) } // Remove all containers containers, err := pc.ListContainers(dockerclient.ListContainersOptions{All: true}) if err != nil { return fmt.Errorf("error listing containers: %v", err) } for _, container := range containers { logrus.Debugf("Removing container %s", container.ID) removeOptions := dockerclient.RemoveContainerOptions{ ID: container.ID, RemoveVolumes: true, Force: true, } if err := pc.RemoveContainer(removeOptions); err != nil { return fmt.Errorf("error removing container: %v", err) } } if err := syncImages(pc, "/images"); err != nil { return fmt.Errorf("error syncing images: %v", err) } logrus.Debugf("Stopping daemon") if err := pk(); err != nil { return fmt.Errorf("error killing daemon %v", err) } } // Run all setup scripts for _, setupScript := range sr.config.RunConfiguration.Setup { if err := RunScript(sr.config.SetupLogCapturer, setupScript); err != nil { return fmt.Errorf("error running setup script %s: %s", setupScript.Command[0], err) } } // Start Docker-in-Docker daemon for tests, build compose images if sr.config.DockerInDocker { logrus.Debugf("Starting daemon") _, k, err := StartDaemon("/usr/bin/docker", sr.config.DockerLogCapturer) if err != nil { return fmt.Errorf("error starting daemon: %s", err) } sr.daemonCloser = k if sr.config.ComposeFile != "" { logrus.Debugf("Build compose images") buildScript := Script{ Command: []string{"docker-compose", "-f", sr.config.ComposeFile, "build", "--no-cache"}, } if err := RunScript(sr.config.ComposeCapturer, buildScript); err != nil { return fmt.Errorf("error running docker compose build: %v", err) } upScript := Script{ Command: []string{"docker-compose", "-f", sr.config.ComposeFile, "up", "-d"}, } if err := RunScript(sr.config.ComposeCapturer, upScript); err != nil { return fmt.Errorf("error running docker compose up: %v", err) } go func() { logrus.Debugf("Listening for logs") logScript := Script{ Command: []string{"docker-compose", "-f", sr.config.ComposeFile, "logs"}, } if err := RunScript(sr.config.ComposeCapturer, logScript); err != nil { logrus.Errorf("Error running docker compose logs: %v", err) } }() } } return nil }
func main() { name := filepath.Base(os.Args[0]) if name == "golem_runner" { runnerMain() return } var ( dockerBinary string cacheDir string buildCache string ) co := clientutil.NewClientOptions() cm := runner.NewConfigurationManager() // Move Docker Specific options to separate type flag.StringVar(&dockerBinary, "db", "", "Docker binary to test") flag.StringVar(&cacheDir, "cache", "", "Cache directory") flag.StringVar(&buildCache, "build-cache", "", "Build cache location, if outside of default cache directory") // TODO: Add swarm flag and host option flag.Parse() // TODO: Allow quiet and verbose mode logrus.SetLevel(logrus.DebugLevel) if cacheDir == "" { td, err := ioutil.TempDir("", "build-cache-") if err != nil { logrus.Fatalf("Error creating tempdir: %v", err) } cacheDir = td defer os.RemoveAll(td) } if buildCache == "" { buildCache = filepath.Join(cacheDir, "builds") if err := os.MkdirAll(buildCache, 0755); err != nil { logrus.Fatalf("Error creating build cache directory") } } c := runner.CacheConfiguration{ ImageCache: runner.NewImageCache(filepath.Join(cacheDir, "images")), BuildCache: buildutil.NewFSBuildCache(buildCache), } if dockerBinary != "" { v, err := versionutil.BinaryVersion(dockerBinary) if err != nil { logrus.Fatalf("Error getting binary version of %s: %v", dockerBinary, err) } logrus.Debugf("Using local binary with version %s", v.String()) if err := c.BuildCache.PutVersion(v, dockerBinary); err != nil { logrus.Fatalf("Error putting %s in cache as %s: %v", dockerBinary, v, err) } flag.Set("docker-version", v.String()) } client, err := runner.NewDockerClient(co) if err != nil { logrus.Fatalf("Failed to create client: %v", err) } v, err := client.Version() if err != nil { logrus.Fatalf("Error getting version: %v", err) } serverVersion, err := versionutil.ParseVersion(v.Get("Version")) if err != nil { logrus.Fatalf("Unexpected version value: %s", v.Get("Version")) } // TODO: Support arbitrary load version instead of server version by // starting up separate daemon for load // TODO: Check cache here to ensure that load will not have issues logrus.Debugf("Using docker daemon for image export, version %s", serverVersion) r, err := cm.CreateRunner(serverVersion, c) if err != nil { logrus.Fatalf("Error creating runner: %v", err) } if err := r.Build(client); err != nil { logrus.Fatalf("Error building test images: %v", err) } if err := r.Run(client); err != nil { logrus.Fatalf("Error running tests: %v", err) } }