utils.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package docker
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. // Compare two Config struct. Do not compare the "Image" nor "Hostname" fields
  7. // If OpenStdin is set, then it differs
  8. func CompareConfig(a, b *Config) bool {
  9. if a == nil || b == nil ||
  10. a.OpenStdin || b.OpenStdin {
  11. return false
  12. }
  13. if a.AttachStdout != b.AttachStdout ||
  14. a.AttachStderr != b.AttachStderr ||
  15. a.User != b.User ||
  16. a.Memory != b.Memory ||
  17. a.MemorySwap != b.MemorySwap ||
  18. a.CpuShares != b.CpuShares ||
  19. a.OpenStdin != b.OpenStdin ||
  20. a.Tty != b.Tty ||
  21. a.VolumesFrom != b.VolumesFrom {
  22. return false
  23. }
  24. if len(a.Cmd) != len(b.Cmd) ||
  25. len(a.Dns) != len(b.Dns) ||
  26. len(a.Env) != len(b.Env) ||
  27. len(a.PortSpecs) != len(b.PortSpecs) ||
  28. len(a.Entrypoint) != len(b.Entrypoint) ||
  29. len(a.Volumes) != len(b.Volumes) {
  30. return false
  31. }
  32. for i := 0; i < len(a.Cmd); i++ {
  33. if a.Cmd[i] != b.Cmd[i] {
  34. return false
  35. }
  36. }
  37. for i := 0; i < len(a.Dns); i++ {
  38. if a.Dns[i] != b.Dns[i] {
  39. return false
  40. }
  41. }
  42. for i := 0; i < len(a.Env); i++ {
  43. if a.Env[i] != b.Env[i] {
  44. return false
  45. }
  46. }
  47. for i := 0; i < len(a.PortSpecs); i++ {
  48. if a.PortSpecs[i] != b.PortSpecs[i] {
  49. return false
  50. }
  51. }
  52. for i := 0; i < len(a.Entrypoint); i++ {
  53. if a.Entrypoint[i] != b.Entrypoint[i] {
  54. return false
  55. }
  56. }
  57. for key := range a.Volumes {
  58. if _, exists := b.Volumes[key]; !exists {
  59. return false
  60. }
  61. }
  62. return true
  63. }
  64. func MergeConfig(userConf, imageConf *Config) {
  65. if userConf.User == "" {
  66. userConf.User = imageConf.User
  67. }
  68. if userConf.Memory == 0 {
  69. userConf.Memory = imageConf.Memory
  70. }
  71. if userConf.MemorySwap == 0 {
  72. userConf.MemorySwap = imageConf.MemorySwap
  73. }
  74. if userConf.CpuShares == 0 {
  75. userConf.CpuShares = imageConf.CpuShares
  76. }
  77. if userConf.PortSpecs == nil || len(userConf.PortSpecs) == 0 {
  78. userConf.PortSpecs = imageConf.PortSpecs
  79. } else {
  80. for _, imagePortSpec := range imageConf.PortSpecs {
  81. found := false
  82. imageNat, _ := parseNat(imagePortSpec)
  83. for _, userPortSpec := range userConf.PortSpecs {
  84. userNat, _ := parseNat(userPortSpec)
  85. if imageNat.Proto == userNat.Proto && imageNat.Backend == userNat.Backend {
  86. found = true
  87. }
  88. }
  89. if !found {
  90. userConf.PortSpecs = append(userConf.PortSpecs, imagePortSpec)
  91. }
  92. }
  93. }
  94. if !userConf.Tty {
  95. userConf.Tty = imageConf.Tty
  96. }
  97. if !userConf.OpenStdin {
  98. userConf.OpenStdin = imageConf.OpenStdin
  99. }
  100. if !userConf.StdinOnce {
  101. userConf.StdinOnce = imageConf.StdinOnce
  102. }
  103. if userConf.Env == nil || len(userConf.Env) == 0 {
  104. userConf.Env = imageConf.Env
  105. } else {
  106. for _, imageEnv := range imageConf.Env {
  107. found := false
  108. imageEnvKey := strings.Split(imageEnv, "=")[0]
  109. for _, userEnv := range userConf.Env {
  110. userEnvKey := strings.Split(userEnv, "=")[0]
  111. if imageEnvKey == userEnvKey {
  112. found = true
  113. }
  114. }
  115. if !found {
  116. userConf.Env = append(userConf.Env, imageEnv)
  117. }
  118. }
  119. }
  120. if userConf.Cmd == nil || len(userConf.Cmd) == 0 {
  121. userConf.Cmd = imageConf.Cmd
  122. }
  123. if userConf.Dns == nil || len(userConf.Dns) == 0 {
  124. userConf.Dns = imageConf.Dns
  125. } else {
  126. //duplicates aren't an issue here
  127. userConf.Dns = append(userConf.Dns, imageConf.Dns...)
  128. }
  129. if userConf.Entrypoint == nil || len(userConf.Entrypoint) == 0 {
  130. userConf.Entrypoint = imageConf.Entrypoint
  131. }
  132. if userConf.WorkingDir == "" {
  133. userConf.WorkingDir = imageConf.WorkingDir
  134. }
  135. if userConf.VolumesFrom == "" {
  136. userConf.VolumesFrom = imageConf.VolumesFrom
  137. }
  138. if userConf.Volumes == nil || len(userConf.Volumes) == 0 {
  139. userConf.Volumes = imageConf.Volumes
  140. } else {
  141. for k, v := range imageConf.Volumes {
  142. userConf.Volumes[k] = v
  143. }
  144. }
  145. }
  146. func parseLxcConfOpts(opts ListOpts) ([]KeyValuePair, error) {
  147. out := make([]KeyValuePair, len(opts))
  148. for i, o := range opts {
  149. k, v, err := parseLxcOpt(o)
  150. if err != nil {
  151. return nil, err
  152. }
  153. out[i] = KeyValuePair{Key: k, Value: v}
  154. }
  155. return out, nil
  156. }
  157. func parseLxcOpt(opt string) (string, string, error) {
  158. parts := strings.SplitN(opt, "=", 2)
  159. if len(parts) != 2 {
  160. return "", "", fmt.Errorf("Unable to parse lxc conf option: %s", opt)
  161. }
  162. return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
  163. }