github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/integration/build/build_cgroupns_linux_test.go (about)

     1  package build // import "github.com/demonoid81/moby/integration/build"
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"io"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/demonoid81/moby/api/types"
    11  	"github.com/demonoid81/moby/integration/internal/requirement"
    12  	"github.com/demonoid81/moby/pkg/jsonmessage"
    13  	"github.com/demonoid81/moby/testutil/daemon"
    14  	"github.com/demonoid81/moby/testutil/fakecontext"
    15  	"gotest.tools/v3/assert"
    16  	"gotest.tools/v3/skip"
    17  )
    18  
    19  // Finds the output of `readlink /proc/<pid>/ns/cgroup` in build output
    20  func getCgroupFromBuildOutput(buildOutput io.Reader) (string, error) {
    21  	const prefix = "cgroup:"
    22  
    23  	dec := json.NewDecoder(buildOutput)
    24  	for {
    25  		m := jsonmessage.JSONMessage{}
    26  		err := dec.Decode(&m)
    27  		if err == io.EOF {
    28  			return "", nil
    29  		}
    30  		if err != nil {
    31  			return "", err
    32  		}
    33  		if ix := strings.Index(m.Stream, prefix); ix == 0 {
    34  			return strings.TrimSpace(m.Stream), nil
    35  		}
    36  	}
    37  }
    38  
    39  // Runs a docker build against a daemon with the given cgroup namespace default value.
    40  // Returns the container cgroup and daemon cgroup.
    41  func testBuildWithCgroupNs(t *testing.T, daemonNsMode string) (string, string) {
    42  	d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode(daemonNsMode))
    43  	d.StartWithBusybox(t)
    44  	defer d.Stop(t)
    45  
    46  	dockerfile := `
    47  		FROM busybox
    48  		RUN readlink /proc/self/ns/cgroup
    49  	`
    50  	ctx := context.Background()
    51  	source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile))
    52  	defer source.Close()
    53  
    54  	client := d.NewClientT(t)
    55  	resp, err := client.ImageBuild(ctx,
    56  		source.AsTarReader(t),
    57  		types.ImageBuildOptions{
    58  			Remove:      true,
    59  			ForceRemove: true,
    60  			Tags:        []string{"buildcgroupns"},
    61  		})
    62  	assert.NilError(t, err)
    63  	defer resp.Body.Close()
    64  
    65  	containerCgroup, err := getCgroupFromBuildOutput(resp.Body)
    66  	assert.NilError(t, err)
    67  	daemonCgroup := d.CgroupNamespace(t)
    68  
    69  	return containerCgroup, daemonCgroup
    70  }
    71  
    72  func TestCgroupNamespacesBuild(t *testing.T) {
    73  	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
    74  	skip.If(t, testEnv.IsRemoteDaemon())
    75  	skip.If(t, !requirement.CgroupNamespacesEnabled())
    76  
    77  	// When the daemon defaults to private cgroup namespaces, containers launched
    78  	// should be in their own private cgroup namespace by default
    79  	containerCgroup, daemonCgroup := testBuildWithCgroupNs(t, "private")
    80  	assert.Assert(t, daemonCgroup != containerCgroup)
    81  }
    82  
    83  func TestCgroupNamespacesBuildDaemonHostMode(t *testing.T) {
    84  	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
    85  	skip.If(t, testEnv.IsRemoteDaemon())
    86  	skip.If(t, !requirement.CgroupNamespacesEnabled())
    87  
    88  	// When the daemon defaults to host cgroup namespaces, containers
    89  	// launched should not be inside their own cgroup namespaces
    90  	containerCgroup, daemonCgroup := testBuildWithCgroupNs(t, "host")
    91  	assert.Assert(t, daemonCgroup == containerCgroup)
    92  }