예제 #1
0
// EnsureItExists make sure the volume exists and return an error if it does not exists
// and cannot be created.
func (v *Volume) EnsureItExists(ctx context.Context) error {
	volumeResource, err := v.Inspect(ctx)
	if v.external {
		if client.IsErrVolumeNotFound(err) {
			// FIXME(shouze) introduce some libcompose error type
			return fmt.Errorf("Volume %s declared as external, but could not be found. Please create the volume manually using docker volume create %s and try again", v.name, v.name)
		}
		return err
	}
	if err != nil && client.IsErrVolumeNotFound(err) {
		return v.create(ctx)
	}
	if volumeResource.Driver != v.driver {
		return fmt.Errorf("Volume %q needs to be recreated - driver has changed", v.name)
	}
	return err
}
예제 #2
0
파일: runner.go 프로젝트: docker/golem
// Run starts the test instance containers as well as any
// containers which will manage the tests and waits for
// the results.
func (r *runner) Run(cli DockerClient) error {
	var (
		failedTests int
		runTests    int
		runnerStart = time.Now()
		ctx         = context.Background()
	)

	// TODO: Run in parallel
	// TODO: validate namespace when in parallel mode
	for _, suite := range r.config.Suites {
		for _, instance := range suite.Instances {
			// TODO: Add configuration for nocache
			nocache := false
			contName := "golem-" + instance.Name
			// TODO: Use image ID and not image name
			imageName := r.imageName(instance.Name)

			logFields := logrus.Fields{
				"instance":  instance.Name,
				"image":     imageName,
				"container": contName,
			}
			logrus.WithFields(logFields).Info("running instance")

			hc := &container.HostConfig{
				Privileged:   true,
				VolumeDriver: "local",
			}

			args := []string{}
			if suite.DockerInDocker {
				args = append(args, "-docker")
			}
			if r.debug {
				args = append(args, "-debug")
			}
			// TODO: Add argument for instance name

			config := &container.Config{
				Image:      imageName,
				Cmd:        append([]string{r.config.ExecutableName}, args...),
				WorkingDir: "/runner",
				Volumes: map[string]struct{}{
					"/var/log/docker": {},
				},
			}

			if suite.DockerInDocker {
				config.Env = append(config.Env, "DOCKER_GRAPHDRIVER="+getGraphDriver())

				// TODO: In parallel mode, do not use a cached volume
				volumeName := contName + "-graph"
				cont, err := cli.ContainerInspect(ctx, contName)
				if err == nil {
					removeOptions := types.ContainerRemoveOptions{
						RemoveVolumes: true,
					}
					if err := cli.ContainerRemove(ctx, cont.ID, removeOptions); err != nil {
						return fmt.Errorf("error removing existing container %s: %v", contName, err)
					}
				}

				var createVolume bool
				vol, err := cli.VolumeInspect(ctx, volumeName)
				if err == nil {
					if nocache {
						if err := cli.VolumeRemove(ctx, vol.Name); err != nil {
							return fmt.Errorf("error removing volume %s: %v", vol.Name, err)
						}
						createVolume = true
					}
				} else if client.IsErrVolumeNotFound(err) {
					createVolume = true
				} else {
					return fmt.Errorf("error inspecting volume: %v", err)
				}

				if createVolume {
					createOptions := types.VolumeCreateRequest{
						Name:   volumeName,
						Driver: "local",
					}
					vol, err = cli.VolumeCreate(ctx, createOptions)
					if err != nil {
						return fmt.Errorf("error creating volume: %v", err)
					}
				}

				// TODO: Use volume name instead of mountpoint
				logrus.Debugf("Mounting %s to %s", vol.Mountpoint, "/var/lib/docker")
				hc.Binds = append(hc.Binds, fmt.Sprintf("%s:/var/lib/docker", vol.Mountpoint))
			}

			nc := &network.NetworkingConfig{}

			container, err := cli.ContainerCreate(ctx, config, hc, nc, contName)
			if err != nil {
				return fmt.Errorf("error creating container: %s", err)
			}

			for _, warning := range container.Warnings {
				logrus.Warnf("Container %q create warning: %v", contName, warning)
			}

			if err := cli.ContainerStart(ctx, container.ID); err != nil {
				return fmt.Errorf("error starting container: %s", err)
			}

			attachOptions := types.ContainerAttachOptions{
				Stream: true,
				Stdout: true,
				Stderr: true,
			}
			resp, err := cli.ContainerAttach(ctx, container.ID, attachOptions)
			if err != nil {
				return fmt.Errorf("Error attaching to container: %v", err)
			}

			// TODO: Capture output for parallel mode
			if _, err := stdcopy.StdCopy(os.Stdout, os.Stderr, resp.Reader); err != nil {
				return fmt.Errorf("Error copying output stream: %v", err)
			}

			inspectedContainer, err := cli.ContainerInspect(ctx, container.ID)
			if err != nil {
				return fmt.Errorf("Error inspecting container: %v", err)
			}
			runTests = runTests + 1
			if inspectedContainer.State.ExitCode > 0 {
				logrus.Errorf("Test failed with exit code %d", inspectedContainer.State.ExitCode)
				failedTests = failedTests + 1
			}
		}
	}

	logFields := logrus.Fields{
		timerKey: time.Since(runnerStart),
		"ran":    runTests,
		"failed": failedTests,
	}
	logrus.WithFields(logFields).Info("test runner complete")

	if failedTests > 0 {
		return fmt.Errorf("test failure: %d of %d tests failed", failedTests, runTests)
	}

	return nil
}