diff --git a/client/client.go b/client/client.go index 3e716a3d4e..9d17e31a61 100644 --- a/client/client.go +++ b/client/client.go @@ -117,7 +117,11 @@ func New(address string, opts ...Opt) (*Client, error) { } if copts.defaultRuntime != "" { - c.runtime.value = copts.defaultRuntime + c.defaults.runtime = copts.defaultRuntime + } + + if copts.defaultSandboxer != "" { + c.defaults.sandboxer = copts.defaultSandboxer } if copts.defaultPlatform != nil { @@ -193,7 +197,11 @@ func NewWithConn(conn *grpc.ClientConn, opts ...Opt) (*Client, error) { } if copts.defaultRuntime != "" { - c.runtime.value = copts.defaultRuntime + c.defaults.runtime = copts.defaultRuntime + } + + if copts.defaultSandboxer != "" { + c.defaults.sandboxer = copts.defaultSandboxer } if copts.defaultPlatform != nil { @@ -218,10 +226,11 @@ type Client struct { platform platforms.MatchComparer connector func() (*grpc.ClientConn, error) - // this should only be accessed via defaultRuntime() - runtime struct { - value string - mut sync.Mutex + // this should only be accessed via default*() functions + defaults struct { + runtime string + sandboxer string + mut sync.Mutex } } @@ -248,11 +257,11 @@ func (c *Client) Runtime() string { } func (c *Client) defaultRuntime(ctx context.Context) (string, error) { - c.runtime.mut.Lock() - defer c.runtime.mut.Unlock() + c.defaults.mut.Lock() + defer c.defaults.mut.Unlock() - if c.runtime.value != "" { - return c.runtime.value, nil + if c.defaults.runtime != "" { + return c.defaults.runtime, nil } if c.defaultns != "" { @@ -262,12 +271,35 @@ func (c *Client) defaultRuntime(ctx context.Context) (string, error) { return defaults.DefaultRuntime, fmt.Errorf("failed to get default runtime label: %w", err) } if label != "" { - c.runtime.value = label + c.defaults.runtime = label return label, nil } } - c.runtime.value = defaults.DefaultRuntime - return c.runtime.value, nil + c.defaults.runtime = defaults.DefaultRuntime + return c.defaults.runtime, nil +} + +func (c *Client) defaultSandboxer(ctx context.Context) (string, error) { + c.defaults.mut.Lock() + defer c.defaults.mut.Unlock() + + if c.defaults.sandboxer != "" { + return c.defaults.sandboxer, nil + } + + if c.defaultns != "" { + label, err := c.GetLabel(ctx, defaults.DefaultSandboxerNSLabel) + if err != nil { + // Don't set the sandboxer value if there's an error + return defaults.DefaultSandboxer, fmt.Errorf("failed to get default sandboxer label: %w", err) + } + if label != "" { + c.defaults.sandboxer = label + return label, nil + } + } + c.defaults.sandboxer = defaults.DefaultSandboxer + return c.defaults.sandboxer, nil } // IsServing returns true if the client can successfully connect to the diff --git a/client/client_opts.go b/client/client_opts.go index 48f3ff2a26..a96e55e75b 100644 --- a/client/client_opts.go +++ b/client/client_opts.go @@ -30,14 +30,15 @@ import ( ) type clientOpts struct { - defaultns string - defaultRuntime string - defaultPlatform platforms.MatchComparer - services *services - dialOptions []grpc.DialOption - extraDialOpts []grpc.DialOption - callOptions []grpc.CallOption - timeout time.Duration + defaultns string + defaultRuntime string + defaultSandboxer string + defaultPlatform platforms.MatchComparer + services *services + dialOptions []grpc.DialOption + extraDialOpts []grpc.DialOption + callOptions []grpc.CallOption + timeout time.Duration } // Opt allows callers to set options on the containerd client @@ -62,6 +63,14 @@ func WithDefaultRuntime(rt string) Opt { } } +// WithDefaultSandboxer sets the default sandboxer on the client +func WithDefaultSandboxer(sb string) Opt { + return func(c *clientOpts) error { + c.defaultSandboxer = sb + return nil + } +} + // WithDefaultPlatform sets the default platform matcher on the client func WithDefaultPlatform(platform platforms.MatchComparer) Opt { return func(c *clientOpts) error { diff --git a/client/sandbox.go b/client/sandbox.go index 335debe226..75a51a8791 100644 --- a/client/sandbox.go +++ b/client/sandbox.go @@ -114,7 +114,7 @@ func (s *sandboxClient) Stop(ctx context.Context) error { } func (s *sandboxClient) Shutdown(ctx context.Context) error { - if err := s.client.SandboxController(s.metadata.Sandboxer).Shutdown(ctx, s.ID()); err != nil && errdefs.IsNotFound(err) { + if err := s.client.SandboxController(s.metadata.Sandboxer).Shutdown(ctx, s.ID()); err != nil && !errdefs.IsNotFound(err) { return fmt.Errorf("failed to shutdown sandbox: %w", err) } @@ -131,10 +131,15 @@ func (c *Client) NewSandbox(ctx context.Context, sandboxID string, opts ...NewSa return nil, errors.New("sandbox ID must be specified") } + sandboxer, err := c.defaultSandboxer(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get default sandboxer: %w", err) + } newSandbox := api.Sandbox{ ID: sandboxID, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC(), + Sandboxer: sandboxer, } for _, opt := range opts { @@ -148,6 +153,10 @@ func (c *Client) NewSandbox(ctx context.Context, sandboxID string, opts ...NewSa return nil, err } + if err := c.SandboxController(sandboxer).Create(ctx, newSandbox); err != nil { + return nil, fmt.Errorf("failed to create sandbox with %s sandboxer: %w", sandboxer, err) + } + return &sandboxClient{ client: c, metadata: metadata, diff --git a/defaults/defaults.go b/defaults/defaults.go index 6f5b122ecf..fcf3ec60cd 100644 --- a/defaults/defaults.go +++ b/defaults/defaults.go @@ -29,4 +29,9 @@ const ( // DefaultSnapshotterNSLabel defines the namespace label to check for the // default snapshotter DefaultSnapshotterNSLabel = "containerd.io/defaults/snapshotter" + // DefaultSandboxerNSLabel defines the namespace label to check for the + // default sandboxcr + DefaultSandboxerNSLabel = "containerd.io/defaults/sandboxer" + // DefaultSandboxer defines the default sandboxer to use for creating sandboxes. + DefaultSandboxer = "shim" ) diff --git a/plugins/services/sandbox/controller_service.go b/plugins/services/sandbox/controller_service.go index 21d1c05444..7b80814996 100644 --- a/plugins/services/sandbox/controller_service.go +++ b/plugins/services/sandbox/controller_service.go @@ -103,7 +103,13 @@ func (s *controllerService) getController(name string) (sandbox.Controller, erro } func (s *controllerService) Create(ctx context.Context, req *api.ControllerCreateRequest) (*api.ControllerCreateResponse, error) { - log.G(ctx).WithField("req", req).Debug("create sandbox") + ctx = log.WithLogger(ctx, log.G(ctx).WithFields(log.Fields{ + "sandbox_id": req.GetSandboxID(), + "sandboxer": req.GetSandboxer(), + })) + + log.G(ctx).Debug("create sandbox") + // TODO: Rootfs ctrl, err := s.getController(req.Sandboxer) if err != nil { @@ -132,14 +138,19 @@ func (s *controllerService) Create(ctx context.Context, req *api.ControllerCreat } func (s *controllerService) Start(ctx context.Context, req *api.ControllerStartRequest) (*api.ControllerStartResponse, error) { - log.G(ctx).WithField("req", req).Debug("start sandbox") + ctx = log.WithLogger(ctx, log.G(ctx).WithFields(log.Fields{ + "sandbox_id": req.GetSandboxID(), + "sandboxer": req.GetSandboxer(), + })) + + log.G(ctx).Debug("start sandbox") ctrl, err := s.getController(req.Sandboxer) if err != nil { - return nil, errgrpc.ToGRPC(err) + return nil, errgrpc.ToGRPCf(err, "failed to get sandbox controller for %q", req.Sandboxer) } inst, err := ctrl.Start(ctx, req.GetSandboxID()) if err != nil { - return &api.ControllerStartResponse{}, errgrpc.ToGRPC(err) + return &api.ControllerStartResponse{}, errgrpc.ToGRPCf(err, "failed to start sandbox %q", req.GetSandboxID()) } if err := s.publisher.Publish(ctx, "sandboxes/start", &eventtypes.SandboxStart{