Browse code

Add (hidden) flags to set containerd namespaces

This allows our tests, which all share a containerd instance, to be a
bit more isolated by setting the containerd namespaces to the generated
daemon ID's rather than the default namespaces.

This came about because I found in some cases we had test daemons
failing to start (really very slow to start) because it was (seemingly)
processing events from other tests.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>

Brian Goff authored on 2019/07/12 08:42:16
Showing 7 changed files
... ...
@@ -3,8 +3,10 @@ package main
3 3
 import (
4 4
 	"runtime"
5 5
 
6
+	"github.com/docker/docker/daemon"
6 7
 	"github.com/docker/docker/daemon/config"
7 8
 	"github.com/docker/docker/opts"
9
+	"github.com/docker/docker/plugin/executor/containerd"
8 10
 	"github.com/docker/docker/registry"
9 11
 	"github.com/spf13/pflag"
10 12
 )
... ...
@@ -85,7 +87,13 @@ func installCommonConfigFlags(conf *config.Config, flags *pflag.FlagSet) error {
85 85
 
86 86
 	conf.MaxConcurrentDownloads = &maxConcurrentDownloads
87 87
 	conf.MaxConcurrentUploads = &maxConcurrentUploads
88
-	return nil
88
+
89
+	flags.StringVar(&conf.ContainerdNamespace, "containerd-namespace", daemon.ContainersNamespace, "Containerd namespace to use")
90
+	if err := flags.MarkHidden("containerd-namespace"); err != nil {
91
+		return err
92
+	}
93
+	flags.StringVar(&conf.ContainerdPluginNamespace, "containerd-plugins-namespace", containerd.PluginNamespace, "Containerd namespace to use for plugins")
94
+	return flags.MarkHidden("containerd-plugins-namespace")
89 95
 }
90 96
 
91 97
 func installRegistryServiceFlags(options *registry.ServiceOptions, flags *pflag.FlagSet) {
... ...
@@ -230,6 +230,9 @@ type CommonConfig struct {
230 230
 	Features map[string]bool `json:"features,omitempty"`
231 231
 
232 232
 	Builder BuilderConfig `json:"builder,omitempty"`
233
+
234
+	ContainerdNamespace       string `json:"containerd-namespace,omitempty"`
235
+	ContainerdPluginNamespace string `json:"containerd-plugin-namespace,omitempty"`
233 236
 }
234 237
 
235 238
 // IsValueSet returns true if a configuration value
... ...
@@ -888,7 +888,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
888 888
 		grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize)),
889 889
 	}
890 890
 	if config.ContainerdAddr != "" {
891
-		d.containerdCli, err = containerd.New(config.ContainerdAddr, containerd.WithDefaultNamespace(ContainersNamespace), containerd.WithDialOpts(gopts), containerd.WithTimeout(60*time.Second))
891
+		d.containerdCli, err = containerd.New(config.ContainerdAddr, containerd.WithDefaultNamespace(config.ContainerdNamespace), containerd.WithDialOpts(gopts), containerd.WithTimeout(60*time.Second))
892 892
 		if err != nil {
893 893
 			return nil, errors.Wrapf(err, "failed to dial %q", config.ContainerdAddr)
894 894
 		}
... ...
@@ -900,13 +900,13 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
900 900
 		// Windows is not currently using containerd, keep the
901 901
 		// client as nil
902 902
 		if config.ContainerdAddr != "" {
903
-			pluginCli, err = containerd.New(config.ContainerdAddr, containerd.WithDefaultNamespace(pluginexec.PluginNamespace), containerd.WithDialOpts(gopts), containerd.WithTimeout(60*time.Second))
903
+			pluginCli, err = containerd.New(config.ContainerdAddr, containerd.WithDefaultNamespace(config.ContainerdPluginNamespace), containerd.WithDialOpts(gopts), containerd.WithTimeout(60*time.Second))
904 904
 			if err != nil {
905 905
 				return nil, errors.Wrapf(err, "failed to dial %q", config.ContainerdAddr)
906 906
 			}
907 907
 		}
908 908
 
909
-		return pluginexec.New(ctx, getPluginExecRoot(config.Root), pluginCli, m)
909
+		return pluginexec.New(ctx, getPluginExecRoot(config.Root), pluginCli, config.ContainerdPluginNamespace, m)
910 910
 	}
911 911
 
912 912
 	// Plugin system initialization should happen before restore. Do not change order.
... ...
@@ -1054,7 +1054,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
1054 1054
 
1055 1055
 	go d.execCommandGC()
1056 1056
 
1057
-	d.containerd, err = libcontainerd.NewClient(ctx, d.containerdCli, filepath.Join(config.ExecRoot, "containerd"), ContainersNamespace, d)
1057
+	d.containerd, err = libcontainerd.NewClient(ctx, d.containerdCli, filepath.Join(config.ExecRoot, "containerd"), config.ContainerdNamespace, d)
1058 1058
 	if err != nil {
1059 1059
 		return nil, err
1060 1060
 	}
