This also migrates the volumes from integration tests into the new cli
integration test framework.
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
| ... | ... |
@@ -312,3 +312,75 @@ func TestVolumesMountedAsReadonly(t *testing.T) {
|
| 312 | 312 |
|
| 313 | 313 |
logDone("run - volumes as readonly mount")
|
| 314 | 314 |
} |
| 315 |
+ |
|
| 316 |
+func TestVolumesFromInReadonlyMode(t *testing.T) {
|
|
| 317 |
+ cmd := exec.Command(dockerBinary, "run", "--name", "parent", "-v", "/test", "busybox", "true") |
|
| 318 |
+ if _, err := runCommand(cmd); err != nil {
|
|
| 319 |
+ t.Fatal(err) |
|
| 320 |
+ } |
|
| 321 |
+ |
|
| 322 |
+ cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent:ro", "busybox", "touch", "/test/file") |
|
| 323 |
+ if code, err := runCommand(cmd); err == nil || code == 0 {
|
|
| 324 |
+ t.Fatalf("run should fail because volume is ro: exit code %d", code)
|
|
| 325 |
+ } |
|
| 326 |
+ |
|
| 327 |
+ deleteAllContainers() |
|
| 328 |
+ |
|
| 329 |
+ logDone("run - volumes from as readonly mount")
|
|
| 330 |
+} |
|
| 331 |
+ |
|
| 332 |
+// Regression test for #1201 |
|
| 333 |
+func TestVolumesFromInReadWriteMode(t *testing.T) {
|
|
| 334 |
+ cmd := exec.Command(dockerBinary, "run", "--name", "parent", "-v", "/test", "busybox", "true") |
|
| 335 |
+ if _, err := runCommand(cmd); err != nil {
|
|
| 336 |
+ t.Fatal(err) |
|
| 337 |
+ } |
|
| 338 |
+ |
|
| 339 |
+ cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent", "busybox", "touch", "/test/file") |
|
| 340 |
+ if _, err := runCommand(cmd); err != nil {
|
|
| 341 |
+ t.Fatal(err) |
|
| 342 |
+ } |
|
| 343 |
+ |
|
| 344 |
+ deleteAllContainers() |
|
| 345 |
+ |
|
| 346 |
+ logDone("run - volumes from as read write mount")
|
|
| 347 |
+} |
|
| 348 |
+ |
|
| 349 |
+// Test for #1351 |
|
| 350 |
+func TestApplyVolumesFromBeforeVolumes(t *testing.T) {
|
|
| 351 |
+ cmd := exec.Command(dockerBinary, "run", "--name", "parent", "-v", "/test", "busybox", "touch", "/test/foo") |
|
| 352 |
+ if _, err := runCommand(cmd); err != nil {
|
|
| 353 |
+ t.Fatal(err) |
|
| 354 |
+ } |
|
| 355 |
+ |
|
| 356 |
+ cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent", "-v", "/test", "busybox", "cat", "/test/foo") |
|
| 357 |
+ if _, err := runCommand(cmd); err != nil {
|
|
| 358 |
+ t.Fatal(err) |
|
| 359 |
+ } |
|
| 360 |
+ |
|
| 361 |
+ deleteAllContainers() |
|
| 362 |
+ |
|
| 363 |
+ logDone("run - volumes from mounted first")
|
|
| 364 |
+} |
|
| 365 |
+ |
|
| 366 |
+func TestMultipleVolumesFrom(t *testing.T) {
|
|
| 367 |
+ cmd := exec.Command(dockerBinary, "run", "--name", "parent1", "-v", "/test", "busybox", "touch", "/test/foo") |
|
| 368 |
+ if _, err := runCommand(cmd); err != nil {
|
|
| 369 |
+ t.Fatal(err) |
|
| 370 |
+ } |
|
| 371 |
+ |
|
| 372 |
+ cmd = exec.Command(dockerBinary, "run", "--name", "parent2", "-v", "/other", "busybox", "touch", "/other/bar") |
|
| 373 |
+ if _, err := runCommand(cmd); err != nil {
|
|
| 374 |
+ t.Fatal(err) |
|
| 375 |
+ } |
|
| 376 |
+ |
|
| 377 |
+ cmd = exec.Command(dockerBinary, "run", "--volumes-from", "parent1", "--volumes-from", "parent2", |
|
| 378 |
+ "busybox", "sh", "-c", "cat /test/foo && cat /other/bar") |
|
| 379 |
+ if _, err := runCommand(cmd); err != nil {
|
|
| 380 |
+ t.Fatal(err) |
|
| 381 |
+ } |
|
| 382 |
+ |
|
| 383 |
+ deleteAllContainers() |
|
| 384 |
+ |
|
| 385 |
+ logDone("run - multiple volumes from")
|
|
| 386 |
+} |
| ... | ... |
@@ -1273,123 +1273,6 @@ func TestBindMounts(t *testing.T) {
|
| 1273 | 1273 |
} |
| 1274 | 1274 |
} |
| 1275 | 1275 |
|
| 1276 |
-// Test that -volumes-from supports both read-only mounts |
|
| 1277 |
-func TestFromVolumesInReadonlyMode(t *testing.T) {
|
|
| 1278 |
- runtime := mkRuntime(t) |
|
| 1279 |
- defer nuke(runtime) |
|
| 1280 |
- container, _, err := runtime.Create( |
|
| 1281 |
- &runconfig.Config{
|
|
| 1282 |
- Image: GetTestImage(runtime).ID, |
|
| 1283 |
- Cmd: []string{"/bin/echo", "-n", "foobar"},
|
|
| 1284 |
- Volumes: map[string]struct{}{"/test": {}},
|
|
| 1285 |
- }, |
|
| 1286 |
- "", |
|
| 1287 |
- ) |
|
| 1288 |
- if err != nil {
|
|
| 1289 |
- t.Fatal(err) |
|
| 1290 |
- } |
|
| 1291 |
- defer runtime.Destroy(container) |
|
| 1292 |
- _, err = container.Output() |
|
| 1293 |
- if err != nil {
|
|
| 1294 |
- t.Fatal(err) |
|
| 1295 |
- } |
|
| 1296 |
- if !container.VolumesRW["/test"] {
|
|
| 1297 |
- t.Fail() |
|
| 1298 |
- } |
|
| 1299 |
- |
|
| 1300 |
- container2, _, err := runtime.Create( |
|
| 1301 |
- &runconfig.Config{
|
|
| 1302 |
- Image: GetTestImage(runtime).ID, |
|
| 1303 |
- Cmd: []string{"/bin/echo", "-n", "foobar"},
|
|
| 1304 |
- VolumesFrom: container.ID + ":ro", |
|
| 1305 |
- }, |
|
| 1306 |
- "", |
|
| 1307 |
- ) |
|
| 1308 |
- if err != nil {
|
|
| 1309 |
- t.Fatal(err) |
|
| 1310 |
- } |
|
| 1311 |
- defer runtime.Destroy(container2) |
|
| 1312 |
- |
|
| 1313 |
- _, err = container2.Output() |
|
| 1314 |
- if err != nil {
|
|
| 1315 |
- t.Fatal(err) |
|
| 1316 |
- } |
|
| 1317 |
- |
|
| 1318 |
- if container.Volumes["/test"] != container2.Volumes["/test"] {
|
|
| 1319 |
- t.Logf("container volumes do not match: %s | %s ",
|
|
| 1320 |
- container.Volumes["/test"], |
|
| 1321 |
- container2.Volumes["/test"]) |
|
| 1322 |
- t.Fail() |
|
| 1323 |
- } |
|
| 1324 |
- |
|
| 1325 |
- _, exists := container2.VolumesRW["/test"] |
|
| 1326 |
- if !exists {
|
|
| 1327 |
- t.Logf("container2 is missing '/test' volume: %s", container2.VolumesRW)
|
|
| 1328 |
- t.Fail() |
|
| 1329 |
- } |
|
| 1330 |
- |
|
| 1331 |
- if container2.VolumesRW["/test"] != false {
|
|
| 1332 |
- t.Log("'/test' volume mounted in read-write mode, expected read-only")
|
|
| 1333 |
- t.Fail() |
|
| 1334 |
- } |
|
| 1335 |
-} |
|
| 1336 |
- |
|
| 1337 |
-// Test that VolumesRW values are copied to the new container. Regression test for #1201 |
|
| 1338 |
-func TestVolumesFromReadonlyMount(t *testing.T) {
|
|
| 1339 |
- runtime := mkRuntime(t) |
|
| 1340 |
- defer nuke(runtime) |
|
| 1341 |
- container, _, err := runtime.Create( |
|
| 1342 |
- &runconfig.Config{
|
|
| 1343 |
- Image: GetTestImage(runtime).ID, |
|
| 1344 |
- Cmd: []string{"/bin/echo", "-n", "foobar"},
|
|
| 1345 |
- Volumes: map[string]struct{}{"/test": {}},
|
|
| 1346 |
- }, |
|
| 1347 |
- "", |
|
| 1348 |
- ) |
|
| 1349 |
- if err != nil {
|
|
| 1350 |
- t.Fatal(err) |
|
| 1351 |
- } |
|
| 1352 |
- defer runtime.Destroy(container) |
|
| 1353 |
- _, err = container.Output() |
|
| 1354 |
- if err != nil {
|
|
| 1355 |
- t.Fatal(err) |
|
| 1356 |
- } |
|
| 1357 |
- if !container.VolumesRW["/test"] {
|
|
| 1358 |
- t.Fail() |
|
| 1359 |
- } |
|
| 1360 |
- |
|
| 1361 |
- container2, _, err := runtime.Create( |
|
| 1362 |
- &runconfig.Config{
|
|
| 1363 |
- Image: GetTestImage(runtime).ID, |
|
| 1364 |
- Cmd: []string{"/bin/echo", "-n", "foobar"},
|
|
| 1365 |
- VolumesFrom: container.ID, |
|
| 1366 |
- }, |
|
| 1367 |
- "", |
|
| 1368 |
- ) |
|
| 1369 |
- if err != nil {
|
|
| 1370 |
- t.Fatal(err) |
|
| 1371 |
- } |
|
| 1372 |
- defer runtime.Destroy(container2) |
|
| 1373 |
- |
|
| 1374 |
- _, err = container2.Output() |
|
| 1375 |
- if err != nil {
|
|
| 1376 |
- t.Fatal(err) |
|
| 1377 |
- } |
|
| 1378 |
- |
|
| 1379 |
- if container.Volumes["/test"] != container2.Volumes["/test"] {
|
|
| 1380 |
- t.Fail() |
|
| 1381 |
- } |
|
| 1382 |
- |
|
| 1383 |
- actual, exists := container2.VolumesRW["/test"] |
|
| 1384 |
- if !exists {
|
|
| 1385 |
- t.Fail() |
|
| 1386 |
- } |
|
| 1387 |
- |
|
| 1388 |
- if container.VolumesRW["/test"] != actual {
|
|
| 1389 |
- t.Fail() |
|
| 1390 |
- } |
|
| 1391 |
-} |
|
| 1392 |
- |
|
| 1393 | 1276 |
// Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819. |
| 1394 | 1277 |
func TestRestartWithVolumes(t *testing.T) {
|
| 1395 | 1278 |
runtime := mkRuntime(t) |
| ... | ... |
@@ -1434,73 +1317,6 @@ func TestRestartWithVolumes(t *testing.T) {
|
| 1434 | 1434 |
} |
| 1435 | 1435 |
} |
| 1436 | 1436 |
|
| 1437 |
-// Test for #1351 |
|
| 1438 |
-func TestVolumesFromWithVolumes(t *testing.T) {
|
|
| 1439 |
- runtime := mkRuntime(t) |
|
| 1440 |
- defer nuke(runtime) |
|
| 1441 |
- |
|
| 1442 |
- container, _, err := runtime.Create(&runconfig.Config{
|
|
| 1443 |
- Image: GetTestImage(runtime).ID, |
|
| 1444 |
- Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
|
|
| 1445 |
- Volumes: map[string]struct{}{"/test": {}},
|
|
| 1446 |
- }, |
|
| 1447 |
- "", |
|
| 1448 |
- ) |
|
| 1449 |
- if err != nil {
|
|
| 1450 |
- t.Fatal(err) |
|
| 1451 |
- } |
|
| 1452 |
- defer runtime.Destroy(container) |
|
| 1453 |
- |
|
| 1454 |
- for key := range container.Config.Volumes {
|
|
| 1455 |
- if key != "/test" {
|
|
| 1456 |
- t.Fail() |
|
| 1457 |
- } |
|
| 1458 |
- } |
|
| 1459 |
- |
|
| 1460 |
- _, err = container.Output() |
|
| 1461 |
- if err != nil {
|
|
| 1462 |
- t.Fatal(err) |
|
| 1463 |
- } |
|
| 1464 |
- |
|
| 1465 |
- expected := container.Volumes["/test"] |
|
| 1466 |
- if expected == "" {
|
|
| 1467 |
- t.Fail() |
|
| 1468 |
- } |
|
| 1469 |
- |
|
| 1470 |
- container2, _, err := runtime.Create( |
|
| 1471 |
- &runconfig.Config{
|
|
| 1472 |
- Image: GetTestImage(runtime).ID, |
|
| 1473 |
- Cmd: []string{"cat", "/test/foo"},
|
|
| 1474 |
- VolumesFrom: container.ID, |
|
| 1475 |
- Volumes: map[string]struct{}{"/test": {}},
|
|
| 1476 |
- }, |
|
| 1477 |
- "", |
|
| 1478 |
- ) |
|
| 1479 |
- if err != nil {
|
|
| 1480 |
- t.Fatal(err) |
|
| 1481 |
- } |
|
| 1482 |
- defer runtime.Destroy(container2) |
|
| 1483 |
- |
|
| 1484 |
- output, err := container2.Output() |
|
| 1485 |
- if err != nil {
|
|
| 1486 |
- t.Fatal(err) |
|
| 1487 |
- } |
|
| 1488 |
- |
|
| 1489 |
- if string(output) != "bar" {
|
|
| 1490 |
- t.Fail() |
|
| 1491 |
- } |
|
| 1492 |
- |
|
| 1493 |
- if container.Volumes["/test"] != container2.Volumes["/test"] {
|
|
| 1494 |
- t.Fail() |
|
| 1495 |
- } |
|
| 1496 |
- |
|
| 1497 |
- // Ensure it restarts successfully |
|
| 1498 |
- _, err = container2.Output() |
|
| 1499 |
- if err != nil {
|
|
| 1500 |
- t.Fatal(err) |
|
| 1501 |
- } |
|
| 1502 |
-} |
|
| 1503 |
- |
|
| 1504 | 1437 |
func TestContainerNetwork(t *testing.T) {
|
| 1505 | 1438 |
runtime := mkRuntime(t) |
| 1506 | 1439 |
defer nuke(runtime) |
| ... | ... |
@@ -1636,81 +1452,3 @@ func TestUnprivilegedCannotMount(t *testing.T) {
|
| 1636 | 1636 |
t.Fatal("Could mount into secure container")
|
| 1637 | 1637 |
} |
| 1638 | 1638 |
} |
| 1639 |
- |
|
| 1640 |
-func TestMultipleVolumesFrom(t *testing.T) {
|
|
| 1641 |
- runtime := mkRuntime(t) |
|
| 1642 |
- defer nuke(runtime) |
|
| 1643 |
- |
|
| 1644 |
- container, _, err := runtime.Create(&runconfig.Config{
|
|
| 1645 |
- Image: GetTestImage(runtime).ID, |
|
| 1646 |
- Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
|
|
| 1647 |
- Volumes: map[string]struct{}{"/test": {}},
|
|
| 1648 |
- }, |
|
| 1649 |
- "", |
|
| 1650 |
- ) |
|
| 1651 |
- if err != nil {
|
|
| 1652 |
- t.Fatal(err) |
|
| 1653 |
- } |
|
| 1654 |
- defer runtime.Destroy(container) |
|
| 1655 |
- |
|
| 1656 |
- for key := range container.Config.Volumes {
|
|
| 1657 |
- if key != "/test" {
|
|
| 1658 |
- t.Fail() |
|
| 1659 |
- } |
|
| 1660 |
- } |
|
| 1661 |
- |
|
| 1662 |
- _, err = container.Output() |
|
| 1663 |
- if err != nil {
|
|
| 1664 |
- t.Fatal(err) |
|
| 1665 |
- } |
|
| 1666 |
- |
|
| 1667 |
- expected := container.Volumes["/test"] |
|
| 1668 |
- if expected == "" {
|
|
| 1669 |
- t.Fail() |
|
| 1670 |
- } |
|
| 1671 |
- |
|
| 1672 |
- container2, _, err := runtime.Create( |
|
| 1673 |
- &runconfig.Config{
|
|
| 1674 |
- Image: GetTestImage(runtime).ID, |
|
| 1675 |
- Cmd: []string{"sh", "-c", "echo -n bar > /other/foo"},
|
|
| 1676 |
- Volumes: map[string]struct{}{"/other": {}},
|
|
| 1677 |
- }, |
|
| 1678 |
- "", |
|
| 1679 |
- ) |
|
| 1680 |
- if err != nil {
|
|
| 1681 |
- t.Fatal(err) |
|
| 1682 |
- } |
|
| 1683 |
- defer runtime.Destroy(container2) |
|
| 1684 |
- |
|
| 1685 |
- for key := range container2.Config.Volumes {
|
|
| 1686 |
- if key != "/other" {
|
|
| 1687 |
- t.FailNow() |
|
| 1688 |
- } |
|
| 1689 |
- } |
|
| 1690 |
- if _, err := container2.Output(); err != nil {
|
|
| 1691 |
- t.Fatal(err) |
|
| 1692 |
- } |
|
| 1693 |
- |
|
| 1694 |
- container3, _, err := runtime.Create( |
|
| 1695 |
- &runconfig.Config{
|
|
| 1696 |
- Image: GetTestImage(runtime).ID, |
|
| 1697 |
- Cmd: []string{"/bin/echo", "-n", "foobar"},
|
|
| 1698 |
- VolumesFrom: strings.Join([]string{container.ID, container2.ID}, ","),
|
|
| 1699 |
- }, "") |
|
| 1700 |
- |
|
| 1701 |
- if err != nil {
|
|
| 1702 |
- t.Fatal(err) |
|
| 1703 |
- } |
|
| 1704 |
- defer runtime.Destroy(container3) |
|
| 1705 |
- |
|
| 1706 |
- if _, err := container3.Output(); err != nil {
|
|
| 1707 |
- t.Fatal(err) |
|
| 1708 |
- } |
|
| 1709 |
- |
|
| 1710 |
- if container3.Volumes["/test"] != container.Volumes["/test"] {
|
|
| 1711 |
- t.Fail() |
|
| 1712 |
- } |
|
| 1713 |
- if container3.Volumes["/other"] != container2.Volumes["/other"] {
|
|
| 1714 |
- t.Fail() |
|
| 1715 |
- } |
|
| 1716 |
-} |
| ... | ... |
@@ -14,8 +14,7 @@ func Compare(a, b *Config) bool {
|
| 14 | 14 |
a.MemorySwap != b.MemorySwap || |
| 15 | 15 |
a.CpuShares != b.CpuShares || |
| 16 | 16 |
a.OpenStdin != b.OpenStdin || |
| 17 |
- a.Tty != b.Tty || |
|
| 18 |
- a.VolumesFrom != b.VolumesFrom {
|
|
| 17 |
+ a.Tty != b.Tty {
|
|
| 19 | 18 |
return false |
| 20 | 19 |
} |
| 21 | 20 |
if len(a.Cmd) != len(b.Cmd) || |
| ... | ... |
@@ -27,7 +27,6 @@ type Config struct {
|
| 27 | 27 |
Cmd []string |
| 28 | 28 |
Image string // Name of the image as it was passed by the operator (eg. could be symbolic) |
| 29 | 29 |
Volumes map[string]struct{}
|
| 30 |
- VolumesFrom string |
|
| 31 | 30 |
WorkingDir string |
| 32 | 31 |
Entrypoint []string |
| 33 | 32 |
NetworkDisabled bool |
| ... | ... |
@@ -49,7 +48,6 @@ func ContainerConfigFromJob(job *engine.Job) *Config {
|
| 49 | 49 |
OpenStdin: job.GetenvBool("OpenStdin"),
|
| 50 | 50 |
StdinOnce: job.GetenvBool("StdinOnce"),
|
| 51 | 51 |
Image: job.Getenv("Image"),
|
| 52 |
- VolumesFrom: job.Getenv("VolumesFrom"),
|
|
| 53 | 52 |
WorkingDir: job.Getenv("WorkingDir"),
|
| 54 | 53 |
NetworkDisabled: job.GetenvBool("NetworkDisabled"),
|
| 55 | 54 |
} |
| ... | ... |
@@ -163,37 +163,25 @@ func TestCompare(t *testing.T) {
|
| 163 | 163 |
volumes1 := make(map[string]struct{})
|
| 164 | 164 |
volumes1["/test1"] = struct{}{}
|
| 165 | 165 |
config1 := Config{
|
| 166 |
- PortSpecs: []string{"1111:1111", "2222:2222"},
|
|
| 167 |
- Env: []string{"VAR1=1", "VAR2=2"},
|
|
| 168 |
- VolumesFrom: "11111111", |
|
| 169 |
- Volumes: volumes1, |
|
| 166 |
+ PortSpecs: []string{"1111:1111", "2222:2222"},
|
|
| 167 |
+ Env: []string{"VAR1=1", "VAR2=2"},
|
|
| 168 |
+ Volumes: volumes1, |
|
| 170 | 169 |
} |
| 171 | 170 |
config3 := Config{
|
| 172 |
- PortSpecs: []string{"0000:0000", "2222:2222"},
|
|
| 173 |
- Env: []string{"VAR1=1", "VAR2=2"},
|
|
| 174 |
- VolumesFrom: "11111111", |
|
| 175 |
- Volumes: volumes1, |
|
| 176 |
- } |
|
| 177 |
- config4 := Config{
|
|
| 178 |
- PortSpecs: []string{"0000:0000", "2222:2222"},
|
|
| 179 |
- Env: []string{"VAR1=1", "VAR2=2"},
|
|
| 180 |
- VolumesFrom: "22222222", |
|
| 181 |
- Volumes: volumes1, |
|
| 171 |
+ PortSpecs: []string{"0000:0000", "2222:2222"},
|
|
| 172 |
+ Env: []string{"VAR1=1", "VAR2=2"},
|
|
| 173 |
+ Volumes: volumes1, |
|
| 182 | 174 |
} |
| 183 | 175 |
volumes2 := make(map[string]struct{})
|
| 184 | 176 |
volumes2["/test2"] = struct{}{}
|
| 185 | 177 |
config5 := Config{
|
| 186 |
- PortSpecs: []string{"0000:0000", "2222:2222"},
|
|
| 187 |
- Env: []string{"VAR1=1", "VAR2=2"},
|
|
| 188 |
- VolumesFrom: "11111111", |
|
| 189 |
- Volumes: volumes2, |
|
| 178 |
+ PortSpecs: []string{"0000:0000", "2222:2222"},
|
|
| 179 |
+ Env: []string{"VAR1=1", "VAR2=2"},
|
|
| 180 |
+ Volumes: volumes2, |
|
| 190 | 181 |
} |
| 191 | 182 |
if Compare(&config1, &config3) {
|
| 192 | 183 |
t.Fatalf("Compare should return false, PortSpecs are different")
|
| 193 | 184 |
} |
| 194 |
- if Compare(&config1, &config4) {
|
|
| 195 |
- t.Fatalf("Compare should return false, VolumesFrom are different")
|
|
| 196 |
- } |
|
| 197 | 185 |
if Compare(&config1, &config5) {
|
| 198 | 186 |
t.Fatalf("Compare should return false, Volumes are different")
|
| 199 | 187 |
} |
| ... | ... |
@@ -207,10 +195,9 @@ func TestMerge(t *testing.T) {
|
| 207 | 207 |
volumesImage["/test1"] = struct{}{}
|
| 208 | 208 |
volumesImage["/test2"] = struct{}{}
|
| 209 | 209 |
configImage := &Config{
|
| 210 |
- PortSpecs: []string{"1111:1111", "2222:2222"},
|
|
| 211 |
- Env: []string{"VAR1=1", "VAR2=2"},
|
|
| 212 |
- VolumesFrom: "1111", |
|
| 213 |
- Volumes: volumesImage, |
|
| 210 |
+ PortSpecs: []string{"1111:1111", "2222:2222"},
|
|
| 211 |
+ Env: []string{"VAR1=1", "VAR2=2"},
|
|
| 212 |
+ Volumes: volumesImage, |
|
| 214 | 213 |
} |
| 215 | 214 |
|
| 216 | 215 |
volumesUser := make(map[string]struct{})
|
| ... | ... |
@@ -251,10 +238,6 @@ func TestMerge(t *testing.T) {
|
| 251 | 251 |
} |
| 252 | 252 |
} |
| 253 | 253 |
|
| 254 |
- if configUser.VolumesFrom != "1111" {
|
|
| 255 |
- t.Fatalf("Expected VolumesFrom to be 1111, found %s", configUser.VolumesFrom)
|
|
| 256 |
- } |
|
| 257 |
- |
|
| 258 | 254 |
ports, _, err := nat.ParsePortSpecs([]string{"0000"})
|
| 259 | 255 |
if err != nil {
|
| 260 | 256 |
t.Error(err) |
| ... | ... |
@@ -16,6 +16,7 @@ type HostConfig struct {
|
| 16 | 16 |
PublishAllPorts bool |
| 17 | 17 |
Dns []string |
| 18 | 18 |
DnsSearch []string |
| 19 |
+ VolumesFrom string |
|
| 19 | 20 |
} |
| 20 | 21 |
|
| 21 | 22 |
func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
|
| ... | ... |
@@ -23,6 +24,7 @@ func ContainerHostConfigFromJob(job *engine.Job) *HostConfig {
|
| 23 | 23 |
ContainerIDFile: job.Getenv("ContainerIDFile"),
|
| 24 | 24 |
Privileged: job.GetenvBool("Privileged"),
|
| 25 | 25 |
PublishAllPorts: job.GetenvBool("PublishAllPorts"),
|
| 26 |
+ VolumesFrom: job.Getenv("VolumesFrom"),
|
|
| 26 | 27 |
} |
| 27 | 28 |
job.GetenvJson("LxcConf", &hostConfig.LxcConf)
|
| 28 | 29 |
job.GetenvJson("PortBindings", &hostConfig.PortBindings)
|
| ... | ... |
@@ -100,9 +100,6 @@ func Merge(userConf, imageConf *Config) error {
|
| 100 | 100 |
if userConf.WorkingDir == "" {
|
| 101 | 101 |
userConf.WorkingDir = imageConf.WorkingDir |
| 102 | 102 |
} |
| 103 |
- if userConf.VolumesFrom == "" {
|
|
| 104 |
- userConf.VolumesFrom = imageConf.VolumesFrom |
|
| 105 |
- } |
|
| 106 | 103 |
if userConf.Volumes == nil || len(userConf.Volumes) == 0 {
|
| 107 | 104 |
userConf.Volumes = imageConf.Volumes |
| 108 | 105 |
} else {
|
| ... | ... |
@@ -215,7 +215,6 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf |
| 215 | 215 |
Cmd: runCmd, |
| 216 | 216 |
Image: image, |
| 217 | 217 |
Volumes: flVolumes.GetMap(), |
| 218 |
- VolumesFrom: strings.Join(flVolumesFrom.GetAll(), ","), |
|
| 219 | 218 |
Entrypoint: entrypoint, |
| 220 | 219 |
WorkingDir: *flWorkingDir, |
| 221 | 220 |
} |
| ... | ... |
@@ -230,6 +229,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf |
| 230 | 230 |
PublishAllPorts: *flPublishAll, |
| 231 | 231 |
Dns: flDns.GetAll(), |
| 232 | 232 |
DnsSearch: flDnsSearch.GetAll(), |
| 233 |
+ VolumesFrom: strings.Join(flVolumesFrom.GetAll(), ","), |
|
| 233 | 234 |
} |
| 234 | 235 |
|
| 235 | 236 |
if sysInfo != nil && flMemory > 0 && !sysInfo.SwapLimit {
|
| ... | ... |
@@ -59,8 +59,9 @@ func setupMountsForContainer(container *Container, envPath string) error {
|
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 | 61 |
func applyVolumesFrom(container *Container) error {
|
| 62 |
- if container.Config.VolumesFrom != "" {
|
|
| 63 |
- for _, containerSpec := range strings.Split(container.Config.VolumesFrom, ",") {
|
|
| 62 |
+ volumesFrom := container.hostConfig.VolumesFrom |
|
| 63 |
+ if volumesFrom != "" {
|
|
| 64 |
+ for _, containerSpec := range strings.Split(volumesFrom, ",") {
|
|
| 64 | 65 |
var ( |
| 65 | 66 |
mountRW = true |
| 66 | 67 |
specParts = strings.SplitN(containerSpec, ":", 2) |
| ... | ... |
@@ -68,7 +69,7 @@ func applyVolumesFrom(container *Container) error {
|
| 68 | 68 |
|
| 69 | 69 |
switch len(specParts) {
|
| 70 | 70 |
case 0: |
| 71 |
- return fmt.Errorf("Malformed volumes-from specification: %s", container.Config.VolumesFrom)
|
|
| 71 |
+ return fmt.Errorf("Malformed volumes-from specification: %s", volumesFrom)
|
|
| 72 | 72 |
case 2: |
| 73 | 73 |
switch specParts[1] {
|
| 74 | 74 |
case "ro": |