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 <derek@mcg.dev>
This commit is contained in:
parent
9a2b85561a
commit
1bf781d8eb
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
30
core/introspection/introspection.go
Normal file
30
core/introspection/introspection.go
Normal file
@ -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)
|
||||
}
|
108
core/introspection/proxy/remote.go
Normal file
108
core/introspection/proxy/remote.go
Normal file
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -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(),
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user