From 1bf781d8eba443244363f3e587a56a4287c08e65 Mon Sep 17 00:00:00 2001 From: Derek McGowan Date: Fri, 1 Mar 2024 23:06:22 -0800 Subject: [PATCH] Cleanup introspection interface Split service proxy from service plugin. Make introspection service easier for clients to use. Update service proxy to support grpc and ttrpc. Signed-off-by: Derek McGowan --- client/client.go | 24 ++-- client/install.go | 3 +- client/services.go | 12 +- cmd/ctr/commands/client.go | 3 +- cmd/ctr/commands/deprecations/deprecations.go | 3 +- cmd/ctr/commands/info/info.go | 3 +- cmd/ctr/commands/plugins/plugins.go | 2 +- core/introspection/introspection.go | 30 +++++ core/introspection/proxy/remote.go | 108 ++++++++++++++++++ internal/cri/server/service.go | 15 +-- internal/cri/server/status.go | 3 +- .../services/introspection/introspection.go | 77 ------------- plugins/services/introspection/local.go | 42 +++---- plugins/services/introspection/service.go | 29 +++-- 14 files changed, 195 insertions(+), 159 deletions(-) create mode 100644 core/introspection/introspection.go create mode 100644 core/introspection/proxy/remote.go delete mode 100644 plugins/services/introspection/introspection.go diff --git a/client/client.go b/client/client.go index b78030b71..17133de31 100644 --- a/client/client.go +++ b/client/client.go @@ -31,7 +31,6 @@ import ( diffapi "github.com/containerd/containerd/v2/api/services/diff/v1" eventsapi "github.com/containerd/containerd/v2/api/services/events/v1" imagesapi "github.com/containerd/containerd/v2/api/services/images/v1" - introspectionapi "github.com/containerd/containerd/v2/api/services/introspection/v1" leasesapi "github.com/containerd/containerd/v2/api/services/leases/v1" namespacesapi "github.com/containerd/containerd/v2/api/services/namespaces/v1" sandboxsapi "github.com/containerd/containerd/v2/api/services/sandbox/v1" @@ -44,6 +43,8 @@ import ( contentproxy "github.com/containerd/containerd/v2/core/content/proxy" "github.com/containerd/containerd/v2/core/events" "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/introspection" + introspectionproxy "github.com/containerd/containerd/v2/core/introspection/proxy" "github.com/containerd/containerd/v2/core/leases" leasesproxy "github.com/containerd/containerd/v2/core/leases/proxy" "github.com/containerd/containerd/v2/core/remotes" @@ -56,7 +57,6 @@ import ( "github.com/containerd/containerd/v2/pkg/dialer" "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/containerd/v2/plugins" - "github.com/containerd/containerd/v2/plugins/services/introspection" "github.com/containerd/containerd/v2/protobuf" ptypes "github.com/containerd/containerd/v2/protobuf/types" "github.com/containerd/errdefs" @@ -681,7 +681,7 @@ func (c *Client) IntrospectionService() introspection.Service { } c.connMu.Lock() defer c.connMu.Unlock() - return introspection.NewIntrospectionServiceFromClient(introspectionapi.NewIntrospectionClient(c.conn)) + return introspectionproxy.NewIntrospectionProxy(c.conn) } // LeasesService returns the underlying Leases Client @@ -785,7 +785,7 @@ func (c *Client) Server(ctx context.Context) (ServerInfo, error) { } c.connMu.Unlock() - response, err := c.IntrospectionService().Server(ctx, &ptypes.Empty{}) + response, err := c.IntrospectionService().Server(ctx) if err != nil { return ServerInfo{}, err } @@ -831,7 +831,7 @@ func (c *Client) GetSnapshotterSupportedPlatforms(ctx context.Context, snapshott filters := []string{fmt.Sprintf("type==%s, id==%s", plugins.SnapshotPlugin, snapshotterName)} in := c.IntrospectionService() - resp, err := in.Plugins(ctx, filters) + resp, err := in.Plugins(ctx, filters...) if err != nil { return nil, err } @@ -862,7 +862,7 @@ func (c *Client) GetSnapshotterCapabilities(ctx context.Context, snapshotterName filters := []string{fmt.Sprintf("type==%s, id==%s", plugins.SnapshotPlugin, snapshotterName)} in := c.IntrospectionService() - resp, err := in.Plugins(ctx, filters) + resp, err := in.Plugins(ctx, filters...) if err != nil { return nil, err } @@ -903,20 +903,10 @@ func (c *Client) RuntimeInfo(ctx context.Context, runtimePath string, runtimeOpt return nil, fmt.Errorf("failed to marshal %T: %w", runtimeOptions, err) } } - options, err := protobuf.MarshalAnyToProto(rr) - if err != nil { - return nil, fmt.Errorf("failed to marshal runtime requst: %w", err) - } s := c.IntrospectionService() - req := &introspectionapi.PluginInfoRequest{ - Type: string(plugins.RuntimePluginV2), - ID: "task", - Options: options, - } - - resp, err := s.PluginInfo(ctx, req) + resp, err := s.PluginInfo(ctx, string(plugins.RuntimePluginV2), "task", rr) if err != nil { return nil, err } diff --git a/client/install.go b/client/install.go index 38ef6fe29..2f636b277 100644 --- a/client/install.go +++ b/client/install.go @@ -112,8 +112,7 @@ func (c *Client) getInstallPath(ctx context.Context, config InstallConfig) (stri if config.Path != "" { return config.Path, nil } - filters := []string{"id==opt"} - resp, err := c.IntrospectionService().Plugins(ctx, filters) + resp, err := c.IntrospectionService().Plugins(ctx, "id==opt") if err != nil { return "", err } diff --git a/client/services.go b/client/services.go index d5e8361ce..dd383a977 100644 --- a/client/services.go +++ b/client/services.go @@ -22,19 +22,18 @@ import ( containersapi "github.com/containerd/containerd/v2/api/services/containers/v1" "github.com/containerd/containerd/v2/api/services/diff/v1" imagesapi "github.com/containerd/containerd/v2/api/services/images/v1" - introspectionapi "github.com/containerd/containerd/v2/api/services/introspection/v1" namespacesapi "github.com/containerd/containerd/v2/api/services/namespaces/v1" "github.com/containerd/containerd/v2/api/services/tasks/v1" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/introspection" "github.com/containerd/containerd/v2/core/leases" "github.com/containerd/containerd/v2/core/sandbox" "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/containerd/v2/plugins" srv "github.com/containerd/containerd/v2/plugins/services" - "github.com/containerd/containerd/v2/plugins/services/introspection" "github.com/containerd/plugin" ) @@ -150,13 +149,6 @@ func WithLeasesService(leasesService leases.Manager) ServicesOpt { } } -// WithIntrospectionClient sets the introspection service using an introspection client. -func WithIntrospectionClient(in introspectionapi.IntrospectionClient) ServicesOpt { - return func(s *services) { - s.introspectionService = introspection.NewIntrospectionServiceFromClient(in) - } -} - // WithIntrospectionService sets the introspection service. func WithIntrospectionService(in introspection.Service) ServicesOpt { return func(s *services) { @@ -221,7 +213,7 @@ func WithInMemoryServices(ic *plugin.InitContext) Opt { return WithNamespaceClient(s.(namespacesapi.NamespacesClient)) }, srv.IntrospectionService: func(s interface{}) ServicesOpt { - return WithIntrospectionClient(s.(introspectionapi.IntrospectionClient)) + return WithIntrospectionService(s.(introspection.Service)) }, } { i := plugins[s] diff --git a/cmd/ctr/commands/client.go b/cmd/ctr/commands/client.go index 655dc6fdd..80de87bb1 100644 --- a/cmd/ctr/commands/client.go +++ b/cmd/ctr/commands/client.go @@ -24,7 +24,6 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/epoch" "github.com/containerd/containerd/v2/pkg/namespaces" - ptypes "github.com/containerd/containerd/v2/protobuf/types" "github.com/containerd/log" "github.com/urfave/cli/v2" ) @@ -73,7 +72,7 @@ func NewClient(context *cli.Context, opts ...containerd.Opt) (*containerd.Client } } if !suppressDeprecationWarnings { - resp, err := client.IntrospectionService().Server(ctx, &ptypes.Empty{}) + resp, err := client.IntrospectionService().Server(ctx) if err != nil { log.L.WithError(err).Warn("Failed to check deprecations") } else { diff --git a/cmd/ctr/commands/deprecations/deprecations.go b/cmd/ctr/commands/deprecations/deprecations.go index 34ec9bd69..67ed2ca1b 100644 --- a/cmd/ctr/commands/deprecations/deprecations.go +++ b/cmd/ctr/commands/deprecations/deprecations.go @@ -27,7 +27,6 @@ import ( api "github.com/containerd/containerd/v2/api/services/introspection/v1" "github.com/containerd/containerd/v2/cmd/ctr/commands" "github.com/containerd/containerd/v2/protobuf" - ptypes "github.com/containerd/containerd/v2/protobuf/types" ) // Command is the parent for all commands under "deprecations" @@ -56,7 +55,7 @@ var listCommand = &cli.Command{ } defer cancel() - resp, err := client.IntrospectionService().Server(ctx, &ptypes.Empty{}) + resp, err := client.IntrospectionService().Server(ctx) if err != nil { return err } diff --git a/cmd/ctr/commands/info/info.go b/cmd/ctr/commands/info/info.go index 101c189c6..1a10e97e3 100644 --- a/cmd/ctr/commands/info/info.go +++ b/cmd/ctr/commands/info/info.go @@ -19,7 +19,6 @@ package info import ( api "github.com/containerd/containerd/v2/api/services/introspection/v1" "github.com/containerd/containerd/v2/cmd/ctr/commands" - ptypes "github.com/containerd/containerd/v2/protobuf/types" "github.com/urfave/cli/v2" ) @@ -38,7 +37,7 @@ var Command = &cli.Command{ } defer cancel() var info Info - info.Server, err = client.IntrospectionService().Server(ctx, &ptypes.Empty{}) + info.Server, err = client.IntrospectionService().Server(ctx) if err != nil { return err } diff --git a/cmd/ctr/commands/plugins/plugins.go b/cmd/ctr/commands/plugins/plugins.go index e152ff199..0d2f25352 100644 --- a/cmd/ctr/commands/plugins/plugins.go +++ b/cmd/ctr/commands/plugins/plugins.go @@ -71,7 +71,7 @@ var listCommand = &cli.Command{ } defer cancel() ps := client.IntrospectionService() - response, err := ps.Plugins(ctx, context.Args().Slice()) + response, err := ps.Plugins(ctx, context.Args().Slice()...) if err != nil { return err } diff --git a/core/introspection/introspection.go b/core/introspection/introspection.go new file mode 100644 index 000000000..cc9dca18d --- /dev/null +++ b/core/introspection/introspection.go @@ -0,0 +1,30 @@ +/* + 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 introspection + +import ( + context "context" + + api "github.com/containerd/containerd/v2/api/services/introspection/v1" +) + +// Service defines the introspection service interface +type Service interface { + Plugins(context.Context, ...string) (*api.PluginsResponse, error) + Server(context.Context) (*api.ServerResponse, error) + PluginInfo(context.Context, string, string, any) (*api.PluginInfoResponse, error) +} diff --git a/core/introspection/proxy/remote.go b/core/introspection/proxy/remote.go new file mode 100644 index 000000000..4f10e6aa0 --- /dev/null +++ b/core/introspection/proxy/remote.go @@ -0,0 +1,108 @@ +/* + 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 introspectionproxy + +import ( + "context" + "fmt" + + api "github.com/containerd/containerd/v2/api/services/introspection/v1" + "github.com/containerd/containerd/v2/core/introspection" + "github.com/containerd/containerd/v2/protobuf" + "github.com/containerd/errdefs" + "github.com/containerd/log" + "github.com/containerd/ttrpc" + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/emptypb" +) + +var _ = (introspection.Service)(&introspectionRemote{}) + +// NewIntrospectionServiceFromClient creates a new introspection service from an API client +func NewIntrospectionProxy(client any) introspection.Service { + switch c := client.(type) { + case api.IntrospectionClient: + return &introspectionRemote{client: convertIntrospection{c}} + case api.TTRPCIntrospectionService: + return &introspectionRemote{client: c} + case grpc.ClientConnInterface: + return &introspectionRemote{client: convertIntrospection{api.NewIntrospectionClient(c)}} + case *ttrpc.Client: + return &introspectionRemote{client: api.NewTTRPCIntrospectionClient(c)} + default: + panic(fmt.Errorf("unsupported introspection client %T: %w", client, errdefs.ErrNotImplemented)) + } +} + +type introspectionRemote struct { + client api.TTRPCIntrospectionService +} + +func (i *introspectionRemote) Plugins(ctx context.Context, filters ...string) (*api.PluginsResponse, error) { + log.G(ctx).WithField("filters", filters).Debug("remote introspection plugin filters") + resp, err := i.client.Plugins(ctx, &api.PluginsRequest{ + Filters: filters, + }) + + if err != nil { + return nil, errdefs.FromGRPC(err) + } + + return resp, nil +} + +func (i *introspectionRemote) Server(ctx context.Context) (*api.ServerResponse, error) { + resp, err := i.client.Server(ctx, &emptypb.Empty{}) + + if err != nil { + return nil, errdefs.FromGRPC(err) + } + + return resp, nil +} + +func (i *introspectionRemote) PluginInfo(ctx context.Context, pluginType, id string, options any) (resp *api.PluginInfoResponse, err error) { + var optionsPB *anypb.Any + if options != nil { + optionsPB, err = protobuf.MarshalAnyToProto(options) + if err != nil { + return nil, fmt.Errorf("failed to marshal runtime requst: %w", err) + } + } + resp, err = i.client.PluginInfo(ctx, &api.PluginInfoRequest{ + Type: pluginType, + ID: id, + Options: optionsPB, + }) + + return resp, errdefs.FromGRPC(err) +} + +type convertIntrospection struct { + client api.IntrospectionClient +} + +func (c convertIntrospection) Plugins(ctx context.Context, req *api.PluginsRequest) (*api.PluginsResponse, error) { + return c.client.Plugins(ctx, req) +} +func (c convertIntrospection) Server(ctx context.Context, in *emptypb.Empty) (*api.ServerResponse, error) { + return c.client.Server(ctx, in) +} +func (c convertIntrospection) PluginInfo(ctx context.Context, req *api.PluginInfoRequest) (*api.PluginInfoResponse, error) { + return c.client.PluginInfo(ctx, req) +} diff --git a/internal/cri/server/service.go b/internal/cri/server/service.go index 9e4ba10b3..2fb2e5d28 100644 --- a/internal/cri/server/service.go +++ b/internal/cri/server/service.go @@ -34,9 +34,9 @@ import ( runtime "k8s.io/cri-api/pkg/apis/runtime/v1" "k8s.io/kubelet/pkg/cri/streaming" - introspectionapi "github.com/containerd/containerd/v2/api/services/introspection/v1" apitypes "github.com/containerd/containerd/v2/api/types" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/introspection" _ "github.com/containerd/containerd/v2/core/runtime" // for typeurl init "github.com/containerd/containerd/v2/core/sandbox" "github.com/containerd/containerd/v2/internal/cri/config" @@ -54,7 +54,6 @@ import ( "github.com/containerd/containerd/v2/pkg/oci" osinterface "github.com/containerd/containerd/v2/pkg/os" "github.com/containerd/containerd/v2/plugins" - "github.com/containerd/containerd/v2/plugins/services/introspection" "github.com/containerd/containerd/v2/protobuf" ) @@ -407,10 +406,7 @@ func introspectRuntimeFeatures(ctx context.Context, intro introspection.Service, plugins.RuntimeRuncV2, r.Type) // For other runtimes, protobuf.MarshalAnyToProto will cause nil panic during typeurl dereference } - infoReq := &introspectionapi.PluginInfoRequest{ - Type: string(plugins.RuntimePluginV2), // "io.containerd.runtime.v2" - ID: "task", - } + rr := &apitypes.RuntimeRequest{ RuntimePath: r.Type, // "io.containerd.runc.v2" } @@ -425,11 +421,8 @@ func introspectRuntimeFeatures(ctx context.Context, intro introspection.Service, if err != nil { return nil, fmt.Errorf("failed to marshal %T: %w", options, err) } - infoReq.Options, err = protobuf.MarshalAnyToProto(rr) - if err != nil { - return nil, fmt.Errorf("failed to marshal %T: %w", rr, err) - } - infoResp, err := intro.PluginInfo(ctx, infoReq) + + infoResp, err := intro.PluginInfo(ctx, string(plugins.RuntimePluginV2), "task", rr) if err != nil { return nil, fmt.Errorf("failed to call PluginInfo: %w", err) } diff --git a/internal/cri/server/status.go b/internal/cri/server/status.go index 61e1d2c1c..7c51665db 100644 --- a/internal/cri/server/status.go +++ b/internal/cri/server/status.go @@ -23,7 +23,6 @@ import ( goruntime "runtime" "github.com/containerd/containerd/v2/api/services/introspection/v1" - ptypes "github.com/containerd/containerd/v2/protobuf/types" "github.com/containerd/log" runtime "k8s.io/cri-api/pkg/apis/runtime/v1" ) @@ -97,7 +96,7 @@ func (c *criService) Status(ctx context.Context, r *runtime.StatusRequest) (*run } resp.Info["lastCNILoadStatus"] = defaultStatus } - intro, err := c.client.IntrospectionService().Server(ctx, &ptypes.Empty{}) + intro, err := c.client.IntrospectionService().Server(ctx) if err != nil { return nil, err } diff --git a/plugins/services/introspection/introspection.go b/plugins/services/introspection/introspection.go deleted file mode 100644 index b455dc3ee..000000000 --- a/plugins/services/introspection/introspection.go +++ /dev/null @@ -1,77 +0,0 @@ -/* - 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 introspection - -import ( - context "context" - - api "github.com/containerd/containerd/v2/api/services/introspection/v1" - ptypes "github.com/containerd/containerd/v2/protobuf/types" - "github.com/containerd/errdefs" - "github.com/containerd/log" -) - -// Service defines the introspection service interface -type Service interface { - Plugins(context.Context, []string) (*api.PluginsResponse, error) - Server(context.Context, *ptypes.Empty) (*api.ServerResponse, error) - PluginInfo(ctx context.Context, in *api.PluginInfoRequest) (*api.PluginInfoResponse, error) -} - -type introspectionRemote struct { - client api.IntrospectionClient -} - -var _ = (Service)(&introspectionRemote{}) - -// NewIntrospectionServiceFromClient creates a new introspection service from an API client -func NewIntrospectionServiceFromClient(c api.IntrospectionClient) Service { - return &introspectionRemote{client: c} -} - -func (i *introspectionRemote) Plugins(ctx context.Context, filters []string) (*api.PluginsResponse, error) { - log.G(ctx).WithField("filters", filters).Debug("remote introspection plugin filters") - resp, err := i.client.Plugins(ctx, &api.PluginsRequest{ - Filters: filters, - }) - - if err != nil { - return nil, errdefs.FromGRPC(err) - } - - return resp, nil -} - -func (i *introspectionRemote) Server(ctx context.Context, in *ptypes.Empty) (*api.ServerResponse, error) { - resp, err := i.client.Server(ctx, in) - - if err != nil { - return nil, errdefs.FromGRPC(err) - } - - return resp, nil -} - -func (i *introspectionRemote) PluginInfo(ctx context.Context, in *api.PluginInfoRequest) (*api.PluginInfoResponse, error) { - resp, err := i.client.PluginInfo(ctx, in) - - if err != nil { - return nil, errdefs.FromGRPC(err) - } - - return resp, nil -} diff --git a/plugins/services/introspection/local.go b/plugins/services/introspection/local.go index 29f261d9e..5c9cbf859 100644 --- a/plugins/services/introspection/local.go +++ b/plugins/services/introspection/local.go @@ -28,11 +28,11 @@ import ( "github.com/google/uuid" "google.golang.org/genproto/googleapis/rpc/code" rpc "google.golang.org/genproto/googleapis/rpc/status" - "google.golang.org/grpc" "google.golang.org/grpc/status" api "github.com/containerd/containerd/v2/api/services/introspection/v1" "github.com/containerd/containerd/v2/api/types" + "github.com/containerd/containerd/v2/core/introspection" "github.com/containerd/containerd/v2/pkg/filters" "github.com/containerd/containerd/v2/plugins" "github.com/containerd/containerd/v2/plugins/services" @@ -80,7 +80,7 @@ type Local struct { warningClient warning.Service } -var _ = (api.IntrospectionClient)(&Local{}) +var _ = (introspection.Service)(&Local{}) // UpdateLocal updates the local introspection service func (l *Local) UpdateLocal(root string) { @@ -90,10 +90,10 @@ func (l *Local) UpdateLocal(root string) { } // Plugins returns the locally defined plugins -func (l *Local) Plugins(ctx context.Context, req *api.PluginsRequest, _ ...grpc.CallOption) (*api.PluginsResponse, error) { - filter, err := filters.ParseAll(req.Filters...) +func (l *Local) Plugins(ctx context.Context, fs ...string) (*api.PluginsResponse, error) { + filter, err := filters.ParseAll(fs...) if err != nil { - return nil, errdefs.ToGRPCf(errdefs.ErrInvalidArgument, err.Error()) + return nil, fmt.Errorf("%w: %w", errdefs.ErrInvalidArgument, err) } var plugins []*api.Plugin @@ -121,17 +121,17 @@ func (l *Local) getPlugins() []*api.Plugin { } // Server returns the local server information -func (l *Local) Server(ctx context.Context, _ *ptypes.Empty, _ ...grpc.CallOption) (*api.ServerResponse, error) { +func (l *Local) Server(ctx context.Context) (*api.ServerResponse, error) { u, err := l.getUUID() if err != nil { - return nil, errdefs.ToGRPC(err) + return nil, err } pid := os.Getpid() var pidns uint64 if runtime.GOOS == "linux" { pidns, err = statPIDNS(pid) if err != nil { - return nil, errdefs.ToGRPC(err) + return nil, err } } return &api.ServerResponse{ @@ -278,11 +278,10 @@ type pluginInfoProvider interface { PluginInfo(context.Context, interface{}) (interface{}, error) } -func (l *Local) PluginInfo(ctx context.Context, req *api.PluginInfoRequest, _ ...grpc.CallOption) (*api.PluginInfoResponse, error) { - p := l.plugins.Get(plugin.Type(req.Type), req.ID) +func (l *Local) PluginInfo(ctx context.Context, pluginType, id string, options any) (*api.PluginInfoResponse, error) { + p := l.plugins.Get(plugin.Type(pluginType), id) if p == nil { - err := fmt.Errorf("plugin %s.%s not found: %w", req.Type, req.ID, errdefs.ErrNotFound) - return nil, errdefs.ToGRPC(err) + return nil, fmt.Errorf("plugin %s.%s not found: %w", pluginType, id, errdefs.ErrNotFound) } resp := &api.PluginInfoResponse{ @@ -290,35 +289,26 @@ func (l *Local) PluginInfo(ctx context.Context, req *api.PluginInfoRequest, _ .. } // Request additional info from plugin instance - if req.Options != nil { + if options != nil { if p.Err() != nil { - err := fmt.Errorf("cannot get extra info, plugin not successfully loaded: %w", errdefs.ErrFailedPrecondition) - return resp, errdefs.ToGRPC(err) + return resp, fmt.Errorf("cannot get extra info, plugin not successfully loaded: %w", errdefs.ErrFailedPrecondition) } inst, err := p.Instance() if err != nil { - err := fmt.Errorf("failed to get plugin instance: %w", errdefs.ErrFailedPrecondition) - return resp, errdefs.ToGRPC(err) + return resp, fmt.Errorf("failed to get plugin instance: %w", errdefs.ErrFailedPrecondition) } pi, ok := inst.(pluginInfoProvider) if !ok { - err := fmt.Errorf("plugin does not provided extra information: %w", errdefs.ErrNotImplemented) - return resp, errdefs.ToGRPC(err) + return resp, fmt.Errorf("plugin does not provided extra information: %w", errdefs.ErrNotImplemented) } - options, err := typeurl.UnmarshalAny(req.Options) - if err != nil { - err = fmt.Errorf("failed to unmarshal plugin info Options: %w", err) - return resp, errdefs.ToGRPC(err) - } info, err := pi.PluginInfo(ctx, options) if err != nil { return resp, errdefs.ToGRPC(err) } ai, err := typeurl.MarshalAny(info) if err != nil { - err = fmt.Errorf("failed to marshal plugin info: %w", err) - return resp, errdefs.ToGRPC(err) + return resp, fmt.Errorf("failed to marshal plugin info: %w", err) } resp.Extra = &ptypes.Any{ TypeUrl: ai.GetTypeUrl(), diff --git a/plugins/services/introspection/service.go b/plugins/services/introspection/service.go index b8af091e9..eced9dd7c 100644 --- a/plugins/services/introspection/service.go +++ b/plugins/services/introspection/service.go @@ -19,13 +19,17 @@ package introspection import ( context "context" "errors" + "fmt" api "github.com/containerd/containerd/v2/api/services/introspection/v1" + "github.com/containerd/containerd/v2/core/introspection" "github.com/containerd/containerd/v2/plugins" "github.com/containerd/containerd/v2/plugins/services" ptypes "github.com/containerd/containerd/v2/protobuf/types" + "github.com/containerd/errdefs" "github.com/containerd/plugin" "github.com/containerd/plugin/registry" + "github.com/containerd/typeurl/v2" "google.golang.org/grpc" ) @@ -54,7 +58,7 @@ func init() { } type server struct { - local api.IntrospectionClient + local introspection.Service api.UnimplementedIntrospectionServer } @@ -65,14 +69,25 @@ func (s *server) Register(server *grpc.Server) error { return nil } -func (s *server) Plugins(ctx context.Context, req *api.PluginsRequest) (*api.PluginsResponse, error) { - return s.local.Plugins(ctx, req) +func (s *server) Plugins(ctx context.Context, req *api.PluginsRequest) (resp *api.PluginsResponse, err error) { + resp, err = s.local.Plugins(ctx, req.Filters...) + return resp, errdefs.ToGRPC(err) } -func (s *server) Server(ctx context.Context, empty *ptypes.Empty) (*api.ServerResponse, error) { - return s.local.Server(ctx, empty) +func (s *server) Server(ctx context.Context, _ *ptypes.Empty) (resp *api.ServerResponse, err error) { + resp, err = s.local.Server(ctx) + return resp, errdefs.ToGRPC(err) } -func (s *server) PluginInfo(ctx context.Context, req *api.PluginInfoRequest) (*api.PluginInfoResponse, error) { - return s.local.PluginInfo(ctx, req) +func (s *server) PluginInfo(ctx context.Context, req *api.PluginInfoRequest) (resp *api.PluginInfoResponse, err error) { + var options any + if req.Options != nil { + options, err = typeurl.UnmarshalAny(req.Options) + if err != nil { + return resp, errdefs.ToGRPC(fmt.Errorf("failed to unmarshal plugin info Options: %w", err)) + } + } + + resp, err = s.local.PluginInfo(ctx, req.Type, req.ID, options) + return resp, errdefs.ToGRPC(err) }