2015-12-30 23:18:30 +00:00
|
|
|
// +build linux freebsd darwin solaris
|
2015-09-10 02:23:06 +00:00
|
|
|
|
|
|
|
package volume
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
Add new `HostConfig` field, `Mounts`.
`Mounts` allows users to specify in a much safer way the volumes they
want to use in the container.
This replaces `Binds` and `Volumes`, which both still exist, but
`Mounts` and `Binds`/`Volumes` are exclussive.
The CLI will continue to use `Binds` and `Volumes` due to concerns with
parsing the volume specs on the client side and cross-platform support
(for now).
The new API follows exactly the services mount API.
Example usage of `Mounts`:
```
$ curl -XPOST localhost:2375/containers/create -d '{
"Image": "alpine:latest",
"HostConfig": {
"Mounts": [{
"Type": "Volume",
"Target": "/foo"
},{
"Type": "bind",
"Source": "/var/run/docker.sock",
"Target": "/var/run/docker.sock",
},{
"Type": "volume",
"Name": "important_data",
"Target": "/var/data",
"ReadOnly": true,
"VolumeOptions": {
"DriverConfig": {
Name: "awesomeStorage",
Options: {"size": "10m"},
Labels: {"some":"label"}
}
}]
}
}'
```
There are currently 2 types of mounts:
- **bind**: Paths on the host that get mounted into the
container. Paths must exist prior to creating the container.
- **volume**: Volumes that persist after the
container is removed.
Not all fields are available in each type, and validation is done to
ensure these fields aren't mixed up between types.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-04-26 18:25:35 +00:00
|
|
|
"os"
|
2015-09-10 02:23:06 +00:00
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
2016-08-15 16:13:18 +00:00
|
|
|
|
2016-09-06 18:18:12 +00:00
|
|
|
mounttypes "github.com/docker/docker/api/types/mount"
|
2015-09-10 02:23:06 +00:00
|
|
|
)
|
|
|
|
|
Add new `HostConfig` field, `Mounts`.
`Mounts` allows users to specify in a much safer way the volumes they
want to use in the container.
This replaces `Binds` and `Volumes`, which both still exist, but
`Mounts` and `Binds`/`Volumes` are exclussive.
The CLI will continue to use `Binds` and `Volumes` due to concerns with
parsing the volume specs on the client side and cross-platform support
(for now).
The new API follows exactly the services mount API.
Example usage of `Mounts`:
```
$ curl -XPOST localhost:2375/containers/create -d '{
"Image": "alpine:latest",
"HostConfig": {
"Mounts": [{
"Type": "Volume",
"Target": "/foo"
},{
"Type": "bind",
"Source": "/var/run/docker.sock",
"Target": "/var/run/docker.sock",
},{
"Type": "volume",
"Name": "important_data",
"Target": "/var/data",
"ReadOnly": true,
"VolumeOptions": {
"DriverConfig": {
Name: "awesomeStorage",
Options: {"size": "10m"},
Labels: {"some":"label"}
}
}]
}
}'
```
There are currently 2 types of mounts:
- **bind**: Paths on the host that get mounted into the
container. Paths must exist prior to creating the container.
- **volume**: Volumes that persist after the
container is removed.
Not all fields are available in each type, and validation is done to
ensure these fields aren't mixed up between types.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-04-26 18:25:35 +00:00
|
|
|
var platformRawValidationOpts = []func(o *validateOpts){
|
|
|
|
// need to make sure to not error out if the bind source does not exist on unix
|
|
|
|
// this is supported for historical reasons, the path will be automatically
|
|
|
|
// created later.
|
|
|
|
func(o *validateOpts) { o.skipBindSourceCheck = true },
|
|
|
|
}
|
|
|
|
|
2015-09-10 02:23:06 +00:00
|
|
|
// read-write modes
|
|
|
|
var rwModes = map[string]bool{
|
2015-10-23 20:57:57 +00:00
|
|
|
"rw": true,
|
|
|
|
"ro": true,
|
2015-09-10 02:23:06 +00:00
|
|
|
}
|
|
|
|
|
2015-10-23 20:57:57 +00:00
|
|
|
// label modes
|
|
|
|
var labelModes = map[string]bool{
|
|
|
|
"Z": true,
|
|
|
|
"z": true,
|
2015-09-10 02:23:06 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 12:17:21 +00:00
|
|
|
// consistency modes
|
|
|
|
var consistencyModes = map[mounttypes.Consistency]bool{
|
|
|
|
mounttypes.ConsistencyFull: true,
|
|
|
|
mounttypes.ConsistencyCached: true,
|
|
|
|
mounttypes.ConsistencyDelegated: true,
|
|
|
|
}
|
|
|
|
|
2015-09-10 02:23:06 +00:00
|
|
|
// BackwardsCompatible decides whether this mount point can be
|
|
|
|
// used in old versions of Docker or not.
|
|
|
|
// Only bind mounts and local volumes can be used in old versions of Docker.
|
|
|
|
func (m *MountPoint) BackwardsCompatible() bool {
|
|
|
|
return len(m.Source) > 0 || m.Driver == DefaultDriverName
|
|
|
|
}
|
|
|
|
|
|
|
|
// HasResource checks whether the given absolute path for a container is in
|
|
|
|
// this mount point. If the relative path starts with `../` then the resource
|
|
|
|
// is outside of this mount point, but we can't simply check for this prefix
|
|
|
|
// because it misses `..` which is also outside of the mount, so check both.
|
|
|
|
func (m *MountPoint) HasResource(absolutePath string) bool {
|
|
|
|
relPath, err := filepath.Rel(m.Destination, absolutePath)
|
|
|
|
return err == nil && relPath != ".." && !strings.HasPrefix(relPath, fmt.Sprintf("..%c", filepath.Separator))
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsVolumeNameValid checks a volume name in a platform specific manner.
|
|
|
|
func IsVolumeNameValid(name string) (bool, error) {
|
|
|
|
return true, nil
|
|
|
|
}
|
2015-10-23 20:57:57 +00:00
|
|
|
|
|
|
|
// ValidMountMode will make sure the mount mode is valid.
|
|
|
|
// returns if it's a valid mount mode or not.
|
|
|
|
func ValidMountMode(mode string) bool {
|
Add new `HostConfig` field, `Mounts`.
`Mounts` allows users to specify in a much safer way the volumes they
want to use in the container.
This replaces `Binds` and `Volumes`, which both still exist, but
`Mounts` and `Binds`/`Volumes` are exclussive.
The CLI will continue to use `Binds` and `Volumes` due to concerns with
parsing the volume specs on the client side and cross-platform support
(for now).
The new API follows exactly the services mount API.
Example usage of `Mounts`:
```
$ curl -XPOST localhost:2375/containers/create -d '{
"Image": "alpine:latest",
"HostConfig": {
"Mounts": [{
"Type": "Volume",
"Target": "/foo"
},{
"Type": "bind",
"Source": "/var/run/docker.sock",
"Target": "/var/run/docker.sock",
},{
"Type": "volume",
"Name": "important_data",
"Target": "/var/data",
"ReadOnly": true,
"VolumeOptions": {
"DriverConfig": {
Name: "awesomeStorage",
Options: {"size": "10m"},
Labels: {"some":"label"}
}
}]
}
}'
```
There are currently 2 types of mounts:
- **bind**: Paths on the host that get mounted into the
container. Paths must exist prior to creating the container.
- **volume**: Volumes that persist after the
container is removed.
Not all fields are available in each type, and validation is done to
ensure these fields aren't mixed up between types.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-04-26 18:25:35 +00:00
|
|
|
if mode == "" {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2015-10-23 20:57:57 +00:00
|
|
|
rwModeCount := 0
|
|
|
|
labelModeCount := 0
|
|
|
|
propagationModeCount := 0
|
2016-03-15 03:31:42 +00:00
|
|
|
copyModeCount := 0
|
2017-02-07 12:17:21 +00:00
|
|
|
consistencyModeCount := 0
|
2015-10-23 20:57:57 +00:00
|
|
|
|
|
|
|
for _, o := range strings.Split(mode, ",") {
|
2016-03-15 03:31:42 +00:00
|
|
|
switch {
|
|
|
|
case rwModes[o]:
|
2015-10-23 20:57:57 +00:00
|
|
|
rwModeCount++
|
2016-03-15 03:31:42 +00:00
|
|
|
case labelModes[o]:
|
2015-10-23 20:57:57 +00:00
|
|
|
labelModeCount++
|
2016-08-15 16:13:18 +00:00
|
|
|
case propagationModes[mounttypes.Propagation(o)]:
|
2015-10-23 20:57:57 +00:00
|
|
|
propagationModeCount++
|
2016-03-15 03:31:42 +00:00
|
|
|
case copyModeExists(o):
|
|
|
|
copyModeCount++
|
2017-02-07 12:17:21 +00:00
|
|
|
case consistencyModes[mounttypes.Consistency(o)]:
|
|
|
|
consistencyModeCount++
|
2016-03-15 03:31:42 +00:00
|
|
|
default:
|
|
|
|
return false
|
2015-10-23 20:57:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only one string for each mode is allowed.
|
2017-02-07 12:17:21 +00:00
|
|
|
if rwModeCount > 1 || labelModeCount > 1 || propagationModeCount > 1 || copyModeCount > 1 || consistencyModeCount > 1 {
|
2015-10-23 20:57:57 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// ReadWrite tells you if a mode string is a valid read-write mode or not.
|
|
|
|
// If there are no specifications w.r.t read write mode, then by default
|
2016-03-09 16:17:57 +00:00
|
|
|
// it returns true.
|
2015-10-23 20:57:57 +00:00
|
|
|
func ReadWrite(mode string) bool {
|
|
|
|
if !ValidMountMode(mode) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, o := range strings.Split(mode, ",") {
|
|
|
|
if o == "ro" {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
Add new `HostConfig` field, `Mounts`.
`Mounts` allows users to specify in a much safer way the volumes they
want to use in the container.
This replaces `Binds` and `Volumes`, which both still exist, but
`Mounts` and `Binds`/`Volumes` are exclussive.
The CLI will continue to use `Binds` and `Volumes` due to concerns with
parsing the volume specs on the client side and cross-platform support
(for now).
The new API follows exactly the services mount API.
Example usage of `Mounts`:
```
$ curl -XPOST localhost:2375/containers/create -d '{
"Image": "alpine:latest",
"HostConfig": {
"Mounts": [{
"Type": "Volume",
"Target": "/foo"
},{
"Type": "bind",
"Source": "/var/run/docker.sock",
"Target": "/var/run/docker.sock",
},{
"Type": "volume",
"Name": "important_data",
"Target": "/var/data",
"ReadOnly": true,
"VolumeOptions": {
"DriverConfig": {
Name: "awesomeStorage",
Options: {"size": "10m"},
Labels: {"some":"label"}
}
}]
}
}'
```
There are currently 2 types of mounts:
- **bind**: Paths on the host that get mounted into the
container. Paths must exist prior to creating the container.
- **volume**: Volumes that persist after the
container is removed.
Not all fields are available in each type, and validation is done to
ensure these fields aren't mixed up between types.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2016-04-26 18:25:35 +00:00
|
|
|
|
|
|
|
func validateNotRoot(p string) error {
|
|
|
|
p = filepath.Clean(convertSlash(p))
|
|
|
|
if p == "/" {
|
|
|
|
return fmt.Errorf("invalid specification: destination can't be '/'")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func validateCopyMode(mode bool) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func convertSlash(p string) string {
|
|
|
|
return filepath.ToSlash(p)
|
|
|
|
}
|
|
|
|
|
|
|
|
func splitRawSpec(raw string) ([]string, error) {
|
|
|
|
if strings.Count(raw, ":") > 2 {
|
|
|
|
return nil, errInvalidSpec(raw)
|
|
|
|
}
|
|
|
|
|
|
|
|
arr := strings.SplitN(raw, ":", 3)
|
|
|
|
if arr[0] == "" {
|
|
|
|
return nil, errInvalidSpec(raw)
|
|
|
|
}
|
|
|
|
return arr, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func clean(p string) string {
|
|
|
|
return filepath.Clean(p)
|
|
|
|
}
|
|
|
|
|
|
|
|
func validateStat(fi os.FileInfo) error {
|
|
|
|
return nil
|
|
|
|
}
|