|
@@ -2,14 +2,21 @@ package container // import "github.com/docker/docker/integration/container"
|
|
|
|
|
|
import (
|
|
|
"context"
|
|
|
+ "encoding/json"
|
|
|
+ "fmt"
|
|
|
"strconv"
|
|
|
"testing"
|
|
|
+ "time"
|
|
|
|
|
|
+ "github.com/docker/docker/api/types"
|
|
|
"github.com/docker/docker/api/types/container"
|
|
|
"github.com/docker/docker/api/types/network"
|
|
|
+ ctr "github.com/docker/docker/integration/internal/container"
|
|
|
"github.com/docker/docker/internal/test/request"
|
|
|
+ "github.com/docker/docker/oci"
|
|
|
"github.com/gotestyourself/gotestyourself/assert"
|
|
|
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
|
|
+ "github.com/gotestyourself/gotestyourself/poll"
|
|
|
"github.com/gotestyourself/gotestyourself/skip"
|
|
|
)
|
|
|
|
|
@@ -137,3 +144,160 @@ func TestCreateTmpfsMountsTarget(t *testing.T) {
|
|
|
assert.Check(t, is.ErrorContains(err, tc.expectedError))
|
|
|
}
|
|
|
}
|
|
|
+func TestCreateWithCustomMaskedPaths(t *testing.T) {
|
|
|
+ skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
|
|
+
|
|
|
+ defer setupTest(t)()
|
|
|
+ client := request.NewAPIClient(t)
|
|
|
+ ctx := context.Background()
|
|
|
+
|
|
|
+ testCases := []struct {
|
|
|
+ maskedPaths []string
|
|
|
+ expected []string
|
|
|
+ }{
|
|
|
+ {
|
|
|
+ maskedPaths: []string{},
|
|
|
+ expected: []string{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ maskedPaths: nil,
|
|
|
+ expected: oci.DefaultSpec().Linux.MaskedPaths,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ maskedPaths: []string{"/proc/kcore", "/proc/keys"},
|
|
|
+ expected: []string{"/proc/kcore", "/proc/keys"},
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ checkInspect := func(t *testing.T, ctx context.Context, name string, expected []string) {
|
|
|
+ _, b, err := client.ContainerInspectWithRaw(ctx, name, false)
|
|
|
+ assert.NilError(t, err)
|
|
|
+
|
|
|
+ var inspectJSON map[string]interface{}
|
|
|
+ err = json.Unmarshal(b, &inspectJSON)
|
|
|
+ assert.NilError(t, err)
|
|
|
+
|
|
|
+ cfg, ok := inspectJSON["HostConfig"].(map[string]interface{})
|
|
|
+ assert.Check(t, is.Equal(true, ok), name)
|
|
|
+
|
|
|
+ maskedPaths, ok := cfg["MaskedPaths"].([]interface{})
|
|
|
+ assert.Check(t, is.Equal(true, ok), name)
|
|
|
+
|
|
|
+ mps := []string{}
|
|
|
+ for _, mp := range maskedPaths {
|
|
|
+ mps = append(mps, mp.(string))
|
|
|
+ }
|
|
|
+
|
|
|
+ assert.DeepEqual(t, expected, mps)
|
|
|
+ }
|
|
|
+
|
|
|
+ for i, tc := range testCases {
|
|
|
+ name := fmt.Sprintf("create-masked-paths-%d", i)
|
|
|
+ config := container.Config{
|
|
|
+ Image: "busybox",
|
|
|
+ Cmd: []string{"true"},
|
|
|
+ }
|
|
|
+ hc := container.HostConfig{}
|
|
|
+ if tc.maskedPaths != nil {
|
|
|
+ hc.MaskedPaths = tc.maskedPaths
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create the container.
|
|
|
+ c, err := client.ContainerCreate(context.Background(),
|
|
|
+ &config,
|
|
|
+ &hc,
|
|
|
+ &network.NetworkingConfig{},
|
|
|
+ name,
|
|
|
+ )
|
|
|
+ assert.NilError(t, err)
|
|
|
+
|
|
|
+ checkInspect(t, ctx, name, tc.expected)
|
|
|
+
|
|
|
+ // Start the container.
|
|
|
+ err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{})
|
|
|
+ assert.NilError(t, err)
|
|
|
+
|
|
|
+ poll.WaitOn(t, ctr.IsInState(ctx, client, c.ID, "exited"), poll.WithDelay(100*time.Millisecond))
|
|
|
+
|
|
|
+ checkInspect(t, ctx, name, tc.expected)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestCreateWithCustomReadonlyPaths(t *testing.T) {
|
|
|
+ skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
|
|
+
|
|
|
+ defer setupTest(t)()
|
|
|
+ client := request.NewAPIClient(t)
|
|
|
+ ctx := context.Background()
|
|
|
+
|
|
|
+ testCases := []struct {
|
|
|
+ doc string
|
|
|
+ readonlyPaths []string
|
|
|
+ expected []string
|
|
|
+ }{
|
|
|
+ {
|
|
|
+ readonlyPaths: []string{},
|
|
|
+ expected: []string{},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ readonlyPaths: nil,
|
|
|
+ expected: oci.DefaultSpec().Linux.ReadonlyPaths,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ readonlyPaths: []string{"/proc/asound", "/proc/bus"},
|
|
|
+ expected: []string{"/proc/asound", "/proc/bus"},
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ checkInspect := func(t *testing.T, ctx context.Context, name string, expected []string) {
|
|
|
+ _, b, err := client.ContainerInspectWithRaw(ctx, name, false)
|
|
|
+ assert.NilError(t, err)
|
|
|
+
|
|
|
+ var inspectJSON map[string]interface{}
|
|
|
+ err = json.Unmarshal(b, &inspectJSON)
|
|
|
+ assert.NilError(t, err)
|
|
|
+
|
|
|
+ cfg, ok := inspectJSON["HostConfig"].(map[string]interface{})
|
|
|
+ assert.Check(t, is.Equal(true, ok), name)
|
|
|
+
|
|
|
+ readonlyPaths, ok := cfg["ReadonlyPaths"].([]interface{})
|
|
|
+ assert.Check(t, is.Equal(true, ok), name)
|
|
|
+
|
|
|
+ rops := []string{}
|
|
|
+ for _, rop := range readonlyPaths {
|
|
|
+ rops = append(rops, rop.(string))
|
|
|
+ }
|
|
|
+ assert.DeepEqual(t, expected, rops)
|
|
|
+ }
|
|
|
+
|
|
|
+ for i, tc := range testCases {
|
|
|
+ name := fmt.Sprintf("create-readonly-paths-%d", i)
|
|
|
+ config := container.Config{
|
|
|
+ Image: "busybox",
|
|
|
+ Cmd: []string{"true"},
|
|
|
+ }
|
|
|
+ hc := container.HostConfig{}
|
|
|
+ if tc.readonlyPaths != nil {
|
|
|
+ hc.ReadonlyPaths = tc.readonlyPaths
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create the container.
|
|
|
+ c, err := client.ContainerCreate(context.Background(),
|
|
|
+ &config,
|
|
|
+ &hc,
|
|
|
+ &network.NetworkingConfig{},
|
|
|
+ name,
|
|
|
+ )
|
|
|
+ assert.NilError(t, err)
|
|
|
+
|
|
|
+ checkInspect(t, ctx, name, tc.expected)
|
|
|
+
|
|
|
+ // Start the container.
|
|
|
+ err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{})
|
|
|
+ assert.NilError(t, err)
|
|
|
+
|
|
|
+ poll.WaitOn(t, ctr.IsInState(ctx, client, c.ID, "exited"), poll.WithDelay(100*time.Millisecond))
|
|
|
+
|
|
|
+ checkInspect(t, ctx, name, tc.expected)
|
|
|
+ }
|
|
|
+}
|