... ...
@@ -757,6 +757,9 @@ func (daemon *Daemon) initRuntimes(runtimes map[string]types.Runtime) (err error
757 757
 
758 758
 // verifyDaemonSettings performs validation of daemon config struct
759 759
 func verifyDaemonSettings(conf *config.Config) error {
760
+	if conf.ContainerdNamespace == conf.ContainerdPluginNamespace {
761
+		return errors.New("containers namespace and plugins namespace cannot be the same")
762
+	}
760 763
 	// Check for mutually incompatible config options
761 764
 	if conf.BridgeConfig.Iface != "" && conf.BridgeConfig.IP != "" {
762 765
 		return fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one")
... ...
@@ -25,7 +25,6 @@ import (
25 25
 
26 26
 	"github.com/cloudflare/cfssl/helpers"
27 27
 	"github.com/docker/docker/api/types"
28
-	moby_daemon "github.com/docker/docker/daemon"
29 28
 	"github.com/docker/docker/integration-cli/checker"
30 29
 	"github.com/docker/docker/integration-cli/cli"
31 30
 	"github.com/docker/docker/integration-cli/cli/build"
... ...
@@ -1457,7 +1456,7 @@ func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonAndContainerKill(c *chec
1457 1457
 
1458 1458
 	// kill the container
1459 1459
 	icmd.RunCommand(ctrBinary, "--address", containerdSocket,
1460
-		"--namespace", moby_daemon.ContainersNamespace, "tasks", "kill", id).Assert(c, icmd.Success)
1460
+		"--namespace", d.ContainersNamespace(), "tasks", "kill", id).Assert(c, icmd.Success)
1461 1461
 
1462 1462
 	// restart daemon.
1463 1463
 	d.Restart(c)
... ...
@@ -1977,7 +1976,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithKilledRunningContainer(t *check
1977 1977
 
1978 1978
 	// kill the container
1979 1979
 	icmd.RunCommand(ctrBinary, "--address", containerdSocket,
1980
-		"--namespace", moby_daemon.ContainersNamespace, "tasks", "kill", cid).Assert(t, icmd.Success)
1980
+		"--namespace", s.d.ContainersNamespace(), "tasks", "kill", cid).Assert(t, icmd.Success)
1981 1981
 
1982 1982
 	// Give time to containerd to process the command if we don't
1983 1983
 	// the exit event might be received after we do the inspect
... ...
@@ -2080,7 +2079,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithUnpausedRunningContainer(t *che
2080 2080
 	result := icmd.RunCommand(
2081 2081
 		ctrBinary,
2082 2082
 		"--address", containerdSocket,
2083
-		"--namespace", moby_daemon.ContainersNamespace,
2083
+		"--namespace", s.d.ContainersNamespace(),
2084 2084
 		"tasks", "resume", cid)
2085 2085
 	result.Assert(t, icmd.Success)
2086 2086
 
... ...
@@ -137,6 +137,11 @@ func New(t testingT, ops ...func(*Daemon)) *Daemon {
137 137
 	return d
138 138
 }
139 139
 
140
+// ContainersNamespace returns the containerd namespace used for containers.
141
+func (d *Daemon) ContainersNamespace() string {
142
+	return d.id
143
+}
144
+
140 145
 // RootDir returns the root directory of the daemon.
141 146
 func (d *Daemon) RootDir() string {
142 147
 	return d.Root
... ...
@@ -226,12 +231,15 @@ func (d *Daemon) StartWithLogFile(out *os.File, providedArgs ...string) error {
226 226
 	if err != nil {
227 227
 		return errors.Wrapf(err, "[%s] could not find docker binary in $PATH", d.id)
228 228
 	}
229
+
229 230
 	args := append(d.GlobalFlags,
230 231
 		"--containerd", containerdSocket,
231 232
 		"--data-root", d.Root,
232 233
 		"--exec-root", d.execRoot,
233 234
 		"--pidfile", fmt.Sprintf("%s/docker.pid", d.Folder),
234 235
 		fmt.Sprintf("--userland-proxy=%t", d.userlandProxy),
236
+		"--containerd-namespace", d.id,
237
+		"--containerd-plugins-namespace", d.id+"p",
235 238
 	)
236 239
 	if d.defaultCgroupNamespaceMode != "" {
237 240
 		args = append(args, []string{"--default-cgroupns-mode", d.defaultCgroupNamespaceMode}...)
... ...
@@ -26,13 +26,13 @@ type ExitHandler interface {
26 26
 }
27 27
 
28 28
 // New creates a new containerd plugin executor
29
-func New(ctx context.Context, rootDir string, cli *containerd.Client, exitHandler ExitHandler) (*Executor, error) {
29
+func New(ctx context.Context, rootDir string, cli *containerd.Client, ns string, exitHandler ExitHandler) (*Executor, error) {
30 30
 	e := &Executor{
31 31
 		rootDir:     rootDir,
32 32
 		exitHandler: exitHandler,
33 33
 	}
34 34
 
35
-	client, err := libcontainerd.NewClient(ctx, cli, rootDir, PluginNamespace, e)
35
+	client, err := libcontainerd.NewClient(ctx, cli, rootDir, ns, e)
36 36
 	if err != nil {
37 37
 		return nil, errors.Wrap(err, "error creating containerd exec client")
38 38
 	}