From 243cab594ee6d5edab591a43e399786ff07faab8 Mon Sep 17 00:00:00 2001 From: Derek McGowan Date: Wed, 18 Mar 2026 23:32:33 -0700 Subject: [PATCH] Deprecate old pkg/shim interfaces Signed-off-by: Derek McGowan --- cmd/containerd-shim-runc-v2/main.go | 2 +- .../manager/manager_linux.go | 7 +- core/runtime/v2/example/cmd/main.go | 2 +- core/runtime/v2/example/example.go | 5 +- core/runtime/v2/shim.go | 11 +- core/runtime/v2/shim_manager.go | 9 +- core/runtime/v2/shim_test.go | 16 +-- .../containerd-shim-runc-fp-v1/main_linux.go | 2 +- pkg/shim/compat.go | 3 +- pkg/shim/deprecated.go | 113 ++++++++++++++++++ pkg/shim/shim.go | 25 ++-- 11 files changed, 156 insertions(+), 39 deletions(-) create mode 100644 pkg/shim/deprecated.go diff --git a/cmd/containerd-shim-runc-v2/main.go b/cmd/containerd-shim-runc-v2/main.go index d6f11990c2..4cc0879ccb 100644 --- a/cmd/containerd-shim-runc-v2/main.go +++ b/cmd/containerd-shim-runc-v2/main.go @@ -27,5 +27,5 @@ import ( ) func main() { - shim.Run(context.Background(), manager.NewShimManager("io.containerd.runc.v2")) + shim.RunShim(context.Background(), manager.NewShimManager("io.containerd.runc.v2")) } diff --git a/cmd/containerd-shim-runc-v2/manager/manager_linux.go b/cmd/containerd-shim-runc-v2/manager/manager_linux.go index 0270b9499a..c95fd2c5fd 100644 --- a/cmd/containerd-shim-runc-v2/manager/manager_linux.go +++ b/cmd/containerd-shim-runc-v2/manager/manager_linux.go @@ -34,6 +34,7 @@ import ( "github.com/containerd/cgroups/v3" "github.com/containerd/cgroups/v3/cgroup1" cgroupsv2 "github.com/containerd/cgroups/v3/cgroup2" + bootapi "github.com/containerd/containerd/api/runtime/bootstrap/v1" "github.com/containerd/containerd/api/types" "github.com/containerd/containerd/api/types/runc/options" "github.com/containerd/containerd/v2/cmd/containerd-shim-runc-v2/process" @@ -54,7 +55,7 @@ import ( // NewShimManager returns an implementation of the shim manager // using runc -func NewShimManager(name string) shim.Manager { +func NewShimManager(name string) shim.Shim { return &manager{ name: name, } @@ -182,8 +183,8 @@ func newShimSocket(ctx context.Context, path, id string, debug bool) (*shimSocke return s, nil } -func (manager) Start(ctx context.Context, opts *shim.BootstrapParams) (_ *shim.BootstrapResult, retErr error) { - var params shim.BootstrapResult +func (manager) Start(ctx context.Context, opts *bootapi.BootstrapParams) (_ *bootapi.BootstrapResult, retErr error) { + var params bootapi.BootstrapResult params.Version = 3 params.Protocol = "ttrpc" diff --git a/core/runtime/v2/example/cmd/main.go b/core/runtime/v2/example/cmd/main.go index 2e99793c84..9e36126f49 100644 --- a/core/runtime/v2/example/cmd/main.go +++ b/core/runtime/v2/example/cmd/main.go @@ -25,5 +25,5 @@ import ( func main() { // init and execute the shim - shim.Run(context.Background(), example.NewManager("io.containerd.example.v1")) + shim.RunShim(context.Background(), example.NewManager("io.containerd.example.v1")) } diff --git a/core/runtime/v2/example/example.go b/core/runtime/v2/example/example.go index 2745852ed6..5c428376d9 100644 --- a/core/runtime/v2/example/example.go +++ b/core/runtime/v2/example/example.go @@ -21,6 +21,7 @@ import ( "io" "os" + bootapi "github.com/containerd/containerd/api/runtime/bootstrap/v1" taskAPI "github.com/containerd/containerd/api/runtime/task/v2" apitypes "github.com/containerd/containerd/api/types" ptypes "github.com/containerd/containerd/v2/pkg/protobuf/types" @@ -55,7 +56,7 @@ func init() { }) } -func NewManager(name string) shim.Manager { +func NewManager(name string) shim.Shim { return manager{name: name} } @@ -67,7 +68,7 @@ func (m manager) Name() string { return m.name } -func (m manager) Start(ctx context.Context, opts *shim.BootstrapParams) (*shim.BootstrapResult, error) { +func (m manager) Start(ctx context.Context, opts *bootapi.BootstrapParams) (*bootapi.BootstrapResult, error) { return nil, errdefs.ErrNotImplemented } diff --git a/core/runtime/v2/shim.go b/core/runtime/v2/shim.go index f80177ebd4..92dff55bd1 100644 --- a/core/runtime/v2/shim.go +++ b/core/runtime/v2/shim.go @@ -35,6 +35,7 @@ import ( crmetadata "github.com/checkpoint-restore/checkpointctl/lib" eventstypes "github.com/containerd/containerd/api/events" + bootapi "github.com/containerd/containerd/api/runtime/bootstrap/v1" task "github.com/containerd/containerd/api/runtime/task/v3" "github.com/containerd/containerd/api/types" "github.com/containerd/errdefs" @@ -219,8 +220,8 @@ type clientVersionDowngrader interface { Downgrade() error } -func parseStartResponse(response []byte) (*client.BootstrapResult, error) { - var params client.BootstrapResult +func parseStartResponse(response []byte) (*bootapi.BootstrapResult, error) { + var params bootapi.BootstrapResult if err := json.Unmarshal(response, ¶ms); err != nil || params.Version < 2 { // Use TTRPC for legacy shims @@ -237,7 +238,7 @@ func parseStartResponse(response []byte) (*client.BootstrapResult, error) { } // writeBootstrapParams writes shim's bootstrap configuration (e.g. how to connect, version, etc). -func writeBootstrapParams(path string, params *client.BootstrapResult) error { +func writeBootstrapParams(path string, params *bootapi.BootstrapResult) error { path, err := filepath.Abs(path) if err != nil { return err @@ -262,7 +263,7 @@ func writeBootstrapParams(path string, params *client.BootstrapResult) error { return f.Close() } -func readBootstrapParams(path string) (*client.BootstrapResult, error) { +func readBootstrapParams(path string) (*bootapi.BootstrapResult, error) { path, err := filepath.Abs(path) if err != nil { return nil, err @@ -278,7 +279,7 @@ func readBootstrapParams(path string) (*client.BootstrapResult, error) { // makeConnection creates a new TTRPC or GRPC connection object from address. // address can be either a socket path for TTRPC or JSON serialized BootstrapParams. -func makeConnection(ctx context.Context, id string, params *client.BootstrapResult, onClose func()) (_ io.Closer, retErr error) { +func makeConnection(ctx context.Context, id string, params *bootapi.BootstrapResult, onClose func()) (_ io.Closer, retErr error) { log.G(ctx).WithFields(log.Fields{ "address": params.Address, "protocol": params.Protocol, diff --git a/core/runtime/v2/shim_manager.go b/core/runtime/v2/shim_manager.go index 4aae8bce9f..b74b9ed755 100644 --- a/core/runtime/v2/shim_manager.go +++ b/core/runtime/v2/shim_manager.go @@ -33,6 +33,7 @@ import ( "github.com/containerd/plugin/registry" "github.com/containerd/typeurl/v2" + bootapi "github.com/containerd/containerd/api/runtime/bootstrap/v1" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/core/events/exchange" "github.com/containerd/containerd/v2/core/metadata" @@ -169,7 +170,7 @@ func (m *ShimManager) ID() string { func (m *ShimManager) Start(ctx context.Context, id string, bundle *Bundle, opts runtime.CreateOpts) (_ ShimInstance, retErr error) { shouldInvokeShimBinary := false - var params = &shimbinary.BootstrapResult{} + var params = &bootapi.BootstrapResult{} if opts.SandboxID != "" { _, sbErr := m.sandboxStore.Get(ctx, opts.SandboxID) if sbErr != nil { @@ -193,7 +194,7 @@ func (m *ShimManager) Start(ctx context.Context, id string, bundle *Bundle, opts return nil, fmt.Errorf("the scheme of sandbox address should be in " + " the form of +, i.e. ttrpc+unix or grpc+vsock") } - params = &shimbinary.BootstrapResult{ + params = &bootapi.BootstrapResult{ Version: int32(opts.Version), Protocol: protocol, Address: address, @@ -310,7 +311,7 @@ func (m *ShimManager) startShim(ctx context.Context, bundle *Bundle, id string, // restoreBootstrapParams reads bootstrap.json to restore shim configuration. // If its an old shim, this will perform migration - read address file and write default bootstrap // configuration (version = 2, protocol = ttrpc, and address). -func restoreBootstrapParams(bundlePath string) (*shimbinary.BootstrapResult, error) { +func restoreBootstrapParams(bundlePath string) (*bootapi.BootstrapResult, error) { filePath := filepath.Join(bundlePath, "bootstrap.json") // Read bootstrap.json if exists @@ -327,7 +328,7 @@ func restoreBootstrapParams(bundlePath string) (*shimbinary.BootstrapResult, err return nil, fmt.Errorf("unable to migrate shim: failed to get socket address for bundle %s: %w", bundlePath, err) } - params := shimbinary.BootstrapResult{ + params := bootapi.BootstrapResult{ Version: 2, Address: address, Protocol: "ttrpc", diff --git a/core/runtime/v2/shim_test.go b/core/runtime/v2/shim_test.go index 063fb318a3..82f383109f 100644 --- a/core/runtime/v2/shim_test.go +++ b/core/runtime/v2/shim_test.go @@ -22,7 +22,7 @@ import ( "path/filepath" "testing" - client "github.com/containerd/containerd/v2/pkg/shim" + bootapi "github.com/containerd/containerd/api/runtime/bootstrap/v1" "github.com/containerd/errdefs" "github.com/stretchr/testify/require" ) @@ -31,13 +31,13 @@ func TestParseStartResponse(t *testing.T) { for _, tc := range []struct { Name string Response string - Expected client.BootstrapResult + Expected bootapi.BootstrapResult Err error }{ { Name: "v2 shim", Response: "/somedirectory/somesocket", - Expected: client.BootstrapResult{ + Expected: bootapi.BootstrapResult{ Version: 2, Address: "/somedirectory/somesocket", Protocol: "ttrpc", @@ -46,7 +46,7 @@ func TestParseStartResponse(t *testing.T) { { Name: "v2 shim using grpc", Response: `{"version":2,"address":"/somedirectory/somesocket","protocol":"grpc"}`, - Expected: client.BootstrapResult{ + Expected: bootapi.BootstrapResult{ Version: 2, Address: "/somedirectory/somesocket", Protocol: "grpc", @@ -55,7 +55,7 @@ func TestParseStartResponse(t *testing.T) { { Name: "v2 shim using ttrpc", Response: `{"version":2,"address":"/somedirectory/somesocket","protocol":"ttrpc"}`, - Expected: client.BootstrapResult{ + Expected: bootapi.BootstrapResult{ Version: 2, Address: "/somedirectory/somesocket", Protocol: "ttrpc", @@ -64,7 +64,7 @@ func TestParseStartResponse(t *testing.T) { { Name: "invalid shim v2 response", Response: `{"address":"/somedirectory/somesocket","protocol":"ttrpc"}`, - Expected: client.BootstrapResult{ + Expected: bootapi.BootstrapResult{ Version: 2, Address: `{"address":"/somedirectory/somesocket","protocol":"ttrpc"}`, Protocol: "ttrpc", @@ -73,7 +73,7 @@ func TestParseStartResponse(t *testing.T) { { Name: "later unsupported shim", Response: `{"Version": 4,"Address":"/somedirectory/somesocket","Protocol":"ttrpc"}`, - Expected: client.BootstrapResult{}, + Expected: bootapi.BootstrapResult{}, Err: errdefs.ErrNotImplemented, }, } { @@ -109,7 +109,7 @@ func TestRestoreBootstrapParams(t *testing.T) { restored, err := restoreBootstrapParams(bundlePath) require.NoError(t, err) - expected := &client.BootstrapResult{ + expected := &bootapi.BootstrapResult{ Version: 2, Address: "unix://123", Protocol: "ttrpc", diff --git a/integration/failpoint/cmd/containerd-shim-runc-fp-v1/main_linux.go b/integration/failpoint/cmd/containerd-shim-runc-fp-v1/main_linux.go index da5f4e7562..a0940ff87e 100644 --- a/integration/failpoint/cmd/containerd-shim-runc-fp-v1/main_linux.go +++ b/integration/failpoint/cmd/containerd-shim-runc-fp-v1/main_linux.go @@ -24,5 +24,5 @@ import ( ) func main() { - shim.Run(context.Background(), manager.NewShimManager("io.containerd.runc-fp.v1")) + shim.RunShim(context.Background(), manager.NewShimManager("io.containerd.runc-fp.v1")) } diff --git a/pkg/shim/compat.go b/pkg/shim/compat.go index fa57c4839f..3617d00b02 100644 --- a/pkg/shim/compat.go +++ b/pkg/shim/compat.go @@ -26,11 +26,12 @@ import ( "fmt" "os" + bootapi "github.com/containerd/containerd/api/runtime/bootstrap/v1" "github.com/containerd/containerd/api/types/runc/options" "github.com/containerd/log" ) -func readBootstrapParamsFromDeprecatedFields(input []byte, params *BootstrapParams) error { +func readBootstrapParamsFromDeprecatedFields(input []byte, params *bootapi.BootstrapParams) error { params.InstanceID = id params.Namespace = namespaceFlag params.ContainerdTtrpcAddress = os.Getenv(ttrpcAddressEnv) diff --git a/pkg/shim/deprecated.go b/pkg/shim/deprecated.go new file mode 100644 index 0000000000..0596d2e043 --- /dev/null +++ b/pkg/shim/deprecated.go @@ -0,0 +1,113 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package shim + +import ( + "context" + "fmt" + "io" + "os" + + bootapi "github.com/containerd/containerd/api/runtime/bootstrap/v1" + "github.com/containerd/containerd/api/types" + "github.com/containerd/log" +) + +// StartOpts describes shim start configuration received from containerd. +// +// Deprecated: Use [bootapi.BootstrapParams] instead. +type StartOpts struct { + Address string + TTRPCAddress string + Debug bool +} + +// BootstrapParams is a JSON payload returned in stdout from shim.Start call. +// +// Deprecated: Use [bootapi.BootstrapResult] instead. +type BootstrapParams struct { + // Version is the version of shim parameters (expected 2 for shim v2) + Version int `json:"version"` + // Address is a address containerd should use to connect to shim. + Address string `json:"address"` + // Protocol is either TTRPC or GRPC. + Protocol string `json:"protocol"` +} + +// Manager is the interface which manages the shim process. +// +// Deprecated: Use [Shim] instead. +type Manager interface { + Name() string + Start(ctx context.Context, id string, opts StartOpts) (BootstrapParams, error) + Stop(ctx context.Context, id string) (StopStatus, error) + Info(ctx context.Context, optionsR io.Reader) (*types.RuntimeInfo, error) +} + +// managerShim wraps a deprecated Manager to implement the Shim interface. +type managerShim struct { + manager Manager +} + +func (m *managerShim) Name() string { + return m.manager.Name() +} + +func (m *managerShim) Start(ctx context.Context, params *bootapi.BootstrapParams) (*bootapi.BootstrapResult, error) { + opts := StartOpts{ + Address: params.ContainerdGrpcAddress, + TTRPCAddress: params.ContainerdTtrpcAddress, + Debug: params.LogLevel == "debug" || params.LogLevel == "trace", + } + + bp, err := m.manager.Start(ctx, params.InstanceID, opts) + if err != nil { + return nil, err + } + + return &bootapi.BootstrapResult{ + Version: int32(bp.Version), + Address: bp.Address, + Protocol: bp.Protocol, + }, nil +} + +func (m *managerShim) Stop(ctx context.Context, id string) (StopStatus, error) { + return m.manager.Stop(ctx, id) +} + +func (m *managerShim) Info(ctx context.Context, optionsR io.Reader) (*types.RuntimeInfo, error) { + return m.manager.Info(ctx, optionsR) +} + +// Run initializes and runs a shim server. +// +// Deprecated: Use [RunShim] instead. +func Run(ctx context.Context, manager Manager, opts ...BinaryOpts) { + var config Config + for _, o := range opts { + o(&config) + } + + shim := &managerShim{manager: manager} + ctx = log.WithLogger(ctx, log.G(ctx).WithField("runtime", shim.Name())) + + if err := run(ctx, shim, config); err != nil { + fmt.Fprintf(os.Stderr, "%s: %s", shim.Name(), err) + os.Exit(1) + } +} diff --git a/pkg/shim/shim.go b/pkg/shim/shim.go index d2775651ea..642e47fe61 100644 --- a/pkg/shim/shim.go +++ b/pkg/shim/shim.go @@ -53,19 +53,17 @@ type Publisher interface { io.Closer } -type BootstrapParams = bootapi.BootstrapParams -type BootstrapResult = bootapi.BootstrapResult - type StopStatus struct { Pid int ExitStatus int ExitedAt time.Time } -// Manager is the interface which manages the shim process -type Manager interface { +// Shim is the interface which manages the shim process lifecycle using the +// new bootstrap protocol. +type Shim interface { Name() string - Start(ctx context.Context, params *BootstrapParams) (*BootstrapResult, error) + Start(ctx context.Context, params *bootapi.BootstrapParams) (*bootapi.BootstrapResult, error) Stop(ctx context.Context, id string) (StopStatus, error) Info(ctx context.Context, optionsR io.Reader) (*types.RuntimeInfo, error) } @@ -179,22 +177,23 @@ func setLogger(ctx context.Context, id string) (context.Context, error) { return log.WithLogger(ctx, l), nil } -// Run initializes and runs a shim server. -func Run(ctx context.Context, manager Manager, opts ...BinaryOpts) { +// RunShim initializes and runs a shim server using the new bootstrap protocol. +func RunShim(ctx context.Context, shim Shim, opts ...BinaryOpts) { var config Config for _, o := range opts { o(&config) } - ctx = log.WithLogger(ctx, log.G(ctx).WithField("runtime", manager.Name())) + ctx = log.WithLogger(ctx, log.G(ctx).WithField("runtime", shim.Name())) - if err := run(ctx, manager, config); err != nil { - fmt.Fprintf(os.Stderr, "%s: %s", manager.Name(), err) + if err := run(ctx, shim, config); err != nil { + fmt.Fprintf(os.Stderr, "%s: %s", shim.Name(), err) os.Exit(1) } } -func runInfo(ctx context.Context, manager Manager) error { + +func runInfo(ctx context.Context, manager Shim) error { info, err := manager.Info(ctx, os.Stdin) if err != nil { return err @@ -207,7 +206,7 @@ func runInfo(ctx context.Context, manager Manager) error { return err } -func run(ctx context.Context, manager Manager, config Config) error { +func run(ctx context.Context, manager Shim, config Config) error { parseFlags() if versionFlag { fmt.Printf("%s:\n", filepath.Base(os.Args[0]))