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