mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
7d566b4f76
This happened for me on the last (empty) line, but better safe than sorry so we make the check general.
184 lines
4.4 KiB
Go
184 lines
4.4 KiB
Go
package docker
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"strings"
|
|
)
|
|
|
|
// Compare two Config struct. Do not compare the "Image" nor "Hostname" fields
|
|
// If OpenStdin is set, then it differs
|
|
func CompareConfig(a, b *Config) bool {
|
|
if a == nil || b == nil ||
|
|
a.OpenStdin || b.OpenStdin {
|
|
return false
|
|
}
|
|
if a.AttachStdout != b.AttachStdout ||
|
|
a.AttachStderr != b.AttachStderr ||
|
|
a.User != b.User ||
|
|
a.Memory != b.Memory ||
|
|
a.MemorySwap != b.MemorySwap ||
|
|
a.CpuShares != b.CpuShares ||
|
|
a.OpenStdin != b.OpenStdin ||
|
|
a.Tty != b.Tty ||
|
|
a.VolumesFrom != b.VolumesFrom {
|
|
return false
|
|
}
|
|
if len(a.Cmd) != len(b.Cmd) ||
|
|
len(a.Dns) != len(b.Dns) ||
|
|
len(a.Env) != len(b.Env) ||
|
|
len(a.PortSpecs) != len(b.PortSpecs) ||
|
|
len(a.Entrypoint) != len(b.Entrypoint) ||
|
|
len(a.Volumes) != len(b.Volumes) {
|
|
return false
|
|
}
|
|
|
|
for i := 0; i < len(a.Cmd); i++ {
|
|
if a.Cmd[i] != b.Cmd[i] {
|
|
return false
|
|
}
|
|
}
|
|
for i := 0; i < len(a.Dns); i++ {
|
|
if a.Dns[i] != b.Dns[i] {
|
|
return false
|
|
}
|
|
}
|
|
for i := 0; i < len(a.Env); i++ {
|
|
if a.Env[i] != b.Env[i] {
|
|
return false
|
|
}
|
|
}
|
|
for i := 0; i < len(a.PortSpecs); i++ {
|
|
if a.PortSpecs[i] != b.PortSpecs[i] {
|
|
return false
|
|
}
|
|
}
|
|
for i := 0; i < len(a.Entrypoint); i++ {
|
|
if a.Entrypoint[i] != b.Entrypoint[i] {
|
|
return false
|
|
}
|
|
}
|
|
for key := range a.Volumes {
|
|
if _, exists := b.Volumes[key]; !exists {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func MergeConfig(userConf, imageConf *Config) {
|
|
if userConf.User == "" {
|
|
userConf.User = imageConf.User
|
|
}
|
|
if userConf.Memory == 0 {
|
|
userConf.Memory = imageConf.Memory
|
|
}
|
|
if userConf.MemorySwap == 0 {
|
|
userConf.MemorySwap = imageConf.MemorySwap
|
|
}
|
|
if userConf.CpuShares == 0 {
|
|
userConf.CpuShares = imageConf.CpuShares
|
|
}
|
|
if userConf.PortSpecs == nil || len(userConf.PortSpecs) == 0 {
|
|
userConf.PortSpecs = imageConf.PortSpecs
|
|
} else {
|
|
for _, imagePortSpec := range imageConf.PortSpecs {
|
|
found := false
|
|
imageNat, _ := parseNat(imagePortSpec)
|
|
for _, userPortSpec := range userConf.PortSpecs {
|
|
userNat, _ := parseNat(userPortSpec)
|
|
if imageNat.Proto == userNat.Proto && imageNat.Backend == userNat.Backend {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
userConf.PortSpecs = append(userConf.PortSpecs, imagePortSpec)
|
|
}
|
|
}
|
|
}
|
|
if !userConf.Tty {
|
|
userConf.Tty = imageConf.Tty
|
|
}
|
|
if !userConf.OpenStdin {
|
|
userConf.OpenStdin = imageConf.OpenStdin
|
|
}
|
|
if !userConf.StdinOnce {
|
|
userConf.StdinOnce = imageConf.StdinOnce
|
|
}
|
|
if userConf.Env == nil || len(userConf.Env) == 0 {
|
|
userConf.Env = imageConf.Env
|
|
} else {
|
|
for _, imageEnv := range imageConf.Env {
|
|
found := false
|
|
imageEnvKey := strings.Split(imageEnv, "=")[0]
|
|
for _, userEnv := range userConf.Env {
|
|
userEnvKey := strings.Split(userEnv, "=")[0]
|
|
if imageEnvKey == userEnvKey {
|
|
found = true
|
|
}
|
|
}
|
|
if !found {
|
|
userConf.Env = append(userConf.Env, imageEnv)
|
|
}
|
|
}
|
|
}
|
|
if userConf.Cmd == nil || len(userConf.Cmd) == 0 {
|
|
userConf.Cmd = imageConf.Cmd
|
|
}
|
|
if userConf.Dns == nil || len(userConf.Dns) == 0 {
|
|
userConf.Dns = imageConf.Dns
|
|
} else {
|
|
//duplicates aren't an issue here
|
|
userConf.Dns = append(userConf.Dns, imageConf.Dns...)
|
|
}
|
|
if userConf.Entrypoint == nil || len(userConf.Entrypoint) == 0 {
|
|
userConf.Entrypoint = imageConf.Entrypoint
|
|
}
|
|
if userConf.WorkingDir == "" {
|
|
userConf.WorkingDir = imageConf.WorkingDir
|
|
}
|
|
if userConf.VolumesFrom == "" {
|
|
userConf.VolumesFrom = imageConf.VolumesFrom
|
|
}
|
|
if userConf.Volumes == nil || len(userConf.Volumes) == 0 {
|
|
userConf.Volumes = imageConf.Volumes
|
|
} else {
|
|
for k, v := range imageConf.Volumes {
|
|
userConf.Volumes[k] = v
|
|
}
|
|
}
|
|
}
|
|
|
|
func parseLxcConfOpts(opts ListOpts) ([]KeyValuePair, error) {
|
|
out := make([]KeyValuePair, len(opts))
|
|
for i, o := range opts {
|
|
k, v, err := parseLxcOpt(o)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
out[i] = KeyValuePair{Key: k, Value: v}
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func parseLxcOpt(opt string) (string, string, error) {
|
|
parts := strings.SplitN(opt, "=", 2)
|
|
if len(parts) != 2 {
|
|
return "", "", fmt.Errorf("Unable to parse lxc conf option: %s", opt)
|
|
}
|
|
return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
|
|
}
|
|
|
|
func RootIsShared() bool {
|
|
if data, err := ioutil.ReadFile("/proc/self/mountinfo"); err == nil {
|
|
for _, line := range strings.Split(string(data), "\n") {
|
|
cols := strings.Split(line, " ")
|
|
if len(cols) >= 6 && cols[3] == "/" && cols[4] == "/" {
|
|
return strings.HasPrefix(cols[6], "shared")
|
|
}
|
|
}
|
|
}
|
|
|
|
// No idea, probably safe to assume so
|
|
return true
|
|
}
|