1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/utils.go
Solomon Hykes e6e320acc7 pkg/opts: a collection of custom value parsers implementing flag.Value
This facilitates the refactoring of commands.go.

Docker-DCO-1.1-Signed-off-by: Solomon Hykes <solomon@docker.com> (github: shykes)
2014-02-11 19:59:52 -08:00

282 lines
6.7 KiB
Go

package docker
import (
"fmt"
"github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/nat"
"github.com/dotcloud/docker/pkg/namesgenerator"
"github.com/dotcloud/docker/pkg/opts"
"github.com/dotcloud/docker/utils"
"io"
"strings"
"sync/atomic"
)
type Change struct {
archive.Change
}
// 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.ExposedPorts) != len(b.ExposedPorts) ||
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 k := range a.ExposedPorts {
if _, exists := b.ExposedPorts[k]; !exists {
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) error {
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.ExposedPorts == nil || len(userConf.ExposedPorts) == 0 {
userConf.ExposedPorts = imageConf.ExposedPorts
} else if imageConf.ExposedPorts != nil {
if userConf.ExposedPorts == nil {
userConf.ExposedPorts = make(nat.PortSet)
}
for port := range imageConf.ExposedPorts {
if _, exists := userConf.ExposedPorts[port]; !exists {
userConf.ExposedPorts[port] = struct{}{}
}
}
}
if userConf.PortSpecs != nil && len(userConf.PortSpecs) > 0 {
if userConf.ExposedPorts == nil {
userConf.ExposedPorts = make(nat.PortSet)
}
ports, _, err := nat.ParsePortSpecs(userConf.PortSpecs)
if err != nil {
return err
}
for port := range ports {
if _, exists := userConf.ExposedPorts[port]; !exists {
userConf.ExposedPorts[port] = struct{}{}
}
}
userConf.PortSpecs = nil
}
if imageConf.PortSpecs != nil && len(imageConf.PortSpecs) > 0 {
utils.Debugf("Migrating image port specs to containter: %s", strings.Join(imageConf.PortSpecs, ", "))
if userConf.ExposedPorts == nil {
userConf.ExposedPorts = make(nat.PortSet)
}
ports, _, err := nat.ParsePortSpecs(imageConf.PortSpecs)
if err != nil {
return err
}
for port := range ports {
if _, exists := userConf.ExposedPorts[port]; !exists {
userConf.ExposedPorts[port] = struct{}{}
}
}
}
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
}
}
return nil
}
func parseLxcConfOpts(opts opts.ListOpts) ([]KeyValuePair, error) {
out := make([]KeyValuePair, opts.Len())
for i, o := range opts.GetAll() {
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 migratePortMappings(config *Config, hostConfig *HostConfig) error {
if config.PortSpecs != nil {
ports, bindings, err := nat.ParsePortSpecs(config.PortSpecs)
if err != nil {
return err
}
config.PortSpecs = nil
if len(bindings) > 0 {
if hostConfig == nil {
hostConfig = &HostConfig{}
}
hostConfig.PortBindings = bindings
}
if config.ExposedPorts == nil {
config.ExposedPorts = make(nat.PortSet, len(ports))
}
for k, v := range ports {
config.ExposedPorts[k] = v
}
}
return nil
}
// Links come in the format of
// name:alias
func parseLink(rawLink string) (map[string]string, error) {
return utils.PartParser("name:alias", rawLink)
}
type checker struct {
runtime *Runtime
}
func (c *checker) Exists(name string) bool {
return c.runtime.containerGraph.Exists("/" + name)
}
// Generate a random and unique name
func generateRandomName(runtime *Runtime) (string, error) {
return namesgenerator.GenerateRandomName(&checker{runtime})
}
// Read an io.Reader and call a function when it returns EOF
func EofReader(r io.Reader, callback func()) *eofReader {
return &eofReader{
Reader: r,
callback: callback,
}
}
type eofReader struct {
io.Reader
gotEOF int32
callback func()
}
func (r *eofReader) Read(p []byte) (n int, err error) {
n, err = r.Reader.Read(p)
if err == io.EOF {
// Use atomics to make the gotEOF check threadsafe
if atomic.CompareAndSwapInt32(&r.gotEOF, 0, 1) {
r.callback()
}
}
return
}