-
Notifications
You must be signed in to change notification settings - Fork 285
Add volume mount support for job containers #1057
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| package jobcontainers | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "os" | ||
| "path/filepath" | ||
| "strings" | ||
|
|
||
| specs "github.com/opencontainers/runtime-spec/specs-go" | ||
| "github.com/pkg/errors" | ||
| ) | ||
|
|
||
| // namedPipePath returns true if the given path is to a named pipe. | ||
| func isnamedPipePath(p string) bool { | ||
| return strings.HasPrefix(p, `\\.\pipe\`) | ||
| } | ||
|
|
||
| // Strip the drive letter (if there is one) so we don't end up with "%CONTAINER_SANDBOX_MOUNT_POINT%"\C:\path\to\mount | ||
| func stripDriveLetter(name string) string { | ||
| // Remove drive letter | ||
| if len(name) == 2 && name[1] == ':' { | ||
| name = "." | ||
| } else if len(name) > 2 && name[1] == ':' { | ||
| name = name[2:] | ||
| } | ||
| return name | ||
| } | ||
|
|
||
| // setupMounts adds the custom mounts requested in the OCI runtime spec. Mounts are a bit funny as you already have | ||
| // access to everything on the host, so just symlink in whatever was requested to the path where the container volume | ||
| // is mounted. At least then the mount can be accessed from a path relative to the default working directory/where the volume | ||
| // is. | ||
| func setupMounts(spec *specs.Spec, sandboxVolumePath string) error { | ||
| for _, mount := range spec.Mounts { | ||
| if mount.Destination == "" || mount.Source == "" { | ||
| return fmt.Errorf("invalid OCI spec - a mount must have both source and a destination: %+v", mount) | ||
| } | ||
|
|
||
| if isnamedPipePath(mount.Source) { | ||
| return errors.New("named pipe mounts not supported for job containers - interact with the pipe directly") | ||
| } | ||
|
|
||
| fullCtrPath := filepath.Join(sandboxVolumePath, stripDriveLetter(mount.Destination)) | ||
| // Make sure all of the dirs leading up to the full path exist. | ||
| strippedCtrPath := filepath.Dir(fullCtrPath) | ||
| if err := os.MkdirAll(strippedCtrPath, 0777); err != nil { | ||
| return errors.Wrap(err, "failed to make directory for job container mount") | ||
| } | ||
|
|
||
| if err := os.Symlink(mount.Source, fullCtrPath); err != nil { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there an expectation based on standard container mount behavior that a mount over an existing path will mask the existing path? os.Symlink will fail if the target exists.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct yea. At the bindflt level I'd assume there's nothing stopping a shadowing of whatever was there, but I'm not sure if hcs has any logic to disallow this. Let me give it a whirl, that's a good point.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @msscotb Yea the behavior on Windows (and Linux but I knew this part) is to mask whatever is there. I don't know how we could mimic this without bindflt :/
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @msscotb Was this a blocking comment or just a "curious what happens in a normal container scenario"?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @msscotb ping on this
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see a better option since binding as we do for standard containers is not possible with the process isolated design current. |
||
| return errors.Wrap(err, "failed to setup mount for job container") | ||
| } | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package jobcontainers | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| specs "github.com/opencontainers/runtime-spec/specs-go" | ||
| ) | ||
|
|
||
| func TestNamePipeDeny(t *testing.T) { | ||
| s := &specs.Spec{ | ||
| Mounts: []specs.Mount{ | ||
| { | ||
| Destination: "/path/in/container", | ||
| Source: `\\.\pipe\dummy\path`, | ||
| }, | ||
| }, | ||
| } | ||
| if err := setupMounts(s, "/test"); err == nil { | ||
| t.Fatal("expected named pipe mount validation to fail for job container") | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.