api/services/instrospection: add PluginInfo

The new `PlunginInfo()` call can be used for instrospecting the details
of the runtime plugin.

```console
$ ctr plugins inspect-runtime --runtime=io.containerd.runc.v2 --runc-binary=runc
{
    "Name": "io.containerd.runc.v2",
    "Version": {
        "Version": "v2.0.0-beta.0-XX-gXXXXXXXXX.m",
        "Revision": "v2.0.0-beta.0-XX-gXXXXXXXXX.m"
    },
    "Options": {
        "binary_name": "runc"
    },
    "Features": {
        "ociVersionMin": "1.0.0",
        "ociVersionMax": "1.1.0-rc.2",
        ...,
    },
    "Annotations": null
}
```

The shim binary has to support `-info` flag, see `runtime/v2/README.md`

Replaces PR 8509 (`api/services/task: add RuntimeInfo()`)

Co-authored-by: Derek McGowan <derek@mcg.dev>
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
Akihiro Suda
2023-05-11 18:17:13 +09:00
parent 9dbb7615b6
commit 22d586e515
24 changed files with 1423 additions and 204 deletions

View File

@@ -58,11 +58,13 @@ import (
"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/platforms"
"github.com/containerd/typeurl/v2"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-spec/specs-go/features"
"golang.org/x/sync/semaphore"
"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
@@ -78,6 +80,7 @@ func init() {
typeurl.Register(&specs.Process{}, prefix, "opencontainers/runtime-spec", major, "Process")
typeurl.Register(&specs.LinuxResources{}, prefix, "opencontainers/runtime-spec", major, "LinuxResources")
typeurl.Register(&specs.WindowsResources{}, prefix, "opencontainers/runtime-spec", major, "WindowsResources")
typeurl.Register(&features.Features{}, prefix, "opencontainers/runtime-spec", major, "features", "Features")
}
// New returns a new containerd client that is connected to the containerd
@@ -871,3 +874,76 @@ func (c *Client) GetSnapshotterCapabilities(ctx context.Context, snapshotterName
sn := resp.Plugins[0]
return sn.Capabilities, nil
}
type RuntimeVersion struct {
Version string
Revision string
}
type RuntimeInfo struct {
Name string
Version RuntimeVersion
Options interface{}
Features interface{}
Annotations map[string]string
}
func (c *Client) RuntimeInfo(ctx context.Context, runtimePath string, runtimeOptions interface{}) (*RuntimeInfo, error) {
rt := c.runtime
if runtimePath != "" {
rt = runtimePath
}
rr := &apitypes.RuntimeRequest{
RuntimePath: rt,
}
var err error
if runtimeOptions != nil {
rr.Options, err = protobuf.MarshalAnyToProto(runtimeOptions)
if err != nil {
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)
if err != nil {
return nil, err
}
var info apitypes.RuntimeInfo
if err := typeurl.UnmarshalTo(resp.Extra, &info); err != nil {
return nil, fmt.Errorf("failed to get runtime info from plugin info: %w", err)
}
var result RuntimeInfo
result.Name = info.Name
if info.Version != nil {
result.Version.Version = info.Version.Version
result.Version.Revision = info.Version.Revision
}
if info.Options != nil {
result.Options, err = typeurl.UnmarshalAny(info.Options)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal RuntimeInfo.Options (%T): %w", info.Options, err)
}
}
if info.Features != nil {
result.Features, err = typeurl.UnmarshalAny(info.Features)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal RuntimeInfo.Features (%T): %w", info.Features, err)
}
}
result.Annotations = info.Annotations
return &result, nil
}