Example #1
0
// cmdMount implements MOUNT command
// TODO: document behavior of cmdMount
func (builder *Builder) cmdMount(args []string, attributes map[string]bool, flags map[string]string, original string) error {
	if len(args) == 0 {
		return fmt.Errorf("Command is missing value: %s", original)
	}

	// TODO: read flags
	useCache := false

	newMounts := []*builderMount{}
	newVolumeMounts := []*builderMount{}

	for _, arg := range args {
		var mount builderMount
		if strings.Contains(arg, ":") {
			pair := strings.SplitN(arg, ":", 2)
			mount = builderMount{cache: useCache, src: pair[0], dest: pair[1]}
		} else {
			mount = builderMount{cache: useCache, dest: arg}
		}

		if mount.src == "" {
			newVolumeMounts = append(newVolumeMounts, &mount)
		} else {
			// Process relative paths in volumes
			if strings.HasPrefix(mount.src, "~") {
				mount.src = strings.Replace(mount.src, "~", os.Getenv("HOME"), 1)
			}
			if !path.IsAbs(mount.src) {
				mount.src = path.Join(builder.ContextDir, mount.src)
			}
			mount.origSrc = mount.src

			var err error

			if mount.src, err = dockerclient.ResolveHostPath(mount.src, builder.Docker); err != nil {
				return err
			}
		}

		newMounts = append(newMounts, &mount)
	}

	// For volume mounts we need to create (or use existing) volume container
	if len(newVolumeMounts) > 0 {
		// Collect destinations and sort them alphabetically
		// so changing the order on MOUNT commend does not have any effect
		dests := make([]string, len(newVolumeMounts))
		containerVolumes := make(map[string]struct{})

		for i, mount := range newVolumeMounts {
			dests[i] = mount.dest
			containerVolumes[mount.dest] = struct{}{}
		}
		sort.Strings(dests)

		volumeContainerName := builder.mountsContainerName(dests)

		containerConfig := &docker.Config{
			Image:   busyboxImage,
			Volumes: containerVolumes,
			Labels: map[string]string{
				"Volumes":    strings.Join(dests, ":"),
				"Rockerfile": builder.Rockerfile,
				"ImageId":    builder.imageID,
			},
		}

		container, err := builder.ensureContainer(volumeContainerName, containerConfig, strings.Join(dests, ","))
		if err != nil {
			return err
		}

		// Assing volume container to the list of volume mounts
		for _, mount := range newVolumeMounts {
			mount.containerID = container.ID
		}
	}

	mountIds := make([]string, len(newMounts))

	for i, mount := range newMounts {
		builder.addMount(*mount)
		mountIds[i] = mount.String()
	}

	// TODO: check is useCache flag enabled, so we have to make checksum of the directory

	if err := builder.commitContainer("", builder.Config.Cmd, fmt.Sprintf("MOUNT %q", mountIds)); err != nil {
		return err
	}

	return nil
}
Example #2
0
// ResolveHostPath proxy for the dockerclient.ResolveHostPath
func (c *DockerClient) ResolveHostPath(path string) (resultPath string, err error) {
	return dockerclient.ResolveHostPath(path, c.client)
}