Merge pull request #8140 from klihub/devel/update-nri-config
pkg/nri: pull in latest NRI, update NRI configuration.
This commit is contained in:
commit
d5425c4c41
31
docs/NRI.md
31
docs/NRI.md
@ -64,23 +64,22 @@ NRI section should look something like this:
|
||||
|
||||
```toml
|
||||
[plugins."io.containerd.nri.v1.nri"]
|
||||
config_file = "/etc/nri/nri.conf"
|
||||
# Enable NRI support in containerd.
|
||||
disable = false
|
||||
# Allow connections from externally launched NRI plugins.
|
||||
disable_connections = false
|
||||
# plugin_config_path is the directory to search for plugin-specific configuration.
|
||||
plugin_config_path = "/etc/nri/conf.d"
|
||||
# plugin_path is the directory to search for plugins to launch on startup.
|
||||
plugin_path = "/opt/nri/plugins"
|
||||
socket_path = "/var/run/nri.sock"
|
||||
# plugin_registration_timeout is the timeout for a plugin to register after connection.
|
||||
plugin_registration_timeout = "5s"
|
||||
# plugin_requst_timeout is the timeout for a plugin to handle an event/request.
|
||||
plugin_request_timeout = "2s"
|
||||
# socket_path is the path of the NRI socket to create for plugins to connect to.
|
||||
socket_path = "/var/run/nri/nri.sock"
|
||||
```
|
||||
|
||||
In addition to this, you need to put a runtime agnostic NRI configuration
|
||||
file in place, to let NRI itself know that it is enabled. You can do this
|
||||
by creating `/etc/nri/nri.conf` with the following content:
|
||||
|
||||
```yaml
|
||||
disableConnections: false
|
||||
```
|
||||
|
||||
This enables externally launched NRI plugins to connect and register
|
||||
themselves.
|
||||
|
||||
There are two ways how an NRI plugin can be started. Plugins can be
|
||||
pre-registered in which case they are automatically started when the NRI
|
||||
adaptation is instantiated (or in our case when containerd is started).
|
||||
@ -90,7 +89,7 @@ Pre-registering a plugin happens by placing a symbolic link to the plugin
|
||||
executable into a well-known NRI-specific directory, `/opt/nri/plugins`
|
||||
by default. A pre-registered plugin is started with a socket pre-connected
|
||||
to NRI. Externally launched plugins connect to a well-known NRI-specific
|
||||
socket, `/var/run/nri.sock` by default, to register themselves. The only
|
||||
socket, `/var/run/nri/nri.sock` by default, to register themselves. The only
|
||||
difference between pre-registered and externally launched plugins is how
|
||||
they get started and connected to NRI. Once a connection is established
|
||||
all plugins are identical.
|
||||
@ -102,7 +101,9 @@ enabled regardless of the built-in NRI defaults. This is convenient for
|
||||
testing as it allows one to connect, disconnect and reconnect plugins at
|
||||
any time.
|
||||
|
||||
For more details about pre-registered and externally launched plugins
|
||||
Note that you can't run two NRI-enabled runtimes on a single node with the
|
||||
same default socket configuration. You need to either disable NRI or change
|
||||
the NRI socket path in one of the runtimes.
|
||||
|
||||
## Testing NRI Support in Containerd
|
||||
|
||||
|
2
go.mod
2
go.mod
@ -17,7 +17,7 @@ require (
|
||||
github.com/containerd/go-cni v1.1.9-0.20230211172349-6603d5bd8941
|
||||
github.com/containerd/go-runc v1.0.0
|
||||
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028
|
||||
github.com/containerd/nri v0.2.1-0.20230131001841-b3cabdec0657
|
||||
github.com/containerd/nri v0.3.0
|
||||
github.com/containerd/ttrpc v1.1.1-0.20230127163717-32fab2374638
|
||||
github.com/containerd/typeurl/v2 v2.1.0
|
||||
github.com/containerd/zfs v1.0.0
|
||||
|
4
go.sum
4
go.sum
@ -263,8 +263,8 @@ github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028/go.mod h1:Lo
|
||||
github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c=
|
||||
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
||||
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
||||
github.com/containerd/nri v0.2.1-0.20230131001841-b3cabdec0657 h1:mUUkDOlFTZXCQupsMlHbQflPVxbj1sT6YOSz/hvT4wE=
|
||||
github.com/containerd/nri v0.2.1-0.20230131001841-b3cabdec0657/go.mod h1:Q2u9Sudol4IkJ6YK0gShznKMxM6Un0Y3O4Wslf5Nerg=
|
||||
github.com/containerd/nri v0.3.0 h1:2ZM4WImye1ypSnE7COjOvPAiLv84kaPILBDvb1tbDK8=
|
||||
github.com/containerd/nri v0.3.0/go.mod h1:Zw9q2lP16sdg0zYybemZ9yTDy8g7fPCIB3KXOGlggXI=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
|
||||
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||
|
@ -520,7 +520,7 @@ github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0Z
|
||||
github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0=
|
||||
github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
|
||||
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
|
||||
github.com/containerd/nri v0.2.1-0.20230131001841-b3cabdec0657/go.mod h1:Q2u9Sudol4IkJ6YK0gShznKMxM6Un0Y3O4Wslf5Nerg=
|
||||
github.com/containerd/nri v0.3.0/go.mod h1:Zw9q2lP16sdg0zYybemZ9yTDy8g7fPCIB3KXOGlggXI=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.12.1/go.mod h1:12VUuCq3qPq4y8yUW+l5w3+oXV3cx2Po3KSe/SmPGqw=
|
||||
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
|
||||
|
@ -17,6 +17,8 @@
|
||||
package nri
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
nri "github.com/containerd/nri/pkg/adaptation"
|
||||
)
|
||||
|
||||
@ -24,35 +26,57 @@ import (
|
||||
type Config struct {
|
||||
// Disable this NRI plugin and containerd NRI functionality altogether.
|
||||
Disable bool `toml:"disable" json:"disable"`
|
||||
// ConfigPath is the path to the NRI configuration file to use.
|
||||
ConfigPath string `toml:"config_file" json:"configFile"`
|
||||
// SocketPath is the path to the NRI socket to create for NRI plugins to connect to.
|
||||
SocketPath string `toml:"socket_path" json:"socketPath"`
|
||||
// PluginPath is the path to search for NRI plugins to launch on startup.
|
||||
PluginPath string `toml:"plugin_path" json:"pluginPath"`
|
||||
// PluginConfigPath is the path to search for plugin-specific configuration.
|
||||
PluginConfigPath string `toml:"plugin_config_path" json:"pluginConfigPath"`
|
||||
// PluginRegistrationTimeout is the timeout for plugin registration.
|
||||
PluginRegistrationTimeout time.Duration `toml:"plugin_registration_timeout" json:"pluginRegistrationTimeout"`
|
||||
// PluginRequestTimeout is the timeout for a plugin to handle a request.
|
||||
PluginRequestTimeout time.Duration `toml:"plugin_request_timeout" json:"pluginRequestTimeout"`
|
||||
// DisableConnections disables connections from externally launched plugins.
|
||||
DisableConnections bool `toml:"disable_connections" json:"disableConnections"`
|
||||
}
|
||||
|
||||
// DefaultConfig returns the default configuration.
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
Disable: true,
|
||||
ConfigPath: nri.DefaultConfigPath,
|
||||
SocketPath: nri.DefaultSocketPath,
|
||||
PluginPath: nri.DefaultPluginPath,
|
||||
Disable: true,
|
||||
SocketPath: nri.DefaultSocketPath,
|
||||
PluginPath: nri.DefaultPluginPath,
|
||||
PluginConfigPath: nri.DefaultPluginConfigPath,
|
||||
|
||||
PluginRegistrationTimeout: nri.DefaultPluginRegistrationTimeout,
|
||||
PluginRequestTimeout: nri.DefaultPluginRequestTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// toOptions returns NRI options for this configuration.
|
||||
func (c *Config) toOptions() []nri.Option {
|
||||
opts := []nri.Option{}
|
||||
if c.ConfigPath != "" {
|
||||
opts = append(opts, nri.WithConfigPath(c.ConfigPath))
|
||||
}
|
||||
if c.SocketPath != "" {
|
||||
opts = append(opts, nri.WithSocketPath(c.SocketPath))
|
||||
}
|
||||
if c.PluginPath != "" {
|
||||
opts = append(opts, nri.WithPluginPath(c.PluginPath))
|
||||
}
|
||||
if c.PluginConfigPath != "" {
|
||||
opts = append(opts, nri.WithPluginConfigPath(c.PluginConfigPath))
|
||||
}
|
||||
if c.DisableConnections {
|
||||
opts = append(opts, nri.WithDisabledExternalConnections())
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
// ConfigureTimeouts sets timeout options for NRI.
|
||||
func (c *Config) ConfigureTimeouts() {
|
||||
if c.PluginRegistrationTimeout != 0 {
|
||||
nri.SetPluginRegistrationTimeout(c.PluginRegistrationTimeout)
|
||||
}
|
||||
if c.PluginRequestTimeout != 0 {
|
||||
nri.SetPluginRequestTimeout(c.PluginRequestTimeout)
|
||||
}
|
||||
}
|
||||
|
@ -123,6 +123,8 @@ func New(cfg *Config) (API, error) {
|
||||
err error
|
||||
)
|
||||
|
||||
cfg.ConfigureTimeouts()
|
||||
|
||||
l.nri, err = nri.New(name, version, syncFn, updateFn, opts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize NRI interface: %w", err)
|
||||
|
55
vendor/github.com/containerd/nri/pkg/adaptation/adaptation.go
generated
vendored
55
vendor/github.com/containerd/nri/pkg/adaptation/adaptation.go
generated
vendored
@ -32,12 +32,12 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultConfigPath is the default path to the NRI configuration.
|
||||
DefaultConfigPath = "/etc/nri/nri.conf"
|
||||
// DefaultPluginPath is the default path to search for NRI plugins.
|
||||
DefaultPluginPath = "/opt/nri/plugins"
|
||||
// DefaultSocketPath is the default socket path for external plugins.
|
||||
DefaultSocketPath = api.DefaultSocketPath
|
||||
// PluginConfigDir is the drop-in directory for NRI-launched plugin configuration.
|
||||
DefaultPluginConfigPath = "/etc/nri/conf.d"
|
||||
)
|
||||
|
||||
// SyncFn is a container runtime function for state synchronization.
|
||||
@ -54,12 +54,12 @@ type Adaptation struct {
|
||||
sync.Mutex
|
||||
name string
|
||||
version string
|
||||
configPath string
|
||||
dropinPath string
|
||||
pluginPath string
|
||||
socketPath string
|
||||
dontListen bool
|
||||
syncFn SyncFn
|
||||
updateFn UpdateFn
|
||||
cfg *Config
|
||||
listener net.Listener
|
||||
plugins []*plugin
|
||||
}
|
||||
@ -72,23 +72,6 @@ var (
|
||||
// Option to apply to the NRI runtime.
|
||||
type Option func(*Adaptation) error
|
||||
|
||||
// WithConfigPath returns an option to override the default NRI config path.
|
||||
func WithConfigPath(path string) Option {
|
||||
return func(r *Adaptation) error {
|
||||
r.configPath = path
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithConfig returns an option to provide a pre-parsed NRI configuration.
|
||||
func WithConfig(cfg *Config) Option {
|
||||
return func(r *Adaptation) error {
|
||||
r.cfg = cfg
|
||||
r.configPath = cfg.path
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPluginPath returns an option to override the default NRI plugin path.
|
||||
func WithPluginPath(path string) Option {
|
||||
return func(r *Adaptation) error {
|
||||
@ -97,6 +80,14 @@ func WithPluginPath(path string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithPluginConfigPath returns an option to override the default NRI plugin config path.
|
||||
func WithPluginConfigPath(path string) Option {
|
||||
return func(r *Adaptation) error {
|
||||
r.dropinPath = path
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithSocketPath returns an option to override the default NRI socket path.
|
||||
func WithSocketPath(path string) Option {
|
||||
return func(r *Adaptation) error {
|
||||
@ -105,6 +96,14 @@ func WithSocketPath(path string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithDisabledExternalConnections returns an options to disable accepting plugin connections.
|
||||
func WithDisabledExternalConnections() Option {
|
||||
return func(r *Adaptation) error {
|
||||
r.dontListen = true
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// New creates a new NRI Runtime.
|
||||
func New(name, version string, syncFn SyncFn, updateFn UpdateFn, opts ...Option) (*Adaptation, error) {
|
||||
var err error
|
||||
@ -121,8 +120,8 @@ func New(name, version string, syncFn SyncFn, updateFn UpdateFn, opts ...Option)
|
||||
version: version,
|
||||
syncFn: syncFn,
|
||||
updateFn: updateFn,
|
||||
configPath: DefaultConfigPath,
|
||||
pluginPath: DefaultPluginPath,
|
||||
dropinPath: DefaultPluginConfigPath,
|
||||
socketPath: DefaultSocketPath,
|
||||
}
|
||||
|
||||
@ -132,12 +131,6 @@ func New(name, version string, syncFn SyncFn, updateFn UpdateFn, opts ...Option)
|
||||
}
|
||||
}
|
||||
|
||||
if r.cfg == nil {
|
||||
if r.cfg, err = ReadConfig(r.configPath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof(noCtx, "runtime interface created")
|
||||
|
||||
return r, nil
|
||||
@ -374,13 +367,13 @@ func (r *Adaptation) removeClosedPlugins() {
|
||||
}
|
||||
|
||||
func (r *Adaptation) startListener() error {
|
||||
if r.cfg.DisableConnections {
|
||||
if r.dontListen {
|
||||
log.Infof(noCtx, "connection from external plugins disabled")
|
||||
return nil
|
||||
}
|
||||
|
||||
os.Remove(r.socketPath)
|
||||
if err := os.MkdirAll(filepath.Dir(r.socketPath), 0755); err != nil {
|
||||
if err := os.MkdirAll(filepath.Dir(r.socketPath), 0700); err != nil {
|
||||
return fmt.Errorf("failed to create socket %q: %w", r.socketPath, err)
|
||||
}
|
||||
|
||||
@ -481,7 +474,7 @@ func (r *Adaptation) discoverPlugins() ([]string, []string, []string, error) {
|
||||
r.pluginPath, err)
|
||||
}
|
||||
|
||||
cfg, err := r.cfg.getPluginConfig(idx, base)
|
||||
cfg, err := r.getPluginConfig(idx, base)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("failed to discover plugins in %s: %w",
|
||||
r.pluginPath, err)
|
||||
|
95
vendor/github.com/containerd/nri/pkg/adaptation/config.go
generated
vendored
95
vendor/github.com/containerd/nri/pkg/adaptation/config.go
generated
vendored
@ -1,95 +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 adaptation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
const (
|
||||
// PluginConfigSubdir is the drop-in directory for plugin configuration.
|
||||
PluginConfigSubdir = "conf.d"
|
||||
)
|
||||
|
||||
// Config is the runtime configuration for NRI.
|
||||
type Config struct {
|
||||
// DisableConnections disables plugin-initiated connections.
|
||||
DisableConnections bool `json:"disableConnections"`
|
||||
|
||||
path string
|
||||
dropIn string
|
||||
}
|
||||
|
||||
// DefaultConfig returns the default NRI configuration for a given path.
|
||||
// This configuration should be identical to what ReadConfig would return
|
||||
// for an empty file at the given location. If the given path is empty,
|
||||
// DefaultConfigPath is used instead.
|
||||
func DefaultConfig(path string) *Config {
|
||||
if path == "" {
|
||||
path = DefaultConfigPath
|
||||
}
|
||||
return &Config{
|
||||
path: path,
|
||||
dropIn: filepath.Join(filepath.Dir(path), PluginConfigSubdir),
|
||||
}
|
||||
}
|
||||
|
||||
// ReadConfig reads the NRI runtime configuration from a file.
|
||||
func ReadConfig(path string) (*Config, error) {
|
||||
buf, err := os.ReadFile(path)
|
||||
if os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read file %q: %w", path, err)
|
||||
}
|
||||
|
||||
cfg := &Config{}
|
||||
err = yaml.UnmarshalStrict(buf, cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse file %q: %w", path, err)
|
||||
}
|
||||
|
||||
cfg.path = path
|
||||
cfg.dropIn = filepath.Join(filepath.Dir(path), PluginConfigSubdir)
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (cfg *Config) getPluginConfig(id, base string) (string, error) {
|
||||
name := id + "-" + base
|
||||
dropIns := []string{
|
||||
filepath.Join(cfg.dropIn, name+".conf"),
|
||||
filepath.Join(cfg.dropIn, base+".conf"),
|
||||
}
|
||||
|
||||
for _, path := range dropIns {
|
||||
buf, err := os.ReadFile(path)
|
||||
if err == nil {
|
||||
return string(buf), nil
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return "", fmt.Errorf("failed to read configuration for plugin %q: %w", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
78
vendor/github.com/containerd/nri/pkg/adaptation/plugin.go
generated
vendored
78
vendor/github.com/containerd/nri/pkg/adaptation/plugin.go
generated
vendored
@ -36,8 +36,16 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
pluginRegistrationTimeout = 2 * time.Second
|
||||
pluginRequestTimeout = 2 * time.Second
|
||||
// DefaultPluginRegistrationTimeout is the default timeout for plugin registration.
|
||||
DefaultPluginRegistrationTimeout = 5 * time.Second
|
||||
// DefaultPluginRequestTimeout is the default timeout for plugins to handle a request.
|
||||
DefaultPluginRequestTimeout = 2 * time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
pluginRegistrationTimeout = DefaultPluginRegistrationTimeout
|
||||
pluginRequestTimeout = DefaultPluginRequestTimeout
|
||||
timeoutCfgLock sync.RWMutex
|
||||
)
|
||||
|
||||
type plugin struct {
|
||||
@ -59,6 +67,32 @@ type plugin struct {
|
||||
r *Adaptation
|
||||
}
|
||||
|
||||
// SetPluginRegistrationTimeout sets the timeout for plugin registration.
|
||||
func SetPluginRegistrationTimeout(t time.Duration) {
|
||||
timeoutCfgLock.Lock()
|
||||
defer timeoutCfgLock.Unlock()
|
||||
pluginRegistrationTimeout = t
|
||||
}
|
||||
|
||||
func getPluginRegistrationTimeout() time.Duration {
|
||||
timeoutCfgLock.RLock()
|
||||
defer timeoutCfgLock.RUnlock()
|
||||
return pluginRegistrationTimeout
|
||||
}
|
||||
|
||||
// SetPluginRequestTimeout sets the timeout for plugins to handle a request.
|
||||
func SetPluginRequestTimeout(t time.Duration) {
|
||||
timeoutCfgLock.Lock()
|
||||
defer timeoutCfgLock.Unlock()
|
||||
pluginRequestTimeout = t
|
||||
}
|
||||
|
||||
func getPluginRequestTimeout() time.Duration {
|
||||
timeoutCfgLock.RLock()
|
||||
defer timeoutCfgLock.RUnlock()
|
||||
return pluginRequestTimeout
|
||||
}
|
||||
|
||||
// Launch a pre-installed plugin with a pre-connected socketpair.
|
||||
func (r *Adaptation) newLaunchedPlugin(dir, idx, base, cfg string) (p *plugin, retErr error) {
|
||||
name := idx + "-" + base
|
||||
@ -125,6 +159,27 @@ func (r *Adaptation) newExternalPlugin(conn stdnet.Conn) (p *plugin, retErr erro
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// Get plugin-specific configuration for an NRI-launched plugin.
|
||||
func (r *Adaptation) getPluginConfig(id, base string) (string, error) {
|
||||
name := id + "-" + base
|
||||
dropIns := []string{
|
||||
filepath.Join(r.dropinPath, name+".conf"),
|
||||
filepath.Join(r.dropinPath, base+".conf"),
|
||||
}
|
||||
|
||||
for _, path := range dropIns {
|
||||
buf, err := os.ReadFile(path)
|
||||
if err == nil {
|
||||
return string(buf), nil
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return "", fmt.Errorf("failed to read configuration for plugin %q: %w", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Check if the plugin is external (was not launched by us).
|
||||
func (p *plugin) isExternal() bool {
|
||||
return p.cmd == nil
|
||||
@ -189,7 +244,10 @@ func (p *plugin) connect(conn stdnet.Conn) (retErr error) {
|
||||
|
||||
// Start Runtime service, wait for plugin to register, then configure it.
|
||||
func (p *plugin) start(name, version string) error {
|
||||
var err error
|
||||
var (
|
||||
err error
|
||||
timeout = getPluginRegistrationTimeout()
|
||||
)
|
||||
|
||||
go func() {
|
||||
err := p.rpcs.Serve(context.Background(), p.rpcl)
|
||||
@ -208,7 +266,7 @@ func (p *plugin) start(name, version string) error {
|
||||
}
|
||||
case <-p.closeC:
|
||||
return fmt.Errorf("failed to register plugin, connection closed")
|
||||
case <-time.After(pluginRegistrationTimeout):
|
||||
case <-time.After(timeout):
|
||||
p.close()
|
||||
p.stop()
|
||||
return errors.New("plugin registration timed out")
|
||||
@ -318,7 +376,7 @@ func (p *plugin) UpdateContainers(ctx context.Context, req *UpdateContainersRequ
|
||||
|
||||
// configure the plugin and subscribe it for the events it requested.
|
||||
func (p *plugin) configure(ctx context.Context, name, version, config string) error {
|
||||
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||
ctx, cancel := context.WithTimeout(ctx, getPluginRequestTimeout())
|
||||
defer cancel()
|
||||
|
||||
rpl, err := p.stub.Configure(ctx, &ConfigureRequest{
|
||||
@ -347,7 +405,7 @@ func (p *plugin) configure(ctx context.Context, name, version, config string) er
|
||||
func (p *plugin) synchronize(ctx context.Context, pods []*PodSandbox, containers []*Container) ([]*ContainerUpdate, error) {
|
||||
log.Infof(ctx, "synchronizing plugin %s", p.name())
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||
ctx, cancel := context.WithTimeout(ctx, getPluginRequestTimeout())
|
||||
defer cancel()
|
||||
|
||||
req := &SynchronizeRequest{
|
||||
@ -368,7 +426,7 @@ func (p *plugin) createContainer(ctx context.Context, req *CreateContainerReques
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||
ctx, cancel := context.WithTimeout(ctx, getPluginRequestTimeout())
|
||||
defer cancel()
|
||||
|
||||
rpl, err := p.stub.CreateContainer(ctx, req)
|
||||
@ -391,7 +449,7 @@ func (p *plugin) updateContainer(ctx context.Context, req *UpdateContainerReques
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||
ctx, cancel := context.WithTimeout(ctx, getPluginRequestTimeout())
|
||||
defer cancel()
|
||||
|
||||
rpl, err := p.stub.UpdateContainer(ctx, req)
|
||||
@ -414,7 +472,7 @@ func (p *plugin) stopContainer(ctx context.Context, req *StopContainerRequest) (
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||
ctx, cancel := context.WithTimeout(ctx, getPluginRequestTimeout())
|
||||
defer cancel()
|
||||
|
||||
rpl, err := p.stub.StopContainer(ctx, req)
|
||||
@ -437,7 +495,7 @@ func (p *plugin) StateChange(ctx context.Context, evt *StateChangeEvent) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||
ctx, cancel := context.WithTimeout(ctx, getPluginRequestTimeout())
|
||||
defer cancel()
|
||||
|
||||
_, err := p.stub.StateChange(ctx, evt)
|
||||
|
8
vendor/github.com/containerd/nri/pkg/adaptation/result.go
generated
vendored
8
vendor/github.com/containerd/nri/pkg/adaptation/result.go
generated
vendored
@ -316,9 +316,7 @@ func (r *result) adjustMounts(mounts []*Mount, plugin string) error {
|
||||
}
|
||||
|
||||
// finally, apply additions/modifications to plugin container creation request
|
||||
for _, m := range add {
|
||||
create.Container.Mounts = append(r.reply.adjust.Mounts, m)
|
||||
}
|
||||
create.Container.Mounts = append(create.Container.Mounts, add...)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -376,9 +374,7 @@ func (r *result) adjustDevices(devices []*LinuxDevice, plugin string) error {
|
||||
}
|
||||
|
||||
// finally, apply additions/modifications to plugin container creation request
|
||||
for _, d := range add {
|
||||
create.Container.Linux.Devices = append(r.reply.adjust.Linux.Devices, d)
|
||||
}
|
||||
create.Container.Linux.Devices = append(create.Container.Linux.Devices, add...)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
1
vendor/github.com/containerd/nri/pkg/api/mount.go
generated
vendored
1
vendor/github.com/containerd/nri/pkg/api/mount.go
generated
vendored
@ -47,7 +47,6 @@ func (m *Mount) ToOCI(propagationQuery *string) rspec.Mount {
|
||||
Destination: m.Destination,
|
||||
Type: m.Type,
|
||||
Source: m.Source,
|
||||
Options: []string{},
|
||||
}
|
||||
for _, opt := range m.Options {
|
||||
o.Options = append(o.Options, opt)
|
||||
|
2
vendor/github.com/containerd/nri/pkg/api/plugin.go
generated
vendored
2
vendor/github.com/containerd/nri/pkg/api/plugin.go
generated
vendored
@ -23,7 +23,7 @@ import (
|
||||
|
||||
const (
|
||||
// DefaultSocketPath is the default socket path for external plugins.
|
||||
DefaultSocketPath = "/var/run/nri.sock"
|
||||
DefaultSocketPath = "/var/run/nri/nri.sock"
|
||||
// PluginSocketEnvVar is used to inform plugins about pre-connected sockets.
|
||||
PluginSocketEnvVar = "NRI_PLUGIN_SOCKET"
|
||||
// PluginNameEnvVar is used to inform NRI-launched plugins about their name.
|
||||
|
90
vendor/github.com/containerd/nri/pkg/runtime-tools/generate/generate.go
generated
vendored
90
vendor/github.com/containerd/nri/pkg/runtime-tools/generate/generate.go
generated
vendored
@ -18,6 +18,9 @@ package generate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
@ -212,13 +215,27 @@ func (g *Generator) AdjustResources(r *nri.LinuxResources) error {
|
||||
g.initConfigLinux()
|
||||
|
||||
if r.Cpu != nil {
|
||||
g.SetLinuxResourcesCPUPeriod(r.Cpu.GetPeriod().GetValue())
|
||||
g.SetLinuxResourcesCPUQuota(r.Cpu.GetQuota().GetValue())
|
||||
g.SetLinuxResourcesCPUShares(r.Cpu.GetShares().GetValue())
|
||||
g.SetLinuxResourcesCPUCpus(r.Cpu.GetCpus())
|
||||
g.SetLinuxResourcesCPUMems(r.Cpu.GetMems())
|
||||
g.SetLinuxResourcesCPURealtimeRuntime(r.Cpu.GetRealtimeRuntime().GetValue())
|
||||
g.SetLinuxResourcesCPURealtimePeriod(r.Cpu.GetRealtimePeriod().GetValue())
|
||||
if r.Cpu.Period != nil {
|
||||
g.SetLinuxResourcesCPUPeriod(r.Cpu.GetPeriod().GetValue())
|
||||
}
|
||||
if r.Cpu.Quota != nil {
|
||||
g.SetLinuxResourcesCPUQuota(r.Cpu.GetQuota().GetValue())
|
||||
}
|
||||
if r.Cpu.Shares != nil {
|
||||
g.SetLinuxResourcesCPUShares(r.Cpu.GetShares().GetValue())
|
||||
}
|
||||
if r.Cpu.Cpus != "" {
|
||||
g.SetLinuxResourcesCPUCpus(r.Cpu.GetCpus())
|
||||
}
|
||||
if r.Cpu.Mems != "" {
|
||||
g.SetLinuxResourcesCPUMems(r.Cpu.GetMems())
|
||||
}
|
||||
if r.Cpu.RealtimeRuntime != nil {
|
||||
g.SetLinuxResourcesCPURealtimeRuntime(r.Cpu.GetRealtimeRuntime().GetValue())
|
||||
}
|
||||
if r.Cpu.RealtimePeriod != nil {
|
||||
g.SetLinuxResourcesCPURealtimePeriod(r.Cpu.GetRealtimePeriod().GetValue())
|
||||
}
|
||||
}
|
||||
if r.Memory != nil {
|
||||
if l := r.Memory.GetLimit().GetValue(); l != 0 {
|
||||
@ -305,19 +322,20 @@ func (g *Generator) AdjustDevices(devices []*nri.LinuxDevice) {
|
||||
|
||||
// AdjustMounts adjusts the mounts in the OCI Spec.
|
||||
func (g *Generator) AdjustMounts(mounts []*nri.Mount) error {
|
||||
var (
|
||||
propagation string
|
||||
)
|
||||
if len(mounts) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
propagation := ""
|
||||
for _, m := range mounts {
|
||||
if destination, marked := m.IsMarkedForRemoval(); marked {
|
||||
g.RemoveMount(destination)
|
||||
continue
|
||||
}
|
||||
|
||||
g.RemoveMount(m.Destination)
|
||||
|
||||
mnt := m.ToOCI(&propagation)
|
||||
|
||||
switch propagation {
|
||||
case "rprivate":
|
||||
case "rshared":
|
||||
@ -340,10 +358,60 @@ func (g *Generator) AdjustMounts(mounts []*nri.Mount) error {
|
||||
}
|
||||
g.AddMount(mnt)
|
||||
}
|
||||
g.sortMounts()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// sortMounts sorts the mounts in the generated OCI Spec.
|
||||
func (g *Generator) sortMounts() {
|
||||
mounts := g.Generator.Mounts()
|
||||
g.Generator.ClearMounts()
|
||||
sort.Sort(orderedMounts(mounts))
|
||||
|
||||
// TODO(klihub): This is now a bit ugly maybe we should introduce a
|
||||
// SetMounts([]rspec.Mount) to runtime-tools/generate.Generator. That
|
||||
// could also take care of properly sorting the mount slice.
|
||||
|
||||
g.Generator.Config.Mounts = mounts
|
||||
}
|
||||
|
||||
// orderedMounts defines how to sort an OCI Spec Mount slice.
|
||||
// This is the almost the same implementation sa used by CRI-O and Docker,
|
||||
// with a minor tweak for stable sorting order (easier to test):
|
||||
//
|
||||
// https://github.com/moby/moby/blob/17.05.x/daemon/volumes.go#L26
|
||||
type orderedMounts []rspec.Mount
|
||||
|
||||
// Len returns the number of mounts. Used in sorting.
|
||||
func (m orderedMounts) Len() int {
|
||||
return len(m)
|
||||
}
|
||||
|
||||
// Less returns true if the number of parts (a/b/c would be 3 parts) in the
|
||||
// mount indexed by parameter 1 is less than that of the mount indexed by
|
||||
// parameter 2. Used in sorting.
|
||||
func (m orderedMounts) Less(i, j int) bool {
|
||||
ip, jp := m.parts(i), m.parts(j)
|
||||
if ip < jp {
|
||||
return true
|
||||
}
|
||||
if jp < ip {
|
||||
return false
|
||||
}
|
||||
return m[i].Destination < m[j].Destination
|
||||
}
|
||||
|
||||
// Swap swaps two items in an array of mounts. Used in sorting
|
||||
func (m orderedMounts) Swap(i, j int) {
|
||||
m[i], m[j] = m[j], m[i]
|
||||
}
|
||||
|
||||
// parts returns the number of parts in the destination of a mount. Used in sorting.
|
||||
func (m orderedMounts) parts(i int) int {
|
||||
return strings.Count(filepath.Clean(m[i].Destination), string(os.PathSeparator))
|
||||
}
|
||||
|
||||
func nopFilter(m map[string]string) (map[string]string, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
9
vendor/github.com/containerd/nri/pkg/stub/stub.go
generated
vendored
9
vendor/github.com/containerd/nri/pkg/stub/stub.go
generated
vendored
@ -18,6 +18,7 @@ package stub
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
stdnet "net"
|
||||
"os"
|
||||
@ -160,6 +161,10 @@ var (
|
||||
|
||||
// Used instead of a nil Context in logging.
|
||||
noCtx = context.TODO()
|
||||
|
||||
// ErrNoService indicates that the stub has no runtime service/connection,
|
||||
// for instance by UpdateContainers on a stub which has not been started.
|
||||
ErrNoService = errors.New("stub: no service/connection")
|
||||
)
|
||||
|
||||
// EventMask holds a mask of events for plugin subscription.
|
||||
@ -515,6 +520,10 @@ func (stub *stub) connClosed() {
|
||||
|
||||
// UpdateContainers requests unsolicited updates to containers.
|
||||
func (stub *stub) UpdateContainers(update []*api.ContainerUpdate) ([]*api.ContainerUpdate, error) {
|
||||
if stub.runtime == nil {
|
||||
return nil, ErrNoService
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
req := &api.UpdateContainersRequest{
|
||||
Update: update,
|
||||
|
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@ -125,8 +125,8 @@ github.com/containerd/go-runc
|
||||
## explicit; go 1.16
|
||||
github.com/containerd/imgcrypt
|
||||
github.com/containerd/imgcrypt/images/encryption
|
||||
# github.com/containerd/nri v0.2.1-0.20230131001841-b3cabdec0657
|
||||
## explicit; go 1.18
|
||||
# github.com/containerd/nri v0.3.0
|
||||
## explicit; go 1.19
|
||||
github.com/containerd/nri
|
||||
github.com/containerd/nri/pkg/adaptation
|
||||
github.com/containerd/nri/pkg/api
|
||||
|
Loading…
Reference in New Issue
Block a user