mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-10 21:53:57 +08:00
Add runc features command
Fix issue 3274 See `types/features/features.go`. Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
+74
@@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/capabilities"
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/seccomp"
|
||||
"github.com/opencontainers/runc/libcontainer/specconv"
|
||||
"github.com/opencontainers/runc/types/features"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var featuresCommand = cli.Command{
|
||||
Name: "features",
|
||||
Usage: "show the enabled features",
|
||||
ArgsUsage: "",
|
||||
Description: `Show the enabled features.
|
||||
The result is parsable as a JSON.
|
||||
See https://pkg.go.dev/github.com/opencontainers/runc/types/features for the type definition.
|
||||
`,
|
||||
Action: func(context *cli.Context) error {
|
||||
if err := checkArgs(context, 0, exactArgs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tru := true
|
||||
|
||||
feat := features.Features{
|
||||
OCIVersionMin: "1.0.0",
|
||||
OCIVersionMax: specs.Version,
|
||||
Annotations: map[string]string{
|
||||
features.AnnotationRuncVersion: version,
|
||||
features.AnnotationRuncCommit: gitCommit,
|
||||
features.AnnotationRuncCheckpointEnabled: "true",
|
||||
},
|
||||
Hooks: configs.KnownHookNames(),
|
||||
MountOptions: specconv.KnownMountOptions(),
|
||||
Linux: &features.Linux{
|
||||
Namespaces: specconv.KnownNamespaces(),
|
||||
Capabilities: capabilities.KnownCapabilities(),
|
||||
Cgroup: &features.Cgroup{
|
||||
V1: &tru,
|
||||
V2: &tru,
|
||||
Systemd: &tru,
|
||||
SystemdUser: &tru,
|
||||
},
|
||||
Apparmor: &features.Apparmor{
|
||||
Enabled: &tru,
|
||||
},
|
||||
Selinux: &features.Selinux{
|
||||
Enabled: &tru,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if seccomp.Enabled {
|
||||
feat.Linux.Seccomp = &features.Seccomp{
|
||||
Enabled: &tru,
|
||||
Actions: seccomp.KnownActions(),
|
||||
Operators: seccomp.KnownOperators(),
|
||||
Archs: seccomp.KnownArchs(),
|
||||
}
|
||||
major, minor, patch := seccomp.Version()
|
||||
feat.Annotations[features.AnnotationLibseccompVersion] = fmt.Sprintf("%d.%d.%d", major, minor, patch)
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(context.App.Writer)
|
||||
enc.SetIndent("", " ")
|
||||
return enc.Encode(feat)
|
||||
},
|
||||
}
|
||||
@@ -35,6 +35,17 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
// KnownCapabilities returns the list of the known capabilities.
|
||||
// Used by `runc features`.
|
||||
func KnownCapabilities() []string {
|
||||
list := capability.List()
|
||||
res := make([]string, len(list))
|
||||
for i, c := range list {
|
||||
res[i] = "CAP_" + strings.ToUpper(c.String())
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// New creates a new Caps from the given Capabilities config. Unknown Capabilities
|
||||
// or Capabilities that are unavailable in the current environment are ignored,
|
||||
// printing a warning instead.
|
||||
|
||||
@@ -251,6 +251,19 @@ const (
|
||||
Poststop HookName = "poststop"
|
||||
)
|
||||
|
||||
// KnownHookNames returns the known hook names.
|
||||
// Used by `runc features`.
|
||||
func KnownHookNames() []string {
|
||||
return []string{
|
||||
string(Prestart), // deprecated
|
||||
string(CreateRuntime),
|
||||
string(CreateContainer),
|
||||
string(StartContainer),
|
||||
string(Poststart),
|
||||
string(Poststop),
|
||||
}
|
||||
}
|
||||
|
||||
type Capabilities struct {
|
||||
// Bounding is the set of capabilities checked by the kernel.
|
||||
Bounding []string
|
||||
|
||||
@@ -2,6 +2,7 @@ package seccomp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
)
|
||||
@@ -16,6 +17,17 @@ var operators = map[string]configs.Operator{
|
||||
"SCMP_CMP_MASKED_EQ": configs.MaskEqualTo,
|
||||
}
|
||||
|
||||
// KnownOperators returns the list of the known operations.
|
||||
// Used by `runc features`.
|
||||
func KnownOperators() []string {
|
||||
var res []string
|
||||
for k := range operators {
|
||||
res = append(res, k)
|
||||
}
|
||||
sort.Strings(res)
|
||||
return res
|
||||
}
|
||||
|
||||
var actions = map[string]configs.Action{
|
||||
"SCMP_ACT_KILL": configs.Kill,
|
||||
"SCMP_ACT_ERRNO": configs.Errno,
|
||||
@@ -26,6 +38,17 @@ var actions = map[string]configs.Action{
|
||||
"SCMP_ACT_NOTIFY": configs.Notify,
|
||||
}
|
||||
|
||||
// KnownActions returns the list of the known actions.
|
||||
// Used by `runc features`.
|
||||
func KnownActions() []string {
|
||||
var res []string
|
||||
for k := range actions {
|
||||
res = append(res, k)
|
||||
}
|
||||
sort.Strings(res)
|
||||
return res
|
||||
}
|
||||
|
||||
var archs = map[string]string{
|
||||
"SCMP_ARCH_X86": "x86",
|
||||
"SCMP_ARCH_X86_64": "amd64",
|
||||
@@ -45,6 +68,17 @@ var archs = map[string]string{
|
||||
"SCMP_ARCH_S390X": "s390x",
|
||||
}
|
||||
|
||||
// KnownArchs returns the list of the known archs.
|
||||
// Used by `runc features`.
|
||||
func KnownArchs() []string {
|
||||
var res []string
|
||||
for k := range archs {
|
||||
res = append(res, k)
|
||||
}
|
||||
sort.Strings(res)
|
||||
return res
|
||||
}
|
||||
|
||||
// ConvertStringToOperator converts a string into a Seccomp comparison operator.
|
||||
// Comparison operators use the names they are assigned by Libseccomp's header.
|
||||
// Attempting to convert a string that is not a valid operator results in an
|
||||
|
||||
@@ -265,3 +265,6 @@ func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall, defAct libs
|
||||
func Version() (uint, uint, uint) {
|
||||
return libseccomp.GetLibraryVersion()
|
||||
}
|
||||
|
||||
// Enabled is true if seccomp support is compiled in.
|
||||
const Enabled = true
|
||||
|
||||
@@ -23,3 +23,6 @@ func InitSeccomp(config *configs.Seccomp) (int, error) {
|
||||
func Version() (uint, uint, uint) {
|
||||
return 0, 0, 0
|
||||
}
|
||||
|
||||
// Enabled is true if seccomp support is compiled in.
|
||||
const Enabled = false
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -105,6 +106,38 @@ func initMaps() {
|
||||
})
|
||||
}
|
||||
|
||||
// KnownNamespaces returns the list of the known namespaces.
|
||||
// Used by `runc features`.
|
||||
func KnownNamespaces() []string {
|
||||
initMaps()
|
||||
var res []string
|
||||
for k := range namespaceMapping {
|
||||
res = append(res, string(k))
|
||||
}
|
||||
sort.Strings(res)
|
||||
return res
|
||||
}
|
||||
|
||||
// KnownMountOptions returns the list of the known mount options.
|
||||
// Used by `runc features`.
|
||||
func KnownMountOptions() []string {
|
||||
initMaps()
|
||||
var res []string
|
||||
for k := range mountFlags {
|
||||
res = append(res, k)
|
||||
}
|
||||
for k := range mountPropagationMapping {
|
||||
if k != "" {
|
||||
res = append(res, k)
|
||||
}
|
||||
}
|
||||
for k := range extensionFlags {
|
||||
res = append(res, k)
|
||||
}
|
||||
sort.Strings(res)
|
||||
return res
|
||||
}
|
||||
|
||||
// AllowedDevices is the set of devices which are automatically included for
|
||||
// all containers.
|
||||
//
|
||||
|
||||
@@ -132,6 +132,7 @@ func main() {
|
||||
startCommand,
|
||||
stateCommand,
|
||||
updateCommand,
|
||||
featuresCommand,
|
||||
}
|
||||
app.Before = func(context *cli.Context) error {
|
||||
if !context.IsSet("root") && xdgRuntimeDir != "" {
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
// Package features provides the JSON structure that is printed by `runc features` (since runc v1.1.0).
|
||||
package features
|
||||
|
||||
// Features represents the supported features of the runtime.
|
||||
type Features struct {
|
||||
// OCIVersionMin is the minimum OCI Runtime Spec version recognized by the runtime, e.g., "1.0.0".
|
||||
OCIVersionMin string `json:"ociVersionMin,omitempty"`
|
||||
|
||||
// OCIVersionMax is the maximum OCI Runtime Spec version recognized by the runtime, e.g., "1.0.2-dev".
|
||||
OCIVersionMax string `json:"ociVersionMax,omitempty"`
|
||||
|
||||
// Hooks is the list of the recognized hook names, e.g., "createRuntime".
|
||||
// Nil value means "unknown", not "no support for any hook".
|
||||
Hooks []string `json:"hooks,omitempty"`
|
||||
|
||||
// MountOptions is the list of the recognized mount options, e.g., "ro".
|
||||
// Nil value means "unknown", not "no support for any mount option".
|
||||
MountOptions []string `json:"mountOptions,omitempty"`
|
||||
|
||||
// Linux is specific to Linux.
|
||||
Linux *Linux `json:"linux,omitempty"`
|
||||
|
||||
// Annotations contains implementation-specific annotation strings,
|
||||
// such as the implementation version, and third-party extensions.
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
}
|
||||
|
||||
// Linux is specific to Linux.
|
||||
type Linux struct {
|
||||
// Namespaces is the list of the recognized namespaces, e.g., "mount".
|
||||
// Nil value means "unknown", not "no support for any namespace".
|
||||
Namespaces []string `json:"namespaces,omitempty"`
|
||||
|
||||
// Capabilities is the list of the recognized capabilities , e.g., "CAP_SYS_ADMIN".
|
||||
// Nil value means "unknown", not "no support for any capability".
|
||||
Capabilities []string `json:"capabilities,omitempty"`
|
||||
|
||||
Cgroup *Cgroup `json:"cgroup,omitempty"`
|
||||
Seccomp *Seccomp `json:"seccomp,omitempty"`
|
||||
Apparmor *Apparmor `json:"apparmor,omitempty"`
|
||||
Selinux *Selinux `json:"selinux,omitempty"`
|
||||
}
|
||||
|
||||
// Seccomp represents the "seccomp" field.
|
||||
type Seccomp struct {
|
||||
// Enabled is true if seccomp support is compiled in.
|
||||
// Nil value means "unknown", not "false".
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
|
||||
// Actions is the list of the recognized actions, e.g., "SCMP_ACT_NOTIFY".
|
||||
// Nil value means "unknown", not "no support for any action".
|
||||
Actions []string `json:"actions,omitempty"`
|
||||
|
||||
// Operators is the list of the recognized actions, e.g., "SCMP_CMP_NE".
|
||||
// Nil value means "unknown", not "no support for any operator".
|
||||
Operators []string `json:"operators,omitempty"`
|
||||
|
||||
// Operators is the list of the recognized archs, e.g., "SCMP_ARCH_X86_64".
|
||||
// Nil value means "unknown", not "no support for any arch".
|
||||
Archs []string `json:"archs,omitempty"`
|
||||
}
|
||||
|
||||
// Apparmor represents the "apparmor" field.
|
||||
type Apparmor struct {
|
||||
// Enabled is true if AppArmor support is compiled in.
|
||||
// Unrelated to whether the host supports AppArmor or not.
|
||||
// Nil value means "unknown", not "false".
|
||||
// Always true in the current version of runc.
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
}
|
||||
|
||||
// Selinux represents the "selinux" field.
|
||||
type Selinux struct {
|
||||
// Enabled is true if SELinux support is compiled in.
|
||||
// Unrelated to whether the host supports SELinux or not.
|
||||
// Nil value means "unknown", not "false".
|
||||
// Always true in the current version of runc.
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
}
|
||||
|
||||
// Cgroup represents the "cgroup" field.
|
||||
type Cgroup struct {
|
||||
// V1 represents whether Cgroup v1 support is compiled in.
|
||||
// Unrelated to whether the host uses cgroup v1 or not.
|
||||
// Nil value means "unknown", not "false".
|
||||
// Always true in the current version of runc.
|
||||
V1 *bool `json:"v1,omitempty"`
|
||||
|
||||
// V2 represents whether Cgroup v2 support is compiled in.
|
||||
// Unrelated to whether the host uses cgroup v2 or not.
|
||||
// Nil value means "unknown", not "false".
|
||||
// Always true in the current version of runc.
|
||||
V2 *bool `json:"v2,omitempty"`
|
||||
|
||||
// Systemd represents whether systemd-cgroup support is compiled in.
|
||||
// Unrelated to whether the host uses systemd or not.
|
||||
// Nil value means "unknown", not "false".
|
||||
// Always true in the current version of runc.
|
||||
Systemd *bool `json:"systemd,omitempty"`
|
||||
|
||||
// SystemdUser represents whether user-scoped systemd-cgroup support is compiled in.
|
||||
// Unrelated to whether the host uses systemd or not.
|
||||
// Nil value means "unknown", not "false".
|
||||
// Always true in the current version of runc.
|
||||
SystemdUser *bool `json:"systemdUser,omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
// AnnotationRuncVersion represents the version of runc, e.g., "1.2.3", "1.2.3+dev", "1.2.3-rc.4.", "1.2.3-rc.4+dev".
|
||||
// Third party implementations such as crun and runsc MAY use this annotation to report the most compatible runc version,
|
||||
// however, parsing this annotation value is discouraged.
|
||||
AnnotationRuncVersion = "org.opencontainers.runc.version"
|
||||
|
||||
// AnnotationRuncCommit corresponds to the output of `git describe --dirty --long --always` in the runc repo.
|
||||
// Third party implementations such as crun and runsc SHOULD NOT use this annotation, as their repo is different from the runc repo.
|
||||
// Parsing this annotation value is discouraged.
|
||||
AnnotationRuncCommit = "org.opencontainers.runc.commit"
|
||||
|
||||
// AnnotationRuncCheckpointEnabled is set to "true" if CRIU-based checkpointing is supported.
|
||||
// Unrelated to whether the host supports CRIU or not.
|
||||
// Always set to "true" in the current version of runc.
|
||||
// This is defined as an annotation because checkpointing is a runc-specific feature that is not defined in the OCI Runtime Spec.
|
||||
// Third party implementations such as crun and runsc MAY use this annotation.
|
||||
AnnotationRuncCheckpointEnabled = "org.opencontainers.runc.checkpoint.enabled"
|
||||
|
||||
// AnnotationLibseccompVersion is the version of libseccomp, e.g., "2.5.1".
|
||||
// Note that the runtime MAY support seccomp even when this annotation is not present.
|
||||
AnnotationLibseccompVersion = "io.github.seccomp.libseccomp.version"
|
||||
)
|
||||
Reference in New Issue
Block a user