Add CDISpecDirs to Info output
This change adds the configured CDI spec directories to the system info output. Signed-off-by: Evan Lezar <elezar@nvidia.com>
This commit is contained in:
parent
bbb9255562
commit
7a59913b1a
5 changed files with 135 additions and 5 deletions
|
@ -5301,7 +5301,25 @@ definitions:
|
|||
- "WARNING: No memory limit support"
|
||||
- "WARNING: bridge-nf-call-iptables is disabled"
|
||||
- "WARNING: bridge-nf-call-ip6tables is disabled"
|
||||
CDISpecDirs:
|
||||
description: |
|
||||
List of directories where (Container Device Interface) CDI
|
||||
specifications are located.
|
||||
|
||||
These specifications define vendor-specific modifications to an OCI
|
||||
runtime specification for a container being created.
|
||||
|
||||
An empty list indicates that CDI device injection is disabled.
|
||||
|
||||
Note that since using CDI device injection requires the daemon to have
|
||||
experimental enabled. For non-experimental daemons an empty list will
|
||||
always be returned.
|
||||
type: "array"
|
||||
items:
|
||||
type: "string"
|
||||
example:
|
||||
- "/etc/cdi"
|
||||
- "/var/run/cdi"
|
||||
|
||||
# PluginsInfo is a temp struct holding Plugins name
|
||||
# registered with docker daemon. It is used by Info struct
|
||||
|
|
|
@ -73,6 +73,7 @@ type Info struct {
|
|||
SecurityOptions []string
|
||||
ProductLicense string `json:",omitempty"`
|
||||
DefaultAddressPools []NetworkAddressPool `json:",omitempty"`
|
||||
CDISpecDirs []string
|
||||
|
||||
// Legacy API fields for older API versions.
|
||||
legacyFields
|
||||
|
|
|
@ -62,6 +62,7 @@ func (daemon *Daemon) SystemInfo() *system.Info {
|
|||
NoProxy: getConfigOrEnv(cfg.NoProxy, "NO_PROXY", "no_proxy"),
|
||||
LiveRestoreEnabled: cfg.LiveRestoreEnabled,
|
||||
Isolation: daemon.defaultIsolation,
|
||||
CDISpecDirs: promoteNil(cfg.CDISpecDirs),
|
||||
}
|
||||
|
||||
daemon.fillContainerStates(v)
|
||||
|
@ -309,3 +310,12 @@ func getConfigOrEnv(config string, env ...string) string {
|
|||
}
|
||||
return getEnvAny(env...)
|
||||
}
|
||||
|
||||
// promoteNil converts a nil slice to an empty slice of that type.
|
||||
// A non-nil slice is returned as is.
|
||||
func promoteNil[S ~[]E, E any](s S) S {
|
||||
if s == nil {
|
||||
return S{}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
|
@ -34,6 +34,10 @@ keywords: "API, Docker, rcli, REST, documentation"
|
|||
`BindOptions.ReadOnlyNonRecursive` and `BindOptions.ReadOnlyForceRecursive` to customize the behavior.
|
||||
* `POST /containers/create` now accepts a `HealthConfig.StartInterval` to set the
|
||||
interval for health checks during the start period.
|
||||
* `GET /info` now includes a `CDISpecDirs` field indicating the configured CDI
|
||||
specifications directories. The use of the applied setting requires the daemon
|
||||
to have expermental enabled, and for non-experimental daemons an empty list is
|
||||
always returned.
|
||||
|
||||
## v1.43 API changes
|
||||
|
||||
|
@ -103,7 +107,7 @@ keywords: "API, Docker, rcli, REST, documentation"
|
|||
a default.
|
||||
|
||||
This change is not versioned, and affects all API versions if the daemon has
|
||||
this patch.
|
||||
this patch.
|
||||
* `GET /_ping` and `HEAD /_ping` now return a `Swarm` header, which allows a
|
||||
client to detect if Swarm is enabled on the daemon, without having to call
|
||||
additional endpoints.
|
||||
|
@ -126,7 +130,7 @@ keywords: "API, Docker, rcli, REST, documentation"
|
|||
versioned, and affects all API versions if the daemon has this patch.
|
||||
* `GET /containers/{id}/attach`, `GET /exec/{id}/start`, `GET /containers/{id}/logs`
|
||||
`GET /services/{id}/logs` and `GET /tasks/{id}/logs` now set Content-Type header
|
||||
to `application/vnd.docker.multiplexed-stream` when a multiplexed stdout/stderr
|
||||
to `application/vnd.docker.multiplexed-stream` when a multiplexed stdout/stderr
|
||||
stream is sent to client, `application/vnd.docker.raw-stream` otherwise.
|
||||
* `POST /volumes/create` now accepts a new `ClusterVolumeSpec` to create a cluster
|
||||
volume (CNI). This option can only be used if the daemon is a Swarm manager.
|
||||
|
@ -139,7 +143,7 @@ keywords: "API, Docker, rcli, REST, documentation"
|
|||
* Volume information returned by `GET /volumes/{name}`, `GET /volumes` and
|
||||
`GET /system/df` can now contain a `ClusterVolume` if the volume is a cluster
|
||||
volume (requires the daemon to be a Swarm manager).
|
||||
* The `Volume` type, as returned by `Added new `ClusterVolume` fields
|
||||
* The `Volume` type, as returned by `Added new `ClusterVolume` fields
|
||||
* Added a new `PUT /volumes{name}` endpoint to update cluster volumes (CNI).
|
||||
Cluster volumes are only supported if the daemon is a Swarm manager.
|
||||
* `GET /containers/{name}/attach/ws` endpoint now accepts `stdin`, `stdout` and
|
||||
|
@ -355,7 +359,7 @@ keywords: "API, Docker, rcli, REST, documentation"
|
|||
|
||||
[Docker Engine API v1.36](https://docs.docker.com/engine/api/v1.36/) documentation
|
||||
|
||||
* `Get /events` now return `exec_die` event when an exec process terminates.
|
||||
* `Get /events` now return `exec_die` event when an exec process terminates.
|
||||
|
||||
|
||||
## v1.35 API changes
|
||||
|
@ -563,7 +567,7 @@ keywords: "API, Docker, rcli, REST, documentation"
|
|||
* `POST /services/create` and `POST /services/(id or name)/update` now accept the `TTY` parameter, which allocate a pseudo-TTY in container.
|
||||
* `POST /services/create` and `POST /services/(id or name)/update` now accept the `DNSConfig` parameter, which specifies DNS related configurations in resolver configuration file (resolv.conf) through `Nameservers`, `Search`, and `Options`.
|
||||
* `POST /services/create` and `POST /services/(id or name)/update` now support
|
||||
`node.platform.arch` and `node.platform.os` constraints in the services
|
||||
`node.platform.arch` and `node.platform.os` constraints in the services
|
||||
`TaskSpec.Placement.Constraints` field.
|
||||
* `GET /networks/(id or name)` now includes IP and name of all peers nodes for swarm mode overlay networks.
|
||||
* `GET /plugins` list plugins.
|
||||
|
|
|
@ -3,6 +3,7 @@ package container // import "github.com/docker/docker/integration/container"
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -62,3 +63,99 @@ func TestCreateWithCDIDevices(t *testing.T) {
|
|||
outlines := strings.Split(actualStdout.String(), "\n")
|
||||
assert.Assert(t, is.Contains(outlines, "FOO=injected"))
|
||||
}
|
||||
|
||||
func TestCDISpecDirsAreInSystemInfo(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType == "windows") // d.Start fails on Windows with `protocol not available`
|
||||
// TODO: This restriction can be relaxed with https://github.com/moby/moby/pull/46158
|
||||
skip.If(t, testEnv.IsRootless, "the t.TempDir test creates a folder with incorrect permissions for rootless")
|
||||
|
||||
testCases := []struct {
|
||||
description string
|
||||
config map[string]interface{}
|
||||
experimental bool
|
||||
specDirs []string
|
||||
expectedInfoCDISpecDirs []string
|
||||
}{
|
||||
{
|
||||
description: "experimental no spec dirs specified returns default",
|
||||
experimental: true,
|
||||
specDirs: nil,
|
||||
expectedInfoCDISpecDirs: []string{"/etc/cdi", "/var/run/cdi"},
|
||||
},
|
||||
{
|
||||
description: "experimental specified spec dirs are returned",
|
||||
experimental: true,
|
||||
specDirs: []string{"/foo/bar", "/baz/qux"},
|
||||
expectedInfoCDISpecDirs: []string{"/foo/bar", "/baz/qux"},
|
||||
},
|
||||
{
|
||||
description: "experimental empty string as spec dir returns empty slice",
|
||||
experimental: true,
|
||||
specDirs: []string{""},
|
||||
expectedInfoCDISpecDirs: []string{},
|
||||
},
|
||||
{
|
||||
description: "experimental empty config option returns empty slice",
|
||||
experimental: true,
|
||||
config: map[string]interface{}{"cdi-spec-dirs": []string{}},
|
||||
expectedInfoCDISpecDirs: []string{},
|
||||
},
|
||||
{
|
||||
description: "non-experimental no spec dirs specified returns empty slice",
|
||||
experimental: false,
|
||||
specDirs: nil,
|
||||
expectedInfoCDISpecDirs: []string{},
|
||||
},
|
||||
{
|
||||
description: "non-experimental specified spec dirs returns empty slice",
|
||||
experimental: false,
|
||||
specDirs: []string{"/foo/bar", "/baz/qux"},
|
||||
expectedInfoCDISpecDirs: []string{},
|
||||
},
|
||||
{
|
||||
description: "non-experimental empty string as spec dir returns empty slice",
|
||||
experimental: false,
|
||||
specDirs: []string{""},
|
||||
expectedInfoCDISpecDirs: []string{},
|
||||
},
|
||||
{
|
||||
description: "non-experimental empty config option returns empty slice",
|
||||
experimental: false,
|
||||
config: map[string]interface{}{"cdi-spec-dirs": []string{}},
|
||||
expectedInfoCDISpecDirs: []string{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
var opts []daemon.Option
|
||||
if tc.experimental {
|
||||
opts = append(opts, daemon.WithExperimental())
|
||||
}
|
||||
d := daemon.New(t, opts...)
|
||||
|
||||
var args []string
|
||||
for _, specDir := range tc.specDirs {
|
||||
args = append(args, "--cdi-spec-dir="+specDir)
|
||||
}
|
||||
if tc.config != nil {
|
||||
configPath := filepath.Join(t.TempDir(), "daemon.json")
|
||||
|
||||
configFile, err := os.Create(configPath)
|
||||
assert.NilError(t, err)
|
||||
defer configFile.Close()
|
||||
|
||||
err = json.NewEncoder(configFile).Encode(tc.config)
|
||||
assert.NilError(t, err)
|
||||
|
||||
args = append(args, "--config-file="+configPath)
|
||||
}
|
||||
d.Start(t, args...)
|
||||
defer d.Stop(t)
|
||||
|
||||
info := d.Info(t)
|
||||
|
||||
assert.Check(t, is.DeepEqual(tc.expectedInfoCDISpecDirs, info.CDISpecDirs))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue