From 310be5ce6e17b7f600961db12bf01eacd0313152 Mon Sep 17 00:00:00 2001 From: Krisztian Litkey Date: Mon, 6 Feb 2023 20:05:59 +0200 Subject: [PATCH] pkg/nri: update NRI configuration. Update NRI plugin configuration to match that of NRI. Remove option for the eliminated NRI configuration file. Add option to disable connections from externally launched plugins. Add options to override default plugin registration and request timeouts. Signed-off-by: Krisztian Litkey --- go.mod | 2 +- go.sum | 4 +- integration/client/go.sum | 2 +- pkg/nri/config.go | 42 ++++++-- pkg/nri/nri.go | 2 + .../nri/pkg/adaptation/adaptation.go | 55 +++++------ .../containerd/nri/pkg/adaptation/config.go | 95 ------------------- .../containerd/nri/pkg/adaptation/plugin.go | 78 +++++++++++++-- .../containerd/nri/pkg/adaptation/result.go | 8 +- .../containerd/nri/pkg/api/mount.go | 1 - .../containerd/nri/pkg/api/plugin.go | 2 +- .../pkg/runtime-tools/generate/generate.go | 90 +++++++++++++++--- .../containerd/nri/pkg/stub/stub.go | 9 ++ vendor/modules.txt | 4 +- 14 files changed, 224 insertions(+), 170 deletions(-) delete mode 100644 vendor/github.com/containerd/nri/pkg/adaptation/config.go diff --git a/go.mod b/go.mod index 9c16b0c03..a75831948 100644 --- a/go.mod +++ b/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 diff --git a/go.sum b/go.sum index 4ffb2f522..3bbfef241 100644 --- a/go.sum +++ b/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= diff --git a/integration/client/go.sum b/integration/client/go.sum index 349d26fb7..d822bee30 100644 --- a/integration/client/go.sum +++ b/integration/client/go.sum @@ -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= diff --git a/pkg/nri/config.go b/pkg/nri/config.go index 06d31436a..a1cd5b1d2 100644 --- a/pkg/nri/config.go +++ b/pkg/nri/config.go @@ -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) + } +} diff --git a/pkg/nri/nri.go b/pkg/nri/nri.go index 4323872a4..b8a66dcb7 100644 --- a/pkg/nri/nri.go +++ b/pkg/nri/nri.go @@ -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) diff --git a/vendor/github.com/containerd/nri/pkg/adaptation/adaptation.go b/vendor/github.com/containerd/nri/pkg/adaptation/adaptation.go index eefa84940..441f6e1f0 100644 --- a/vendor/github.com/containerd/nri/pkg/adaptation/adaptation.go +++ b/vendor/github.com/containerd/nri/pkg/adaptation/adaptation.go @@ -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) diff --git a/vendor/github.com/containerd/nri/pkg/adaptation/config.go b/vendor/github.com/containerd/nri/pkg/adaptation/config.go deleted file mode 100644 index 049ea7bac..000000000 --- a/vendor/github.com/containerd/nri/pkg/adaptation/config.go +++ /dev/null @@ -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 -} diff --git a/vendor/github.com/containerd/nri/pkg/adaptation/plugin.go b/vendor/github.com/containerd/nri/pkg/adaptation/plugin.go index 4043f244e..c4be402ea 100644 --- a/vendor/github.com/containerd/nri/pkg/adaptation/plugin.go +++ b/vendor/github.com/containerd/nri/pkg/adaptation/plugin.go @@ -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) diff --git a/vendor/github.com/containerd/nri/pkg/adaptation/result.go b/vendor/github.com/containerd/nri/pkg/adaptation/result.go index 7a7967006..a6188ef55 100644 --- a/vendor/github.com/containerd/nri/pkg/adaptation/result.go +++ b/vendor/github.com/containerd/nri/pkg/adaptation/result.go @@ -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 } diff --git a/vendor/github.com/containerd/nri/pkg/api/mount.go b/vendor/github.com/containerd/nri/pkg/api/mount.go index 63fd6956a..e35bf5b36 100644 --- a/vendor/github.com/containerd/nri/pkg/api/mount.go +++ b/vendor/github.com/containerd/nri/pkg/api/mount.go @@ -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) diff --git a/vendor/github.com/containerd/nri/pkg/api/plugin.go b/vendor/github.com/containerd/nri/pkg/api/plugin.go index 16aab20dc..c4fe8fcf9 100644 --- a/vendor/github.com/containerd/nri/pkg/api/plugin.go +++ b/vendor/github.com/containerd/nri/pkg/api/plugin.go @@ -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. diff --git a/vendor/github.com/containerd/nri/pkg/runtime-tools/generate/generate.go b/vendor/github.com/containerd/nri/pkg/runtime-tools/generate/generate.go index 81f4c1e7f..847383eb0 100644 --- a/vendor/github.com/containerd/nri/pkg/runtime-tools/generate/generate.go +++ b/vendor/github.com/containerd/nri/pkg/runtime-tools/generate/generate.go @@ -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 } diff --git a/vendor/github.com/containerd/nri/pkg/stub/stub.go b/vendor/github.com/containerd/nri/pkg/stub/stub.go index 39d6b22e6..470098657 100644 --- a/vendor/github.com/containerd/nri/pkg/stub/stub.go +++ b/vendor/github.com/containerd/nri/pkg/stub/stub.go @@ -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, diff --git a/vendor/modules.txt b/vendor/modules.txt index 470a7769c..810e9ec56 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -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