// 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 }
// ResolveHostPath proxy for the dockerclient.ResolveHostPath func (c *DockerClient) ResolveHostPath(path string) (resultPath string, err error) { return dockerclient.ResolveHostPath(path, c.client) }