package container // import "github.com/docker/docker/integration/container"

import (
	"context"
	"strings"
	"testing"
	"time"

	"github.com/docker/docker/client"
	"github.com/docker/docker/integration/internal/container"
	"github.com/docker/docker/integration/internal/requirement"
	"github.com/docker/docker/testutil/daemon"
	"gotest.tools/v3/assert"
	is "gotest.tools/v3/assert/cmp"
	"gotest.tools/v3/poll"
	"gotest.tools/v3/skip"
)

// Gets the value of the cgroup namespace for pid 1 of a container
func containerCgroupNamespace(ctx context.Context, t *testing.T, client *client.Client, cID string) string {
	res, err := container.Exec(ctx, client, cID, []string{"readlink", "/proc/1/ns/cgroup"})
	assert.NilError(t, err)
	assert.Assert(t, is.Len(res.Stderr(), 0))
	assert.Equal(t, 0, res.ExitCode)
	return strings.TrimSpace(res.Stdout())
}

// Bring up a daemon with the specified default cgroup namespace mode, and then create a container with the container options
func testRunWithCgroupNs(t *testing.T, daemonNsMode string, containerOpts ...func(*container.TestContainerConfig)) (string, string) {
	d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode(daemonNsMode))
	client := d.NewClientT(t)
	ctx := context.Background()

	d.StartWithBusybox(t)
	defer d.Stop(t)

	cID := container.Run(ctx, t, client, containerOpts...)
	poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))

	daemonCgroup := d.CgroupNamespace(t)
	containerCgroup := containerCgroupNamespace(ctx, t, client, cID)
	return containerCgroup, daemonCgroup
}

// Bring up a daemon with the specified default cgroup namespace mode. Create a container with the container options,
// expecting an error with the specified string
func testCreateFailureWithCgroupNs(t *testing.T, daemonNsMode string, errStr string, containerOpts ...func(*container.TestContainerConfig)) {
	d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode(daemonNsMode))
	client := d.NewClientT(t)
	ctx := context.Background()

	d.StartWithBusybox(t)
	defer d.Stop(t)
	container.CreateExpectingErr(ctx, t, client, errStr, containerOpts...)
}

func TestCgroupNamespacesRun(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
	skip.If(t, testEnv.IsRemoteDaemon())
	skip.If(t, !requirement.CgroupNamespacesEnabled())

	// When the daemon defaults to private cgroup namespaces, containers launched
	// should be in their own private cgroup namespace by default
	containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private")
	assert.Assert(t, daemonCgroup != containerCgroup)
}

func TestCgroupNamespacesRunPrivileged(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
	skip.If(t, testEnv.IsRemoteDaemon())
	skip.If(t, !requirement.CgroupNamespacesEnabled())
	skip.If(t, testEnv.DaemonInfo.CgroupVersion == "2", "on cgroup v2, privileged containers use private cgroupns")

	// When the daemon defaults to private cgroup namespaces, privileged containers
	// launched should not be inside their own cgroup namespaces
	containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private", container.WithPrivileged(true))
	assert.Assert(t, daemonCgroup == containerCgroup)
}

func TestCgroupNamespacesRunDaemonHostMode(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
	skip.If(t, testEnv.IsRemoteDaemon())
	skip.If(t, !requirement.CgroupNamespacesEnabled())

	// When the daemon defaults to host cgroup namespaces, containers
	// launched should not be inside their own cgroup namespaces
	containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "host")
	assert.Assert(t, daemonCgroup == containerCgroup)
}

func TestCgroupNamespacesRunHostMode(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
	skip.If(t, testEnv.IsRemoteDaemon())
	skip.If(t, !requirement.CgroupNamespacesEnabled())

	// When the daemon defaults to private cgroup namespaces, containers launched
	// with a cgroup ns mode of "host" should not be inside their own cgroup namespaces
	containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private", container.WithCgroupnsMode("host"))
	assert.Assert(t, daemonCgroup == containerCgroup)
}

func TestCgroupNamespacesRunPrivateMode(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
	skip.If(t, testEnv.IsRemoteDaemon())
	skip.If(t, !requirement.CgroupNamespacesEnabled())

	// When the daemon defaults to private cgroup namespaces, containers launched
	// with a cgroup ns mode of "private" should be inside their own cgroup namespaces
	containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private", container.WithCgroupnsMode("private"))
	assert.Assert(t, daemonCgroup != containerCgroup)
}

func TestCgroupNamespacesRunPrivilegedAndPrivate(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
	skip.If(t, testEnv.IsRemoteDaemon())
	skip.If(t, !requirement.CgroupNamespacesEnabled())

	containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private", container.WithPrivileged(true), container.WithCgroupnsMode("private"))
	assert.Assert(t, daemonCgroup != containerCgroup)
}

func TestCgroupNamespacesRunInvalidMode(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
	skip.If(t, testEnv.IsRemoteDaemon())
	skip.If(t, !requirement.CgroupNamespacesEnabled())

	// An invalid cgroup namespace mode should return an error on container creation
	errStr := "invalid cgroup namespace mode: invalid"
	testCreateFailureWithCgroupNs(t, "private", errStr, container.WithCgroupnsMode("invalid"))
}

// Clients before 1.40 expect containers to be created in the host cgroup namespace,
// regardless of the default setting of the daemon
func TestCgroupNamespacesRunOlderClient(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType != "linux")
	skip.If(t, testEnv.IsRemoteDaemon())
	skip.If(t, !requirement.CgroupNamespacesEnabled())

	d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode("private"))
	client := d.NewClientT(t, client.WithVersion("1.39"))

	ctx := context.Background()
	d.StartWithBusybox(t)
	defer d.Stop(t)

	cID := container.Run(ctx, t, client)
	poll.WaitOn(t, container.IsInState(ctx, client, cID, "running"), poll.WithDelay(100*time.Millisecond))

	daemonCgroup := d.CgroupNamespace(t)
	containerCgroup := containerCgroupNamespace(ctx, t, client, cID)
	assert.Assert(t, daemonCgroup == containerCgroup)
}
