"output_path": "/tmp"
</code></pre>|Specified path refers to the file *hello.txt* in the *alice* subdirectory|./*foo* 030326... 0:13:*bar*\n
*Note:* Here the subdirectory *alice* is replaced with *foo* and the filename *hello.txt* from this subdirectory is replaced with *bar*.|
+
+h2(#symlinks-in-output). Symlinks in output
+
+When a container's output_path is a tmp mount backed by local disk, this output directory can contain symlinks to other files in the the output directory, or to collection mount points. If the symlink leads to a collection mount, efficiently copy the collection into the output collection. Symlinks leading to files or directories are expanded and created as regular files in the output collection. Further, whether symlinks are relative or absolute, every symlink target (even targets that are symlinks themselves) must either remain in the output directory or point to a collection mount.
|environment|hash|Environment variables and values that should be set in the container environment (@docker run --env@). This augments and (when conflicts exist) overrides environment variables given in the image's Dockerfile.||
|cwd|string|Initial working directory, given as an absolute path (in the container) or a path relative to the WORKDIR given in the image's Dockerfile.|Required.|
|command|array of strings|Command to execute in the container.|Required. e.g., @["echo","hello"]@|
-|output_path|string|Path to a directory or file inside the container that should be preserved as container's output when it finishes. This path must be, or be inside, one of the mount targets. For best performance, point output_path to a writable collection mount. Also, see "Pre-populate output using Mount points":#pre-populate-output for details regarding optional output pre-population using mount points.|Required.|
+|output_path|string|Path to a directory or file inside the container that should be preserved as container's output when it finishes. This path must be one of the mount targets. For best performance, point output_path to a writable collection mount. See "Pre-populate output using Mount points":#pre-populate-output for details regarding optional output pre-population using mount points and "Symlinks in output":#symlinks-in-output for additional details.|Required.|
|output_name|string|Desired name for the output collection. If null, a name will be assigned automatically.||
|output_ttl|integer|Desired lifetime for the output collection, in seconds. If zero, the output collection will not be deleted automatically.||
|priority|integer|Higher value means spend more resources on this container_request, i.e., go ahead of other queued containers, bring up more nodes etc.|Priority 0 means a container should not be run on behalf of this request. Clients are expected to submit container requests with zero priority in order to preview the container that will be used to satisfy it. Priority can be null if and only if state!="Committed".|
return nil
}
-var NotInOutputDirError = fmt.Errorf("Must point to path within the output directory")
+var ErrNotInOutputDir = fmt.Errorf("Must point to path within the output directory")
func (runner *ContainerRunner) derefOutputSymlink(path string, startinfo os.FileInfo) (tgt string, readlinktgt string, info os.FileInfo, err error) {
// Follow symlinks if necessary
readlinktgt = ""
nextlink := path
for followed := 0; info.Mode()&os.ModeSymlink != 0; followed++ {
- if followed >= 16 {
+ if followed >= limitFollowSymlinks {
// Got stuck in a loop or just a pathological number of links, give up.
- err = fmt.Errorf("Followed too many symlinks from path %q", path)
+ err = fmt.Errorf("Followed more than %v symlinks from path %q", limitFollowSymlinks, path)
return
}
// After dereferencing, symlink target must either be
// within output directory, or must point to a
// collection mount.
- err = NotInOutputDirError
+ err = ErrNotInOutputDir
return
}
return
}
+var limitFollowSymlinks = 10
+
// UploadFile uploads files within the output directory, with special handling
// for symlinks. If the symlink leads to a keep mount, copy the manifest text
// from the keep mount into the output manifestText. Ensure that whether
-// symlinks are relative or absolute, they must remain within the output
-// directory.
+// symlinks are relative or absolute, every symlink target (even targets that
+// are symlinks themselves) must either remain in the output directory or point
+// to a collection mount.
//
// Assumes initial value of "path" is absolute, and located within runner.HostOutputDir.
func (runner *ContainerRunner) UploadOutputFile(
return "", infoerr
}
- if followed >= 8 {
+ if followed >= limitFollowSymlinks {
// Got stuck in a loop or just a pathological number of
// directory links, give up.
- err = fmt.Errorf("Followed too many symlinks from path %q", path)
+ err = fmt.Errorf("Followed more than %v symlinks from path %q", limitFollowSymlinks, path)
return
}