Repository: containerd/containerd
File: core/runtime/v2/shim_manager.go (Go)

Code before:

// Start launches a new shim instance
func (m *ShimManager) Start(ctx context.Context, id string, bundle *Bundle, opts runtime.CreateOpts) (_ ShimInstance, retErr error) {
	// This container belongs to sandbox which supposed to be already started via sandbox API.
	if opts.SandboxID != "" {
		var params shimbinary.BootstrapParams
		if opts.Address != "" {
			// The address returned from sandbox controller should be in the form like ttrpc+unix://<uds-path>
			// or grpc+vsock://<cid>:<port>, we should get the protocol from the url first.
			protocol, address, ok := strings.Cut(opts.Address, "+")
			if !ok {
				return nil, fmt.Errorf("the scheme of sandbox address should be in " +
					" the form of <protocol>+<unix|vsock|tcp>, i.e. ttrpc+unix or grpc+vsock")
			}
			params = shimbinary.BootstrapParams{
				Version:  int(opts.Version),
				Protocol: protocol,
				Address:  address,
			}
		} else {
			// For those sandbox we can not get endpoint,
			// fallback to legacy implementation
			process, err := m.Get(ctx, opts.SandboxID)
			if err != nil {
				return nil, fmt.Errorf("can't find sandbox %s", opts.SandboxID)
			}
			p, err := restoreBootstrapParams(process.Bundle())
			if err != nil {
				return nil, fmt.Errorf("failed to get bootstrap "+
					"params of sandbox %s, legacy restore error %v", opts.SandboxID, err)
			}
			params = p
		}

		// Write sandbox ID this task belongs to.
		if err := os.WriteFile(filepath.Join(bundle.Path, "sandbox"), []byte(opts.SandboxID), 0600); err != nil {
			return nil, err
		}

		if err := writeBootstrapParams(filepath.Join(bundle.Path, "bootstrap.json"), params); err != nil {
			return nil, fmt.Errorf("failed to write bootstrap.json for bundle %s: %w", bundle.Path, err)
		}

		shim, err := loadShim(ctx, bundle, func() {})
		if err != nil {
			return nil, fmt.Errorf("failed to load sandbox task %q: %w", opts.SandboxID, err)
		}

		if err := m.shims.Add(ctx, shim); err != nil {
			return nil, err
		}

Review comment (suggestion):
not blocking, but I think we should separate the scheme first before getting the protocol.  Otherwise we might mis-parse something like "unix://<path with + embedded>".

Code after:
}

// Start launches a new shim instance
func (m *ShimManager) Start(ctx context.Context, id string, bundle *Bundle, opts runtime.CreateOpts) (_ ShimInstance, retErr error) {
	shouldInvokeShimBinary := false

	var params shimbinary.BootstrapParams
	if opts.SandboxID != "" {
		_, sbErr := m.sandboxStore.Get(ctx, opts.SandboxID)
		if sbErr != nil {
			if !errors.Is(sbErr, errdefs.ErrNotFound) {
				return nil, sbErr
			}

			log.G(ctx).WithField("id", id).Warningf("sandbox (id=%s) not found, maybe created from v1.x", opts.SandboxID)
			// NOTE: If sandbox container, like pause, is created by
			// v1.6.x or v1.7.x, the shim may be not able to group
			// multiple containers. We should invoke shim binary and
			// establish new connection based on returned address.
			shouldInvokeShimBinary = true
		} else {
			if opts.Address != "" {
				// The address returned from sandbox controller should
				// be in the form like ttrpc+unix://<uds-path> or grpc+vsock://<cid>:<port>,
				// we should get the protocol from the url first.
				protocol, address, ok := strings.Cut(opts.Address, "+")
				if !ok {
					return nil, fmt.Errorf("the scheme of sandbox address should be in " +
						" the form of <protocol>+<unix|vsock|tcp>, i.e. ttrpc+unix or grpc+vsock")
				}
				params = shimbinary.BootstrapParams{
					Version:  int(opts.Version),
					Protocol: protocol,
					Address:  address,
				}
			} else {
				process, err := m.Get(ctx, opts.SandboxID)
				if err != nil {
					return nil, fmt.Errorf("can't find shim for sandbox %s: %w", opts.SandboxID, err)
				}

				p, err := restoreBootstrapParams(process.Bundle())
				if err != nil {
					return nil, fmt.Errorf("failed to get bootstrap "+
						"params of sandbox %s: %w", opts.SandboxID, err)
				}
				params = p
			}
		}
	}
	// Even though one shim can be able to group multiple containers,