hostconfig_test.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. // +build !windows
  2. package runconfig
  3. import (
  4. "bytes"
  5. "fmt"
  6. "io/ioutil"
  7. "testing"
  8. "github.com/docker/docker/api/types/container"
  9. "github.com/docker/docker/pkg/sysinfo"
  10. "github.com/stretchr/testify/assert"
  11. )
  12. // TODO Windows: This will need addressing for a Windows daemon.
  13. func TestNetworkModeTest(t *testing.T) {
  14. networkModes := map[container.NetworkMode][]bool{
  15. // private, bridge, host, container, none, default
  16. "": {true, false, false, false, false, false},
  17. "something:weird": {true, false, false, false, false, false},
  18. "bridge": {true, true, false, false, false, false},
  19. DefaultDaemonNetworkMode(): {true, true, false, false, false, false},
  20. "host": {false, false, true, false, false, false},
  21. "container:name": {false, false, false, true, false, false},
  22. "none": {true, false, false, false, true, false},
  23. "default": {true, false, false, false, false, true},
  24. }
  25. networkModeNames := map[container.NetworkMode]string{
  26. "": "",
  27. "something:weird": "something:weird",
  28. "bridge": "bridge",
  29. DefaultDaemonNetworkMode(): "bridge",
  30. "host": "host",
  31. "container:name": "container",
  32. "none": "none",
  33. "default": "default",
  34. }
  35. for networkMode, state := range networkModes {
  36. if networkMode.IsPrivate() != state[0] {
  37. t.Fatalf("NetworkMode.IsPrivate for %v should have been %v but was %v", networkMode, state[0], networkMode.IsPrivate())
  38. }
  39. if networkMode.IsBridge() != state[1] {
  40. t.Fatalf("NetworkMode.IsBridge for %v should have been %v but was %v", networkMode, state[1], networkMode.IsBridge())
  41. }
  42. if networkMode.IsHost() != state[2] {
  43. t.Fatalf("NetworkMode.IsHost for %v should have been %v but was %v", networkMode, state[2], networkMode.IsHost())
  44. }
  45. if networkMode.IsContainer() != state[3] {
  46. t.Fatalf("NetworkMode.IsContainer for %v should have been %v but was %v", networkMode, state[3], networkMode.IsContainer())
  47. }
  48. if networkMode.IsNone() != state[4] {
  49. t.Fatalf("NetworkMode.IsNone for %v should have been %v but was %v", networkMode, state[4], networkMode.IsNone())
  50. }
  51. if networkMode.IsDefault() != state[5] {
  52. t.Fatalf("NetworkMode.IsDefault for %v should have been %v but was %v", networkMode, state[5], networkMode.IsDefault())
  53. }
  54. if networkMode.NetworkName() != networkModeNames[networkMode] {
  55. t.Fatalf("Expected name %v, got %v", networkModeNames[networkMode], networkMode.NetworkName())
  56. }
  57. }
  58. }
  59. func TestIpcModeTest(t *testing.T) {
  60. ipcModes := map[container.IpcMode]struct {
  61. private bool
  62. host bool
  63. container bool
  64. shareable bool
  65. valid bool
  66. ctrName string
  67. }{
  68. "": {valid: true},
  69. "private": {private: true, valid: true},
  70. "something:weird": {},
  71. ":weird": {},
  72. "host": {host: true, valid: true},
  73. "container": {},
  74. "container:": {container: true, valid: true, ctrName: ""},
  75. "container:name": {container: true, valid: true, ctrName: "name"},
  76. "container:name1:name2": {container: true, valid: true, ctrName: "name1:name2"},
  77. "shareable": {shareable: true, valid: true},
  78. }
  79. for ipcMode, state := range ipcModes {
  80. assert.Equal(t, state.private, ipcMode.IsPrivate(), "IpcMode.IsPrivate() parsing failed for %q", ipcMode)
  81. assert.Equal(t, state.host, ipcMode.IsHost(), "IpcMode.IsHost() parsing failed for %q", ipcMode)
  82. assert.Equal(t, state.container, ipcMode.IsContainer(), "IpcMode.IsContainer() parsing failed for %q", ipcMode)
  83. assert.Equal(t, state.shareable, ipcMode.IsShareable(), "IpcMode.IsShareable() parsing failed for %q", ipcMode)
  84. assert.Equal(t, state.valid, ipcMode.Valid(), "IpcMode.Valid() parsing failed for %q", ipcMode)
  85. assert.Equal(t, state.ctrName, ipcMode.Container(), "IpcMode.Container() parsing failed for %q", ipcMode)
  86. }
  87. }
  88. func TestUTSModeTest(t *testing.T) {
  89. utsModes := map[container.UTSMode][]bool{
  90. // private, host, valid
  91. "": {true, false, true},
  92. "something:weird": {true, false, false},
  93. "host": {false, true, true},
  94. "host:name": {true, false, true},
  95. }
  96. for utsMode, state := range utsModes {
  97. if utsMode.IsPrivate() != state[0] {
  98. t.Fatalf("UtsMode.IsPrivate for %v should have been %v but was %v", utsMode, state[0], utsMode.IsPrivate())
  99. }
  100. if utsMode.IsHost() != state[1] {
  101. t.Fatalf("UtsMode.IsHost for %v should have been %v but was %v", utsMode, state[1], utsMode.IsHost())
  102. }
  103. if utsMode.Valid() != state[2] {
  104. t.Fatalf("UtsMode.Valid for %v should have been %v but was %v", utsMode, state[2], utsMode.Valid())
  105. }
  106. }
  107. }
  108. func TestUsernsModeTest(t *testing.T) {
  109. usrensMode := map[container.UsernsMode][]bool{
  110. // private, host, valid
  111. "": {true, false, true},
  112. "something:weird": {true, false, false},
  113. "host": {false, true, true},
  114. "host:name": {true, false, true},
  115. }
  116. for usernsMode, state := range usrensMode {
  117. if usernsMode.IsPrivate() != state[0] {
  118. t.Fatalf("UsernsMode.IsPrivate for %v should have been %v but was %v", usernsMode, state[0], usernsMode.IsPrivate())
  119. }
  120. if usernsMode.IsHost() != state[1] {
  121. t.Fatalf("UsernsMode.IsHost for %v should have been %v but was %v", usernsMode, state[1], usernsMode.IsHost())
  122. }
  123. if usernsMode.Valid() != state[2] {
  124. t.Fatalf("UsernsMode.Valid for %v should have been %v but was %v", usernsMode, state[2], usernsMode.Valid())
  125. }
  126. }
  127. }
  128. func TestPidModeTest(t *testing.T) {
  129. pidModes := map[container.PidMode][]bool{
  130. // private, host, valid
  131. "": {true, false, true},
  132. "something:weird": {true, false, false},
  133. "host": {false, true, true},
  134. "host:name": {true, false, true},
  135. }
  136. for pidMode, state := range pidModes {
  137. if pidMode.IsPrivate() != state[0] {
  138. t.Fatalf("PidMode.IsPrivate for %v should have been %v but was %v", pidMode, state[0], pidMode.IsPrivate())
  139. }
  140. if pidMode.IsHost() != state[1] {
  141. t.Fatalf("PidMode.IsHost for %v should have been %v but was %v", pidMode, state[1], pidMode.IsHost())
  142. }
  143. if pidMode.Valid() != state[2] {
  144. t.Fatalf("PidMode.Valid for %v should have been %v but was %v", pidMode, state[2], pidMode.Valid())
  145. }
  146. }
  147. }
  148. func TestRestartPolicy(t *testing.T) {
  149. restartPolicies := map[container.RestartPolicy][]bool{
  150. // none, always, failure
  151. {}: {true, false, false},
  152. {Name: "something", MaximumRetryCount: 0}: {false, false, false},
  153. {Name: "no", MaximumRetryCount: 0}: {true, false, false},
  154. {Name: "always", MaximumRetryCount: 0}: {false, true, false},
  155. {Name: "on-failure", MaximumRetryCount: 0}: {false, false, true},
  156. }
  157. for restartPolicy, state := range restartPolicies {
  158. if restartPolicy.IsNone() != state[0] {
  159. t.Fatalf("RestartPolicy.IsNone for %v should have been %v but was %v", restartPolicy, state[0], restartPolicy.IsNone())
  160. }
  161. if restartPolicy.IsAlways() != state[1] {
  162. t.Fatalf("RestartPolicy.IsAlways for %v should have been %v but was %v", restartPolicy, state[1], restartPolicy.IsAlways())
  163. }
  164. if restartPolicy.IsOnFailure() != state[2] {
  165. t.Fatalf("RestartPolicy.IsOnFailure for %v should have been %v but was %v", restartPolicy, state[2], restartPolicy.IsOnFailure())
  166. }
  167. }
  168. }
  169. func TestDecodeHostConfig(t *testing.T) {
  170. fixtures := []struct {
  171. file string
  172. }{
  173. {"fixtures/unix/container_hostconfig_1_14.json"},
  174. {"fixtures/unix/container_hostconfig_1_19.json"},
  175. }
  176. for _, f := range fixtures {
  177. b, err := ioutil.ReadFile(f.file)
  178. if err != nil {
  179. t.Fatal(err)
  180. }
  181. c, err := decodeHostConfig(bytes.NewReader(b))
  182. if err != nil {
  183. t.Fatal(fmt.Errorf("Error parsing %s: %v", f, err))
  184. }
  185. assert.False(t, c.Privileged)
  186. if l := len(c.Binds); l != 1 {
  187. t.Fatalf("Expected 1 bind, found %d\n", l)
  188. }
  189. if len(c.CapAdd) != 1 && c.CapAdd[0] != "NET_ADMIN" {
  190. t.Fatalf("Expected CapAdd NET_ADMIN, got %v", c.CapAdd)
  191. }
  192. if len(c.CapDrop) != 1 && c.CapDrop[0] != "NET_ADMIN" {
  193. t.Fatalf("Expected CapDrop NET_ADMIN, got %v", c.CapDrop)
  194. }
  195. }
  196. }
  197. func TestValidateResources(t *testing.T) {
  198. type resourceTest struct {
  199. ConfigCPURealtimePeriod int64
  200. ConfigCPURealtimeRuntime int64
  201. SysInfoCPURealtimePeriod bool
  202. SysInfoCPURealtimeRuntime bool
  203. ErrorExpected bool
  204. FailureMsg string
  205. }
  206. tests := []resourceTest{
  207. {
  208. ConfigCPURealtimePeriod: 1000,
  209. ConfigCPURealtimeRuntime: 1000,
  210. SysInfoCPURealtimePeriod: true,
  211. SysInfoCPURealtimeRuntime: true,
  212. ErrorExpected: false,
  213. FailureMsg: "Expected valid configuration",
  214. },
  215. {
  216. ConfigCPURealtimePeriod: 5000,
  217. ConfigCPURealtimeRuntime: 5000,
  218. SysInfoCPURealtimePeriod: false,
  219. SysInfoCPURealtimeRuntime: true,
  220. ErrorExpected: true,
  221. FailureMsg: "Expected failure when cpu-rt-period is set but kernel doesn't support it",
  222. },
  223. {
  224. ConfigCPURealtimePeriod: 5000,
  225. ConfigCPURealtimeRuntime: 5000,
  226. SysInfoCPURealtimePeriod: true,
  227. SysInfoCPURealtimeRuntime: false,
  228. ErrorExpected: true,
  229. FailureMsg: "Expected failure when cpu-rt-runtime is set but kernel doesn't support it",
  230. },
  231. {
  232. ConfigCPURealtimePeriod: 5000,
  233. ConfigCPURealtimeRuntime: 10000,
  234. SysInfoCPURealtimePeriod: true,
  235. SysInfoCPURealtimeRuntime: false,
  236. ErrorExpected: true,
  237. FailureMsg: "Expected failure when cpu-rt-runtime is greater than cpu-rt-period",
  238. },
  239. }
  240. for _, rt := range tests {
  241. var hc container.HostConfig
  242. hc.Resources.CPURealtimePeriod = rt.ConfigCPURealtimePeriod
  243. hc.Resources.CPURealtimeRuntime = rt.ConfigCPURealtimeRuntime
  244. var si sysinfo.SysInfo
  245. si.CPURealtimePeriod = rt.SysInfoCPURealtimePeriod
  246. si.CPURealtimeRuntime = rt.SysInfoCPURealtimeRuntime
  247. if err := validateResources(&hc, &si); (err != nil) != rt.ErrorExpected {
  248. t.Fatal(rt.FailureMsg, err)
  249. }
  250. }
  251. }