Example #1
0
// 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
}
Example #2
0
// 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
}
Example #3
0
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)
	}
}