Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
# [global .gitignore](https://help.github.com/articles/ignoring-files).

build/
pkg/version/info/*
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ build-proto-dockerized:
-f hack/Dockerfile.buildproto .
$(Q)tar xf artifacts.tgz && rm -f artifacts.tgz

build-plugins: $(PLUGINS)
build-plugins: go-generate $(PLUGINS)

build-check:
$(Q)$(GO_BUILD) -v $(GO_MODULES)
Expand All @@ -106,6 +106,9 @@ mod-tidy:
$(Q)$(GO_CMD) mod tidy
$(Q)./scripts/go-mod-tidy

go-generate:
$(Q)$(GO_CMD) generate ./...

#
# clean targets
#
Expand Down Expand Up @@ -138,7 +141,7 @@ $(BIN_PATH)/wasm build/bin/wasm: FORCE
# test targets
#

test-gopkgs: ginkgo-tests test-ulimits test-rdt test-hook-injector
test-gopkgs: go-generate ginkgo-tests test-ulimits test-rdt test-hook-injector

SKIPPED_PKGS="ulimit-adjuster,device-injector,rdt,hook-injector"

Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,9 @@ NRI, containerd and CRI-O versions each property was first available in.
| Linux PID limit | v0.7.0 | v2.0.0 | v1.32.0 |
| Linux OOM score adjustment | v0.7.0 | v2.0.0 | v1.32.0 |
| CDI devices | v0.10.0 | unimplemented | unimplemented |
| Linux security profile | v0.10.0 | v2.2.0 | unimplemented |
| Linux security profile | v0.10.0 | v2.2.1 | unimplemented |
| Linux seccomp policy | v0.10.0 | unimplemented | unimplemented |
| Linux I/O priority | v0.10.0 | v2.2.1 | v1.35.0 |
| Linux security profile | v0.10.0 | v2.2.1 | unimplemented |
| Linux scheduling policy | v0.11.0 | v2.2.1 | v1.35.0 |
| Linux network devices | v0.11.0 | v2.2.1 | v1.35.0 |
| Linux RDT CLOS | v0.11.0 | v2.2.1 | v1.35.0 |
Expand Down Expand Up @@ -267,7 +266,7 @@ property was first available in.
| POSIX rlimits | v0.4.0 | v1.7.7 | v1.29.0 |
| Linux PID limits | v0.7.0 | v2.0.0 | v1.32.0 |
| Linux OOM score adjustment | v0.7.0 | v2.0.0 | v1.32.0 |
| CDI device injection | v0.7.0 | v2.0.0 | v1.32.0 |
| CDI device injection | v0.7.0 | v2.1.0 | v1.34.0 |
| Linux namespaces | v0.10.0 | v2.2.0 | v1.34.0 |
| Linux seccomp policy | v0.10.0 | v2.2.0 | v1.34.0 |
| Linux I/O priority | v0.10.0 | v2.2.0 | v1.34.0 |
Expand Down
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ require (
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.4
github.com/tetratelabs/wazero v1.11.0
golang.org/x/sys v0.38.0
golang.org/x/mod v0.32.0
golang.org/x/sys v0.39.0
google.golang.org/grpc v1.57.1
google.golang.org/protobuf v1.34.1
gopkg.in/yaml.v3 v3.0.1
Expand All @@ -33,9 +34,9 @@ require (
github.com/planetscale/vtprotobuf v0.4.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/text v0.23.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
golang.org/x/net v0.48.0 // indirect
golang.org/x/text v0.32.0 // indirect
golang.org/x/tools v0.40.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)
Expand Down
18 changes: 10 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,17 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230731190214-cbb8c96f2d6d h1:pgIUhmqwKOUlnKna4r6amKdUngdL8DrkpFeV8+VBElY=
Expand Down
44 changes: 28 additions & 16 deletions pkg/adaptation/adaptation.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/containerd/nri/pkg/adaptation/builtin"
"github.com/containerd/nri/pkg/api"
"github.com/containerd/nri/pkg/log"
nriver "github.com/containerd/nri/pkg/version"
validator "github.com/containerd/nri/plugins/default-validator/builtin"
"github.com/containerd/ttrpc"

Expand Down Expand Up @@ -57,22 +58,24 @@ type UpdateFn func(context.Context, []*ContainerUpdate) ([]*ContainerUpdate, err
// Adaptation is the NRI abstraction for container runtime NRI adaptation/integration.
type Adaptation struct {
sync.Mutex
name string
version string
dropinPath string
pluginPath string
socketPath string
dontListen bool
syncFn SyncFn
updateFn UpdateFn
clientOpts []ttrpc.ClientOpts
serverOpts []ttrpc.ServerOpt
listener net.Listener
plugins []*plugin
validators []*plugin
builtin []*builtin.BuiltinPlugin
syncLock sync.RWMutex
wasmService *api.PluginPlugin
name string
version string
nriVersion string
dropinPath string
pluginPath string
socketPath string
dontListen bool
syncFn SyncFn
updateFn UpdateFn
clientOpts []ttrpc.ClientOpts
serverOpts []ttrpc.ServerOpt
listener net.Listener
plugins []*plugin
validators []*plugin
builtin []*builtin.BuiltinPlugin
syncLock sync.RWMutex
wasmService *api.PluginPlugin
capabilities CapabilityMask
}

var (
Expand Down Expand Up @@ -145,6 +148,14 @@ func WithDefaultValidator(cfg *validator.DefaultValidatorConfig) Option {
}
}

// WithSupportedCapabilities sets up the supported capabilities reported to plugins.
func WithSupportedCapabilities(capabilities CapabilityMask) Option {
return func(r *Adaptation) error {
r.capabilities = capabilities.Clone()
return nil
}
}

// New creates a new NRI Runtime.
func New(name, version string, syncFn SyncFn, updateFn UpdateFn, opts ...Option) (*Adaptation, error) {
var err error
Expand All @@ -167,6 +178,7 @@ func New(name, version string, syncFn SyncFn, updateFn UpdateFn, opts ...Option)
r := &Adaptation{
name: name,
version: version,
nriVersion: nriver.GetFromBuildInfo(),
syncFn: syncFn,
updateFn: updateFn,
pluginPath: DefaultPluginPath,
Expand Down
167 changes: 167 additions & 0 deletions pkg/adaptation/adaptation_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
nri "github.com/containerd/nri/pkg/adaptation"
"github.com/containerd/nri/pkg/api"
"github.com/containerd/nri/pkg/plugin"
"github.com/containerd/nri/pkg/stub"
validator "github.com/containerd/nri/plugins/default-validator/builtin"
)

Expand Down Expand Up @@ -3292,6 +3293,172 @@ var _ = Describe("Plugin configuration request", func() {
})
})

var _ = Describe("NRI version exchange", func() {
var (
s = &Suite{}
)

AfterEach(func() {
s.Cleanup()
})

BeforeEach(func() {
s.Prepare(&mockRuntime{}, &mockPlugin{idx: "00", name: "test"})
})

It("should pass runtime version information to plugins", func() {
var (
runtimeName = "test-runtime"
runtimeVersion = "1.2.3"
nriVersion = "v9.8.7"
)

s.runtime.name = runtimeName
s.runtime.version = runtimeVersion
s.runtime.options = append(s.runtime.options, nri.WithTestNRIVersion(nriVersion))

s.Startup()

Expect(s.plugins[0].RuntimeName()).To(Equal(runtimeName))
Expect(s.plugins[0].RuntimeVersion()).To(Equal(runtimeVersion))
Expect(s.plugins[0].RuntimeNRIVersion()).To(Equal(nriVersion))
})

})

var _ = Describe("Advertised NRI capabilities", func() {
var (
s = &Suite{}
)

AfterEach(func() {
s.Cleanup()
})

BeforeEach(func() {
s.Prepare(&mockRuntime{})
})

It("should be passed to plugins", func() {
var (
runtimeName = "test-runtime"
runtimeVersion = "1.2.3"
supportedCapabilities = []api.Capability{
api.Capability_ADJUST_POSIX_RLIMITS,
api.Capability_INPUT_POSIX_RLIMITS,
api.Capability_ADJUST_LINUX_IO_PRIORITY,
api.Capability_INPUT_LINUX_IO_PRIORITY,
api.Capability_INPUT_IP_ADDRESSES,
api.Capability_ADJUST_LINUX_CONTAINER_ARGS,
}
)

s.runtime.name = runtimeName
s.runtime.version = runtimeVersion
s.runtime.options = append(s.runtime.options,
nri.WithSupportedCapabilities(
api.NewCapabilityMask(supportedCapabilities...),
),
)

s.Startup()
s.StartPlugins(&mockPlugin{idx: "00", name: "test"})
s.WaitForPluginsToSync(s.plugin("00-test"))

Expect(s.plugins[0].RuntimeName()).To(Equal(runtimeName))
Expect(s.plugins[0].RuntimeVersion()).To(Equal(runtimeVersion))
Expect(s.plugins[0].RuntimeCapabilities()).To(Equal(
api.NewCapabilityMask(supportedCapabilities...),
))
})

It("should allow startup of plugins with satisfied capability requirements", func() {
var (
runtimeName = "test-runtime"
runtimeVersion = "1.2.3"
supportedCapabilities = []api.Capability{
api.Capability_ADJUST_POSIX_RLIMITS,
api.Capability_INPUT_POSIX_RLIMITS,
api.Capability_ADJUST_LINUX_IO_PRIORITY,
api.Capability_INPUT_LINUX_IO_PRIORITY,
api.Capability_INPUT_IP_ADDRESSES,
api.Capability_ADJUST_LINUX_CONTAINER_ARGS,
}
subsetCapabilities = []api.Capability{
api.Capability_INPUT_POSIX_RLIMITS,
api.Capability_INPUT_IP_ADDRESSES,
api.Capability_ADJUST_LINUX_CONTAINER_ARGS,
}
plugins = []*mockPlugin{
{
idx: "00",
name: "test",
options: []stub.Option{
stub.WithRequiredCapabilities(supportedCapabilities...),
},
},
{
idx: "01",
name: "test",
options: []stub.Option{
stub.WithRequiredCapabilities(subsetCapabilities...),
},
},
}
)

s.runtime.name = runtimeName
s.runtime.version = runtimeVersion
s.runtime.options = append(s.runtime.options,
nri.WithSupportedCapabilities(
api.NewCapabilityMask(supportedCapabilities...),
),
)

s.Startup()
s.StartPlugins(plugins...)
s.WaitForPluginsToSync(plugins[0], plugins[1])
})

It("should prevent startup of plugins with unsatisfied capability requirements", func() {
var (
runtimeName = "test-runtime"
runtimeVersion = "1.2.3"
supportedCapabilities = []api.Capability{
api.Capability_ADJUST_POSIX_RLIMITS,
api.Capability_INPUT_POSIX_RLIMITS,
api.Capability_ADJUST_LINUX_IO_PRIORITY,
api.Capability_INPUT_LINUX_IO_PRIORITY,
api.Capability_INPUT_IP_ADDRESSES,
api.Capability_ADJUST_LINUX_CONTAINER_ARGS,
}
requiredCapabilities = []api.Capability{
api.Capability_ADJUST_LINUX_SCHEDULING_POLICY,
}
plugin = &mockPlugin{
idx: "00",
name: "test",
options: []stub.Option{
stub.WithRequiredCapabilities(requiredCapabilities...),
},
}
)

s.runtime.name = runtimeName
s.runtime.version = runtimeVersion
s.runtime.options = append(s.runtime.options,
nri.WithSupportedCapabilities(
api.NewCapabilityMask(supportedCapabilities...),
),
)

s.Startup()
err := plugin.Start(s.dir)
Expect(err).ToNot(BeNil())
Expect(strings.Contains(err.Error(), "lacks required capabilities")).To(BeTrue())
})
})

func protoDiff(a, b proto.Message) string {
return cmp.Diff(a, b, protocmp.Transform())
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/adaptation/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ type (
SecurityProfile = api.SecurityProfile
User = api.User

EventMask = api.EventMask
CapabilityMask = api.CapabilityMask
EventMask = api.EventMask
)

// Aliased consts for api/api.proto.
Expand Down
26 changes: 26 additions & 0 deletions pkg/adaptation/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
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

// WithTestNRIVersion is an option to override the local NRI version
// for testing purposes.
func WithTestNRIVersion(v string) Option {
return func(r *Adaptation) error {
r.nriVersion = v
return nil
}
}
Loading
Loading