diff --git a/client.go b/client.go index eefeb4e94..60552e91a 100644 --- a/client.go +++ b/client.go @@ -138,6 +138,22 @@ func New(address string, opts ...ClientOpt) (*Client, error) { if copts.services == nil && c.conn == nil { return nil, errors.New("no grpc connection or services is available") } + + // check namespace labels for default runtime + defaultns := "default" + if copts.defaultns != "" { + defaultns = copts.defaultns + } + namespaces := c.NamespaceService() + ctx := context.Background() + if labels, err := namespaces.Labels(ctx, defaultns); err == nil { + if defaultRuntime, ok := labels["runtime"]; ok { + c.runtime = defaultRuntime + } + } else { + return nil, err + } + return c, nil } diff --git a/client_test.go b/client_test.go index 83081a6c9..2ed367b85 100644 --- a/client_test.go +++ b/client_test.go @@ -393,3 +393,28 @@ func createShimDebugConfig() string { return f.Name() } + +func TestDefaultRuntimeWithNamespaceLabels(t *testing.T) { + client, err := newClient(t, address) + if err != nil { + t.Fatal(err) + } + defer client.Close() + + ctx, cancel := testContext() + defer cancel() + namespaces := client.NamespaceService() + testRuntime := "testRuntime" + if err := namespaces.SetLabel(ctx, testNamespace, "runtime", testRuntime); err != nil { + t.Fatal(err) + } + + testClient, err := newClient(t, address, WithDefaultNamespace(testNamespace)) + if err != nil { + t.Fatal(err) + } + defer testClient.Close() + if testClient.runtime != testRuntime { + t.Error("failed to set default runtime from namespace labels") + } +} diff --git a/container_opts.go b/container_opts.go index ca4bf6748..8f086a729 100644 --- a/container_opts.go +++ b/container_opts.go @@ -21,6 +21,7 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/platforms" "github.com/containerd/typeurl" @@ -106,7 +107,7 @@ func WithSnapshotter(name string) NewContainerOpts { // WithSnapshot uses an existing root filesystem for the container func WithSnapshot(id string) NewContainerOpts { return func(ctx context.Context, client *Client, c *containers.Container) error { - setSnapshotterIfEmpty(c) + setSnapshotterIfEmpty(ctx, client, c) // check that the snapshot exists, if not, fail on creation if _, err := client.SnapshotService(c.Snapshotter).Mounts(ctx, id); err != nil { return err @@ -124,7 +125,7 @@ func WithNewSnapshot(id string, i Image) NewContainerOpts { if err != nil { return err } - setSnapshotterIfEmpty(c) + setSnapshotterIfEmpty(ctx, client, c) parent := identity.ChainID(diffIDs).String() if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, id, parent); err != nil { return err @@ -154,7 +155,7 @@ func WithNewSnapshotView(id string, i Image) NewContainerOpts { if err != nil { return err } - setSnapshotterIfEmpty(c) + setSnapshotterIfEmpty(ctx, client, c) parent := identity.ChainID(diffIDs).String() if _, err := client.SnapshotService(c.Snapshotter).View(ctx, id, parent); err != nil { return err @@ -165,9 +166,18 @@ func WithNewSnapshotView(id string, i Image) NewContainerOpts { } } -func setSnapshotterIfEmpty(c *containers.Container) { +func setSnapshotterIfEmpty(ctx context.Context, client *Client, c *containers.Container) { if c.Snapshotter == "" { - c.Snapshotter = DefaultSnapshotter + defaultSnapshotter := DefaultSnapshotter + namespaceService := client.NamespaceService() + if ns, err := namespaces.NamespaceRequired(ctx); err == nil { + if labels, err := namespaceService.Labels(ctx, ns); err == nil { + if snapshotLabel, ok := labels["snapshotter"]; ok { + defaultSnapshotter = snapshotLabel + } + } + } + c.Snapshotter = defaultSnapshotter } } diff --git a/container_opts_unix.go b/container_opts_unix.go index 9e013f1a4..340a91857 100644 --- a/container_opts_unix.go +++ b/container_opts_unix.go @@ -50,7 +50,7 @@ func withRemappedSnapshotBase(id string, i Image, uid, gid uint32, readonly bool return err } - setSnapshotterIfEmpty(c) + setSnapshotterIfEmpty(ctx, client, c) var ( snapshotter = client.SnapshotService(c.Snapshotter)