Merge pull request #6019 from klihub/pr/proto/nri
NRI: add support for NRI with extended scope.
This commit is contained in:
commit
c469f67a2b
@ -23,6 +23,7 @@ import (
|
|||||||
_ "github.com/containerd/containerd/gc/scheduler"
|
_ "github.com/containerd/containerd/gc/scheduler"
|
||||||
_ "github.com/containerd/containerd/leases/plugin"
|
_ "github.com/containerd/containerd/leases/plugin"
|
||||||
_ "github.com/containerd/containerd/metadata/plugin"
|
_ "github.com/containerd/containerd/metadata/plugin"
|
||||||
|
_ "github.com/containerd/containerd/pkg/nri/plugin"
|
||||||
_ "github.com/containerd/containerd/runtime/restart/monitor"
|
_ "github.com/containerd/containerd/runtime/restart/monitor"
|
||||||
_ "github.com/containerd/containerd/runtime/v2"
|
_ "github.com/containerd/containerd/runtime/v2"
|
||||||
_ "github.com/containerd/containerd/services/containers"
|
_ "github.com/containerd/containerd/services/containers"
|
||||||
|
@ -38,7 +38,7 @@ func FuzzCRIServer(data []byte) int {
|
|||||||
}
|
}
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
c, err := server.NewCRIService(criconfig.Config{}, client)
|
c, err := server.NewCRIService(criconfig.Config{}, client, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
141
docs/NRI.md
Normal file
141
docs/NRI.md
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
# NRI Support In Containerd
|
||||||
|
|
||||||
|
## Node Resource Interface
|
||||||
|
|
||||||
|
NRI, the Node Resource Interface, is a common framework for plugging
|
||||||
|
extensions into OCI-compatible container runtimes. It provides basic
|
||||||
|
mechanisms for plugins to track the state of containers and to make
|
||||||
|
limited changes to their configuration.
|
||||||
|
|
||||||
|
NRI itself is agnostic to the internal implementation details of any
|
||||||
|
container runtime. It provides an adaptation library which runtimes
|
||||||
|
use to integrate to and interact with NRI and plugins. In principle
|
||||||
|
any NRI plugin should be able to work with NRI-enabled runtimes.
|
||||||
|
|
||||||
|
For a detailed description of NRI and its capabilities please take a
|
||||||
|
look at the [NRI respository](https://github.com/containerd/nri).
|
||||||
|
|
||||||
|
## Containerd NRI Integration
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>see the containerd/NRI integration diagram</summary>
|
||||||
|
<img src="./containerd-nri-integration.png" title="Containerd/NRI Integration">
|
||||||
|
</details>
|
||||||
|
|
||||||
|
NRI support in containerd is split into two parts both logically and
|
||||||
|
physically. These parts are a common plugin (/nri/*) to integrate to
|
||||||
|
NRI and CRI-specific bits (/pkg/cri/server/nri-api) which convert
|
||||||
|
data between the runtime-agnostic NRI representation and the internal
|
||||||
|
representation of the CRI plugin.
|
||||||
|
|
||||||
|
### Containerd NRI Plugin
|
||||||
|
|
||||||
|
The containerd common NRI plugin implements the core logic of integrating
|
||||||
|
to and interacting with NRI. However, it does this without any knowledge
|
||||||
|
about the internal representation of containers or pods within containerd.
|
||||||
|
It defines an additional interface, Domain, which is used whenever the
|
||||||
|
internal representation of a container or pod needs to be translated to
|
||||||
|
the runtime agnostic NRI one, or when a configuration change requested by
|
||||||
|
an external NRI plugin needs to be applied to a container within containerd. `Domain` can be considered as a short-cut name for Domain-Namespace as Domain implements the functions the generic NRI interface needs to deal with pods and containers from a particular containerd namespace. As a reminder, containerd namespaces isolate state between clients of containerd. E.g. "k8s.io" for the kubernetes CRI clients, "moby" for docker clients, ... and "containerd" as the default for containerd/ctr.
|
||||||
|
|
||||||
|
### NRI Support for CRI Containers
|
||||||
|
|
||||||
|
The containerd CRI plugin registers itself as an above mentioned NRI
|
||||||
|
Domain for the "k8s.io" namespace, to allow container configuration to be customized by external
|
||||||
|
NRI plugins. Currently this Domain interface is only implemented for
|
||||||
|
the original CRI `pkg/cri/server` implementation. Implementing it for
|
||||||
|
the more recent experimental `pkg/cri/sbserver` implementation is on
|
||||||
|
the TODO list.
|
||||||
|
|
||||||
|
### NRI Support for Other Container 'Domains'
|
||||||
|
|
||||||
|
The main reason for this split of functionality is to allow
|
||||||
|
NRI plugins for other types of sandboxes and for other container clients other than just for CRI containers in the "k8s.io" namespace.
|
||||||
|
|
||||||
|
## Enabling NRI Support in Containerd
|
||||||
|
|
||||||
|
Enabling and disabling NRI support in containerd happens by enabling or
|
||||||
|
disabling the common containerd NRI plugin. The plugin, and consequently
|
||||||
|
NRI functionality, is disabled by default. It can be enabled by editing
|
||||||
|
the `[plugins."io.containerd.nri.v1.nri"]` section in the containerd
|
||||||
|
configuration file, which by default is `/etc/containerd/config.toml`,
|
||||||
|
and changing `disable = true` to `disable = false`. Once enabled, the
|
||||||
|
NRI section should look something like this:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[plugins."io.containerd.nri.v1.nri"]
|
||||||
|
config_file = "/etc/nri/nri.conf"
|
||||||
|
disable = false
|
||||||
|
plugin_path = "/opt/nri/plugins"
|
||||||
|
socket_path = "/var/run/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).
|
||||||
|
Plugins can also be started by external means, for instance by systemd.
|
||||||
|
|
||||||
|
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
|
||||||
|
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.
|
||||||
|
|
||||||
|
NRI can be configured to disable connections from externally launched
|
||||||
|
plugins, in which case the well-known socket is not created at all. The
|
||||||
|
configuration fragment shown above ensures that external connections are
|
||||||
|
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
|
||||||
|
|
||||||
|
## Testing NRI Support in Containerd
|
||||||
|
|
||||||
|
You can verify that NRI integration is properly enabled and functional by
|
||||||
|
configuring containerd and NRI as described above, taking the NRI
|
||||||
|
logger plugin either from the NRI repository or
|
||||||
|
[this fork](https://github.com/klihub/nri/tree/pr/proto/draft/plugins/logger)
|
||||||
|
on github, compiling it and starting it up.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/klihub/nri
|
||||||
|
cd nri
|
||||||
|
git checkout pr/proto/draft
|
||||||
|
make
|
||||||
|
./build/bin/logger -idx 00
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see the logger plugin receiving receiving a list of existing pods
|
||||||
|
and containers. If you then create or remove further pods and containers
|
||||||
|
using crictl or kubectl you should see detailed logs of the corresponding NRI
|
||||||
|
events printed by the logger.
|
||||||
|
|
||||||
|
## NRI Compatibility With v0.1.0 Plugins
|
||||||
|
|
||||||
|
You can enable backward compatibility with NRI v0.1.0 plugins using the
|
||||||
|
[v010-adapter plugin](https://github.com/klihub/nri/tree/pr/proto/draft/plugins/v010-adapter).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/klihub/nri
|
||||||
|
cd nri
|
||||||
|
git checkout pr/proto/draft
|
||||||
|
make
|
||||||
|
sudo cp build/bin/v010-adapter /usr/local/bin
|
||||||
|
sudo mkdir -p /opt/nri/plugins
|
||||||
|
sudo ln -s /usr/local/bin/v010-adapter /opt/nri/plugins/00-v010-adapter
|
||||||
|
```
|
BIN
docs/containerd-nri-integration.png
Normal file
BIN
docs/containerd-nri-integration.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 130 KiB |
22
go.mod
22
go.mod
@ -17,7 +17,9 @@ require (
|
|||||||
github.com/containerd/go-cni v1.1.6
|
github.com/containerd/go-cni v1.1.6
|
||||||
github.com/containerd/go-runc v1.0.0
|
github.com/containerd/go-runc v1.0.0
|
||||||
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028
|
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028
|
||||||
github.com/containerd/nri v0.1.0
|
// We need an NRI with the updated interface. We use a replace to
|
||||||
|
// divert it until the corresponding PR lands in the NRI repo.
|
||||||
|
github.com/containerd/nri v0.2.0
|
||||||
github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3
|
github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3
|
||||||
github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67
|
github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67
|
||||||
github.com/containerd/zfs v1.0.0
|
github.com/containerd/zfs v1.0.0
|
||||||
@ -47,7 +49,10 @@ require (
|
|||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
|
||||||
github.com/opencontainers/runc v1.1.4
|
github.com/opencontainers/runc v1.1.4
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb
|
||||||
|
// ATM the runtime-tools commit we need are beyond the latest tag.
|
||||||
|
// We use a replace to handle that until a new version is tagged.
|
||||||
|
github.com/opencontainers/runtime-tools v0.9.0
|
||||||
github.com/opencontainers/selinux v1.10.2
|
github.com/opencontainers/selinux v1.10.2
|
||||||
github.com/pelletier/go-toml v1.9.3
|
github.com/pelletier/go-toml v1.9.3
|
||||||
github.com/prometheus/client_golang v1.12.1
|
github.com/prometheus/client_golang v1.12.1
|
||||||
@ -82,7 +87,6 @@ require (
|
|||||||
require (
|
require (
|
||||||
cloud.google.com/go/compute/metadata v0.2.1 // indirect
|
cloud.google.com/go/compute/metadata v0.2.1 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
|
||||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
@ -106,7 +110,6 @@ require (
|
|||||||
github.com/moby/spdystream v0.2.0 // indirect
|
github.com/moby/spdystream v0.2.0 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e // indirect
|
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
@ -117,9 +120,6 @@ require (
|
|||||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
|
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
|
||||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
|
||||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
|
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
|
||||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect
|
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect
|
||||||
go.opencensus.io v0.23.0 // indirect
|
go.opencensus.io v0.23.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 // indirect
|
||||||
@ -131,7 +131,7 @@ require (
|
|||||||
golang.org/x/term v0.1.0 // indirect
|
golang.org/x/term v0.1.0 // indirect
|
||||||
golang.org/x/text v0.4.0 // indirect
|
golang.org/x/text v0.4.0 // indirect
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
||||||
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854 // indirect
|
golang.org/x/tools v0.2.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||||
@ -141,3 +141,9 @@ require (
|
|||||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace (
|
||||||
|
// Temporarily divert repo for updated/extended NRI.
|
||||||
|
github.com/containerd/nri => github.com/klihub/nri v0.0.0-20221122201439-2b09b4ad5cf3
|
||||||
|
github.com/opencontainers/runtime-tools => github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809
|
||||||
|
)
|
||||||
|
83
go.sum
83
go.sum
@ -76,6 +76,7 @@ github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JP
|
|||||||
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
|
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||||
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||||
@ -89,6 +90,7 @@ github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwT
|
|||||||
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
||||||
github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
|
github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
|
||||||
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
||||||
|
github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
||||||
github.com/Microsoft/hcsshim v0.10.0-rc.1 h1:Lms8jwpaIdIUvoBNee8ZuvIi1XnNy9uvnxSC9L1q1x4=
|
github.com/Microsoft/hcsshim v0.10.0-rc.1 h1:Lms8jwpaIdIUvoBNee8ZuvIi1XnNy9uvnxSC9L1q1x4=
|
||||||
github.com/Microsoft/hcsshim v0.10.0-rc.1/go.mod h1:7XX96hdvnwWGdXnksDNdhfFcUH1BtQY6bL2L3f9Abyk=
|
github.com/Microsoft/hcsshim v0.10.0-rc.1/go.mod h1:7XX96hdvnwWGdXnksDNdhfFcUH1BtQY6bL2L3f9Abyk=
|
||||||
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
||||||
@ -129,7 +131,6 @@ github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngE
|
|||||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||||
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
|
||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||||
@ -173,6 +174,7 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP
|
|||||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
|
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
|
||||||
@ -192,7 +194,6 @@ github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2v
|
|||||||
github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
|
github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
|
||||||
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
||||||
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
|
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
|
||||||
github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
|
|
||||||
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
|
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
|
||||||
github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
|
github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
|
||||||
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
|
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
|
||||||
@ -213,7 +214,6 @@ github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.
|
|||||||
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
|
||||||
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
@ -225,6 +225,7 @@ github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTV
|
|||||||
github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
|
github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
|
||||||
github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
|
github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
|
||||||
github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE=
|
github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE=
|
||||||
|
github.com/containerd/containerd v1.6.9/go.mod h1:XVicUvkxOrftE2Q1YWUXgZwkkAxwQYNOFzYWvfVfEfQ=
|
||||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
@ -237,7 +238,6 @@ github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvA
|
|||||||
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
|
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
|
||||||
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||||
github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
|
|
||||||
github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
|
github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
|
||||||
github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
|
github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
|
||||||
github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU=
|
github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU=
|
||||||
@ -259,12 +259,9 @@ github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6T
|
|||||||
github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow=
|
github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow=
|
||||||
github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
|
github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
|
||||||
github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4=
|
github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4=
|
||||||
|
github.com/containerd/imgcrypt v1.1.4/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
|
||||||
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028 h1:CqFTne8EGv2eAWAS0O6weGE5RtP0Q8XiFUdkDT840Yc=
|
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028 h1:CqFTne8EGv2eAWAS0O6weGE5RtP0Q8XiFUdkDT840Yc=
|
||||||
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
|
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
|
||||||
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 h1:6QioHRlThlKh2RkRTR4kIT3PKAcrLo3gIWnjkM4dQmQ=
|
|
||||||
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
|
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-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||||
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||||
@ -377,6 +374,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
|
|||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
@ -504,6 +502,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
|
github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
|
||||||
@ -624,6 +623,8 @@ github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
|
|||||||
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
||||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||||
|
github.com/klihub/nri v0.0.0-20221122201439-2b09b4ad5cf3 h1:8V9PThT2f1pBaGz0lSJ6EtLnIuxKEz5utRh1/8tHD0U=
|
||||||
|
github.com/klihub/nri v0.0.0-20221122201439-2b09b4ad5cf3/go.mod h1:Q2u9Sudol4IkJ6YK0gShznKMxM6Un0Y3O4Wslf5Nerg=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
@ -674,6 +675,7 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
|
|||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||||
|
github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
|
||||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||||
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||||
@ -709,6 +711,7 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
|
|||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||||
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||||
|
github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
@ -729,7 +732,12 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k
|
|||||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||||
github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU=
|
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.5.0 h1:TRtrvv2vdQqzkwrQ1ke6vtXf7IK34RBUJafIy1wMwls=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
|
||||||
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
@ -740,7 +748,12 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
|
|||||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||||
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
|
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
|
||||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||||
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||||
|
github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
|
||||||
|
github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
|
||||||
|
github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
|
||||||
|
github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg=
|
||||||
|
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
@ -751,15 +764,16 @@ github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM
|
|||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
|
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||||
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
|
||||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
||||||
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||||
github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
|
github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
|
||||||
|
github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
|
||||||
github.com/opencontainers/runc v1.1.4 h1:nRCz/8sKg6K6jgYAFLDlXzPeITBZJyX28DBVhWD+5dg=
|
github.com/opencontainers/runc v1.1.4 h1:nRCz/8sKg6K6jgYAFLDlXzPeITBZJyX28DBVhWD+5dg=
|
||||||
github.com/opencontainers/runc v1.1.4/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
|
github.com/opencontainers/runc v1.1.4/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
|
||||||
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
@ -767,15 +781,16 @@ github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/
|
|||||||
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
|
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb h1:1xSVPOd7/UA+39/hXEGnBJ13p6JFB0E1EvQFlrRDOXI=
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e h1:2Tg49TNXSTIsX8AAtmo1aQ1IbfnoUFzkOp7p2iWygtc=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809 h1:WSwkWIIS4s+E/dPF6HuVZ/hnq1WfXN371eESjREnU8k=
|
||||||
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI=
|
||||||
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
||||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||||
|
github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||||
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||||
|
github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||||
github.com/opencontainers/selinux v1.10.2 h1:NFy2xCsjn7+WspbfZkUd5zyVeisV7VFbPSP96+8/ha4=
|
github.com/opencontainers/selinux v1.10.2 h1:NFy2xCsjn7+WspbfZkUd5zyVeisV7VFbPSP96+8/ha4=
|
||||||
github.com/opencontainers/selinux v1.10.2/go.mod h1:cARutUbaUrlRClyvxOICCgKixCs6L05aUsohzA3EkHQ=
|
github.com/opencontainers/selinux v1.10.2/go.mod h1:cARutUbaUrlRClyvxOICCgKixCs6L05aUsohzA3EkHQ=
|
||||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
@ -801,6 +816,7 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
|
|||||||
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
||||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||||
|
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||||
github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
|
github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
|
||||||
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||||
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
@ -916,6 +932,7 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1
|
|||||||
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
|
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
|
||||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
|
github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
@ -931,7 +948,6 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17
|
|||||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
|
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
|
||||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
|
||||||
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
|
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
@ -947,6 +963,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||||
@ -1038,6 +1056,8 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
@ -1075,6 +1095,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -1131,8 +1153,14 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
|
|||||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
golang.org/x/net v0.1.1-0.20221027164007-c63010009c80 h1:CtRWmqbiPSOXwJV1JoY7pWiTx2xzVKQ813bvU+Y/9jI=
|
golang.org/x/net v0.1.1-0.20221027164007-c63010009c80 h1:CtRWmqbiPSOXwJV1JoY7pWiTx2xzVKQ813bvU+Y/9jI=
|
||||||
golang.org/x/net v0.1.1-0.20221027164007-c63010009c80/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
golang.org/x/net v0.1.1-0.20221027164007-c63010009c80/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
@ -1161,6 +1189,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -1256,19 +1285,26 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
|
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
|
||||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@ -1355,9 +1391,12 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
|
|||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854 h1:fzDvmJnoyma87dC7IBnNQWmMZNalsNrtiY1X6PwmME0=
|
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||||
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854/go.mod h1:VsjNM1dMo+Ofkp5d7y7fOdQZD8MTXSQ4w3EPk65AvKU=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||||
|
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -1443,6 +1482,7 @@ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxH
|
|||||||
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||||
google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd h1:1eV6KuDTxraYYsYGWksp1thEGP+8dtX/TINL9h+ppiI=
|
google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd h1:1eV6KuDTxraYYsYGWksp1thEGP+8dtX/TINL9h+ppiI=
|
||||||
google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
@ -1473,6 +1513,8 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
|
|||||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
|
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||||
|
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||||
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
|
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
|
||||||
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
@ -1488,6 +1530,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
|
|||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||||
@ -1576,6 +1619,8 @@ k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
|
|||||||
k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
|
k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
|
||||||
k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
|
k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
|
||||||
k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4=
|
k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4=
|
||||||
|
k8s.io/cri-api v0.25.0/go.mod h1:J1rAyQkSJ2Q6I+aBMOVgg2/cbbebso6FNa0UagiR0kc=
|
||||||
|
k8s.io/cri-api v0.25.3/go.mod h1:riC/P0yOGUf2K1735wW+CXs1aY2ctBgePtnnoFLd0dU=
|
||||||
k8s.io/cri-api v0.26.0-beta.0 h1:mVt2/80VZy2dRN4mpVYJbPB9L/Zt/EvVev++zPTV9Tw=
|
k8s.io/cri-api v0.26.0-beta.0 h1:mVt2/80VZy2dRN4mpVYJbPB9L/Zt/EvVev++zPTV9Tw=
|
||||||
k8s.io/cri-api v0.26.0-beta.0/go.mod h1:E49tenyB7esgfIguEd7+g9qYhHOr9peyyBcSaeH6Gxw=
|
k8s.io/cri-api v0.26.0-beta.0/go.mod h1:E49tenyB7esgfIguEd7+g9qYhHOr9peyyBcSaeH6Gxw=
|
||||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
|
@ -13,7 +13,7 @@ require (
|
|||||||
github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67
|
github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67
|
||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.0
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
golang.org/x/sys v0.2.0
|
golang.org/x/sys v0.2.0
|
||||||
@ -58,7 +58,7 @@ require (
|
|||||||
golang.org/x/net v0.1.1-0.20221027164007-c63010009c80 // indirect
|
golang.org/x/net v0.1.1-0.20221027164007-c63010009c80 // indirect
|
||||||
golang.org/x/sync v0.1.0 // indirect
|
golang.org/x/sync v0.1.0 // indirect
|
||||||
golang.org/x/text v0.4.0 // indirect
|
golang.org/x/text v0.4.0 // indirect
|
||||||
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854 // indirect
|
golang.org/x/tools v0.2.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd // indirect
|
google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd // indirect
|
||||||
google.golang.org/grpc v1.50.1 // indirect
|
google.golang.org/grpc v1.50.1 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
@ -70,4 +70,10 @@ require (
|
|||||||
// IMPORTANT: this replace rule ONLY replaces containerd itself; dependencies
|
// IMPORTANT: this replace rule ONLY replaces containerd itself; dependencies
|
||||||
// in the "require" section above are still taken into account for version
|
// in the "require" section above are still taken into account for version
|
||||||
// resolution if newer.
|
// resolution if newer.
|
||||||
replace github.com/containerd/containerd => ../../
|
replace (
|
||||||
|
github.com/containerd/containerd => ../../
|
||||||
|
|
||||||
|
// Temporarily divert repo for updated/extended NRI.
|
||||||
|
github.com/containerd/nri => github.com/klihub/nri v0.0.0-20221122201439-2b09b4ad5cf3
|
||||||
|
github.com/opencontainers/runtime-tools => github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809
|
||||||
|
)
|
||||||
|
@ -390,6 +390,7 @@ github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2B
|
|||||||
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
||||||
github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
||||||
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
||||||
|
github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
||||||
github.com/Microsoft/hcsshim v0.10.0-rc.1 h1:Lms8jwpaIdIUvoBNee8ZuvIi1XnNy9uvnxSC9L1q1x4=
|
github.com/Microsoft/hcsshim v0.10.0-rc.1 h1:Lms8jwpaIdIUvoBNee8ZuvIi1XnNy9uvnxSC9L1q1x4=
|
||||||
github.com/Microsoft/hcsshim v0.10.0-rc.1/go.mod h1:7XX96hdvnwWGdXnksDNdhfFcUH1BtQY6bL2L3f9Abyk=
|
github.com/Microsoft/hcsshim v0.10.0-rc.1/go.mod h1:7XX96hdvnwWGdXnksDNdhfFcUH1BtQY6bL2L3f9Abyk=
|
||||||
github.com/Microsoft/hcsshim/test v0.0.0-20210408205431-da33ecd607e1 h1:pVKfKyPkXna29XlGjxSr9J0A7vNucOUHZ/2ClcTWalw=
|
github.com/Microsoft/hcsshim/test v0.0.0-20210408205431-da33ecd607e1 h1:pVKfKyPkXna29XlGjxSr9J0A7vNucOUHZ/2ClcTWalw=
|
||||||
@ -485,7 +486,6 @@ 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 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0=
|
||||||
github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
|
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/imgcrypt v1.1.5-0.20220421044638-8ba028dca028/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
|
||||||
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
|
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
|
||||||
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
|
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
|
||||||
github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
|
github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
|
||||||
@ -611,6 +611,7 @@ github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
|
|||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
||||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||||
@ -779,8 +780,10 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
|
|||||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
||||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||||
|
github.com/klihub/nri v0.0.0-20221122201439-2b09b4ad5cf3/go.mod h1:Q2u9Sudol4IkJ6YK0gShznKMxM6Un0Y3O4Wslf5Nerg=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
@ -824,6 +827,7 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
|
|||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
|
github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
|
||||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||||
@ -833,6 +837,7 @@ github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vyg
|
|||||||
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||||
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||||
|
github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
|
||||||
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
|
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
|
||||||
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
|
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
|
||||||
github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs=
|
github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs=
|
||||||
@ -865,6 +870,9 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
|
|||||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||||
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
|
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
|
||||||
github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
|
||||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
@ -874,10 +882,14 @@ github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+t
|
|||||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||||
github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
|
github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
|
||||||
|
github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
|
||||||
|
github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
|
||||||
|
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
|
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||||
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||||
@ -888,12 +900,14 @@ github.com/opencontainers/runc v1.1.4/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJ
|
|||||||
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
|
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb h1:1xSVPOd7/UA+39/hXEGnBJ13p6JFB0E1EvQFlrRDOXI=
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
|
github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI=
|
||||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||||
|
github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||||
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||||
|
github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||||
github.com/opencontainers/selinux v1.10.2 h1:NFy2xCsjn7+WspbfZkUd5zyVeisV7VFbPSP96+8/ha4=
|
github.com/opencontainers/selinux v1.10.2 h1:NFy2xCsjn7+WspbfZkUd5zyVeisV7VFbPSP96+8/ha4=
|
||||||
github.com/opencontainers/selinux v1.10.2/go.mod h1:cARutUbaUrlRClyvxOICCgKixCs6L05aUsohzA3EkHQ=
|
github.com/opencontainers/selinux v1.10.2/go.mod h1:cARutUbaUrlRClyvxOICCgKixCs6L05aUsohzA3EkHQ=
|
||||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
@ -1011,6 +1025,7 @@ github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwD
|
|||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
|
github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
@ -1452,8 +1467,9 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854 h1:fzDvmJnoyma87dC7IBnNQWmMZNalsNrtiY1X6PwmME0=
|
|
||||||
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854/go.mod h1:VsjNM1dMo+Ofkp5d7y7fOdQZD8MTXSQ4w3EPk65AvKU=
|
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854/go.mod h1:VsjNM1dMo+Ofkp5d7y7fOdQZD8MTXSQ4w3EPk65AvKU=
|
||||||
|
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||||
|
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -1736,6 +1752,7 @@ k8s.io/client-go v0.25.4/go.mod h1:8trHCAC83XKY0wsBIpbirZU4NTUpbuhc2JnI7OruGZw=
|
|||||||
k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0=
|
k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0=
|
||||||
k8s.io/component-base v0.25.4/go.mod h1:nnZJU8OP13PJEm6/p5V2ztgX2oyteIaAGKGMYb2L2cY=
|
k8s.io/component-base v0.25.4/go.mod h1:nnZJU8OP13PJEm6/p5V2ztgX2oyteIaAGKGMYb2L2cY=
|
||||||
k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
|
k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
|
||||||
|
k8s.io/cri-api v0.25.3/go.mod h1:riC/P0yOGUf2K1735wW+CXs1aY2ctBgePtnnoFLd0dU=
|
||||||
k8s.io/cri-api v0.26.0-beta.0/go.mod h1:E49tenyB7esgfIguEd7+g9qYhHOr9peyyBcSaeH6Gxw=
|
k8s.io/cri-api v0.26.0-beta.0/go.mod h1:E49tenyB7esgfIguEd7+g9qYhHOr9peyyBcSaeH6Gxw=
|
||||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
|
@ -471,5 +471,5 @@ func initLocalCRIPlugin(client *containerd.Client, tmpDir string, registryCfg cr
|
|||||||
RootDir: filepath.Join(criWorkDir, "root"),
|
RootDir: filepath.Join(criWorkDir, "root"),
|
||||||
StateDir: filepath.Join(criWorkDir, "state"),
|
StateDir: filepath.Join(criWorkDir, "state"),
|
||||||
}
|
}
|
||||||
return criserver.NewCRIService(cfg, client)
|
return criserver.NewCRIService(cfg, client, nil)
|
||||||
}
|
}
|
||||||
|
1256
integration/nri_test.go
Normal file
1256
integration/nri_test.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/pkg/cri/sbserver"
|
"github.com/containerd/containerd/pkg/cri/sbserver"
|
||||||
|
"github.com/containerd/containerd/pkg/nri"
|
||||||
"github.com/containerd/containerd/platforms"
|
"github.com/containerd/containerd/platforms"
|
||||||
"github.com/containerd/containerd/plugin"
|
"github.com/containerd/containerd/plugin"
|
||||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
@ -46,6 +47,7 @@ func init() {
|
|||||||
Requires: []plugin.Type{
|
Requires: []plugin.Type{
|
||||||
plugin.EventPlugin,
|
plugin.EventPlugin,
|
||||||
plugin.ServicePlugin,
|
plugin.ServicePlugin,
|
||||||
|
plugin.NRIApiPlugin,
|
||||||
},
|
},
|
||||||
InitFn: initCRIService,
|
InitFn: initCRIService,
|
||||||
})
|
})
|
||||||
@ -85,12 +87,19 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var s server.CRIService
|
var s server.CRIService
|
||||||
|
var nrip nri.API
|
||||||
if os.Getenv("ENABLE_CRI_SANDBOXES") != "" {
|
if os.Getenv("ENABLE_CRI_SANDBOXES") != "" {
|
||||||
log.G(ctx).Info("using experimental CRI Sandbox server - unset ENABLE_CRI_SANDBOXES to disable")
|
log.G(ctx).Info("using experimental CRI Sandbox server - unset ENABLE_CRI_SANDBOXES to disable")
|
||||||
s, err = sbserver.NewCRIService(c, client)
|
s, err = sbserver.NewCRIService(c, client)
|
||||||
} else {
|
} else {
|
||||||
log.G(ctx).Info("using legacy CRI server")
|
log.G(ctx).Info("using legacy CRI server")
|
||||||
s, err = server.NewCRIService(c, client)
|
|
||||||
|
nrip, err = getNRIPlugin(ic)
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).Info("NRI service not found, disabling NRI support")
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err = server.NewCRIService(c, client, nrip)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create CRI service: %w", err)
|
return nil, fmt.Errorf("failed to create CRI service: %w", err)
|
||||||
@ -102,6 +111,14 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
// TODO(random-liu): Whether and how we can stop containerd.
|
// TODO(random-liu): Whether and how we can stop containerd.
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
if nrip != nil {
|
||||||
|
log.G(ctx).Info("using experimental NRI integration - disable nri plugin to prevent this")
|
||||||
|
if err = nrip.Start(); err != nil {
|
||||||
|
log.G(ctx).WithError(err).Fatal("Failed to start NRI service")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,3 +145,24 @@ func setGLogLevel() error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the NRI plugin and verify its type.
|
||||||
|
func getNRIPlugin(ic *plugin.InitContext) (nri.API, error) {
|
||||||
|
const (
|
||||||
|
pluginType = plugin.NRIApiPlugin
|
||||||
|
pluginName = "nri"
|
||||||
|
)
|
||||||
|
|
||||||
|
p, err := ic.GetByID(pluginType, pluginName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
api, ok := p.(nri.API)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("NRI plugin (%s, %q) has incompatible type %T",
|
||||||
|
pluginType, pluginName, api)
|
||||||
|
}
|
||||||
|
|
||||||
|
return api, nil
|
||||||
|
}
|
||||||
|
@ -246,6 +246,19 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
|
|||||||
containerd.WithRuntime(sandboxInfo.Runtime.Name, runtimeOptions),
|
containerd.WithRuntime(sandboxInfo.Runtime.Name, runtimeOptions),
|
||||||
containerd.WithContainerLabels(containerLabels),
|
containerd.WithContainerLabels(containerLabels),
|
||||||
containerd.WithContainerExtension(containerMetadataExtension, &meta))
|
containerd.WithContainerExtension(containerMetadataExtension, &meta))
|
||||||
|
|
||||||
|
if c.nri.isEnabled() {
|
||||||
|
opts = append(opts, c.nri.WithContainerAdjustment())
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
deferCtx, deferCancel := ctrdutil.DeferContext()
|
||||||
|
defer deferCancel()
|
||||||
|
c.nri.undoCreateContainer(deferCtx, &sandbox, id, spec)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
var cntr containerd.Container
|
var cntr containerd.Container
|
||||||
if cntr, err = c.client.NewContainer(ctx, id, opts...); err != nil {
|
if cntr, err = c.client.NewContainer(ctx, id, opts...); err != nil {
|
||||||
return nil, fmt.Errorf("failed to create containerd container: %w", err)
|
return nil, fmt.Errorf("failed to create containerd container: %w", err)
|
||||||
@ -284,6 +297,13 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
|
|||||||
return nil, fmt.Errorf("failed to add container %q into store: %w", id, err)
|
return nil, fmt.Errorf("failed to add container %q into store: %w", id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.nri.isEnabled() {
|
||||||
|
err = c.nri.postCreateContainer(ctx, &sandbox, &container)
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Errorf("NRI post-create notification failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
containerCreateTimer.WithValues(ociRuntime.Type).UpdateSince(start)
|
containerCreateTimer.WithValues(ociRuntime.Type).UpdateSince(start)
|
||||||
|
|
||||||
return &runtime.CreateContainerResponse{ContainerId: id}, nil
|
return &runtime.CreateContainerResponse{ContainerId: id}, nil
|
||||||
|
@ -73,6 +73,18 @@ func (c *criService) RemoveContainer(ctx context.Context, r *runtime.RemoveConta
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
if c.nri.isEnabled() {
|
||||||
|
sandbox, err := c.sandboxStore.Get(container.SandboxID)
|
||||||
|
if err != nil {
|
||||||
|
err = c.nri.removeContainer(ctx, nil, &container)
|
||||||
|
} else {
|
||||||
|
err = c.nri.removeContainer(ctx, &sandbox, &container)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Error("NRI failed to remove container")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE(random-liu): Docker set container to "Dead" state when start removing the
|
// NOTE(random-liu): Docker set container to "Dead" state when start removing the
|
||||||
// container so as to avoid start/restart the container again. However, for current
|
// container so as to avoid start/restart the container again. However, for current
|
||||||
// kubelet implementation, we'll never start a container once we decide to remove it,
|
// kubelet implementation, we'll never start a container once we decide to remove it,
|
||||||
|
@ -27,8 +27,6 @@ import (
|
|||||||
containerdio "github.com/containerd/containerd/cio"
|
containerdio "github.com/containerd/containerd/cio"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/nri"
|
|
||||||
v1 "github.com/containerd/nri/types/v1"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||||
|
|
||||||
@ -135,7 +133,7 @@ func (c *criService) StartContainer(ctx context.Context, r *runtime.StartContain
|
|||||||
deferCtx, deferCancel := ctrdutil.DeferContext()
|
deferCtx, deferCancel := ctrdutil.DeferContext()
|
||||||
defer deferCancel()
|
defer deferCancel()
|
||||||
// It's possible that task is deleted by event monitor.
|
// It's possible that task is deleted by event monitor.
|
||||||
if _, err := task.Delete(deferCtx, WithNRISandboxDelete(sandboxID), containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) {
|
if _, err := task.Delete(deferCtx, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) {
|
||||||
log.G(ctx).WithError(err).Errorf("Failed to delete containerd task %q", id)
|
log.G(ctx).WithError(err).Errorf("Failed to delete containerd task %q", id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,17 +144,22 @@ func (c *criService) StartContainer(ctx context.Context, r *runtime.StartContain
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to wait for containerd task: %w", err)
|
return nil, fmt.Errorf("failed to wait for containerd task: %w", err)
|
||||||
}
|
}
|
||||||
nric, err := nri.New()
|
|
||||||
if err != nil {
|
defer func() {
|
||||||
log.G(ctx).WithError(err).Error("unable to create nri client")
|
if retErr != nil {
|
||||||
}
|
deferCtx, deferCancel := ctrdutil.DeferContext()
|
||||||
if nric != nil {
|
defer deferCancel()
|
||||||
nriSB := &nri.Sandbox{
|
err = c.nri.stopContainer(deferCtx, &sandbox, &cntr)
|
||||||
ID: sandboxID,
|
if err != nil {
|
||||||
Labels: sandbox.Config.Labels,
|
log.G(ctx).WithError(err).Errorf("NRI stop failed for failed container %q", id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _, err := nric.InvokeWithSandbox(ctx, task, v1.Create, nriSB); err != nil {
|
}()
|
||||||
return nil, fmt.Errorf("nri invoke: %w", err)
|
if c.nri.isEnabled() {
|
||||||
|
err = c.nri.startContainer(ctx, &sandbox, &cntr)
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Errorf("NRI container start failed")
|
||||||
|
return nil, fmt.Errorf("NRI container start failed: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,6 +180,13 @@ func (c *criService) StartContainer(ctx context.Context, r *runtime.StartContain
|
|||||||
// It handles the TaskExit event and update container state after this.
|
// It handles the TaskExit event and update container state after this.
|
||||||
c.eventMonitor.startContainerExitMonitor(context.Background(), id, task.Pid(), exitCh)
|
c.eventMonitor.startContainerExitMonitor(context.Background(), id, task.Pid(), exitCh)
|
||||||
|
|
||||||
|
if c.nri.isEnabled() {
|
||||||
|
err = c.nri.postStartContainer(ctx, &sandbox, &cntr)
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Errorf("NRI post-start notification failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
containerStartTimer.WithValues(info.Runtime.Name).UpdateSince(start)
|
containerStartTimer.WithValues(info.Runtime.Name).UpdateSince(start)
|
||||||
|
|
||||||
return &runtime.StartContainerResponse{}, nil
|
return &runtime.StartContainerResponse{}, nil
|
||||||
|
@ -47,6 +47,18 @@ func (c *criService) StopContainer(ctx context.Context, r *runtime.StopContainer
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.nri.isEnabled() {
|
||||||
|
sandbox, err := c.sandboxStore.Get(container.SandboxID)
|
||||||
|
if err != nil {
|
||||||
|
err = c.nri.stopContainer(ctx, nil, &container)
|
||||||
|
} else {
|
||||||
|
err = c.nri.stopContainer(ctx, &sandbox, &container)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Error("NRI failed to stop container")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
i, err := container.Container.Info(ctx)
|
i, err := container.Container.Info(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get container info: %w", err)
|
return nil, fmt.Errorf("get container info: %w", err)
|
||||||
@ -78,7 +90,7 @@ func (c *criService) stopContainer(ctx context.Context, container containerstore
|
|||||||
}
|
}
|
||||||
// Don't return for unknown state, some cleanup needs to be done.
|
// Don't return for unknown state, some cleanup needs to be done.
|
||||||
if state == runtime.ContainerState_CONTAINER_UNKNOWN {
|
if state == runtime.ContainerState_CONTAINER_UNKNOWN {
|
||||||
return cleanupUnknownContainer(ctx, id, container)
|
return c.cleanupUnknownContainer(ctx, id, container)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -93,7 +105,7 @@ func (c *criService) stopContainer(ctx context.Context, container containerstore
|
|||||||
if !errdefs.IsNotFound(err) {
|
if !errdefs.IsNotFound(err) {
|
||||||
return fmt.Errorf("failed to wait for task for %q: %w", id, err)
|
return fmt.Errorf("failed to wait for task for %q: %w", id, err)
|
||||||
}
|
}
|
||||||
return cleanupUnknownContainer(ctx, id, container)
|
return c.cleanupUnknownContainer(ctx, id, container)
|
||||||
}
|
}
|
||||||
|
|
||||||
exitCtx, exitCancel := context.WithCancel(context.Background())
|
exitCtx, exitCancel := context.WithCancel(context.Background())
|
||||||
@ -196,7 +208,7 @@ func (c *criService) waitContainerStop(ctx context.Context, container containers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cleanupUnknownContainer cleanup stopped container in unknown state.
|
// cleanupUnknownContainer cleanup stopped container in unknown state.
|
||||||
func cleanupUnknownContainer(ctx context.Context, id string, cntr containerstore.Container) error {
|
func (c *criService) cleanupUnknownContainer(ctx context.Context, id string, cntr containerstore.Container) error {
|
||||||
// Reuse handleContainerExit to do the cleanup.
|
// Reuse handleContainerExit to do the cleanup.
|
||||||
return handleContainerExit(ctx, &eventtypes.TaskExit{
|
return handleContainerExit(ctx, &eventtypes.TaskExit{
|
||||||
ContainerID: id,
|
ContainerID: id,
|
||||||
@ -204,5 +216,5 @@ func cleanupUnknownContainer(ctx context.Context, id string, cntr containerstore
|
|||||||
Pid: 0,
|
Pid: 0,
|
||||||
ExitStatus: unknownExitCode,
|
ExitStatus: unknownExitCode,
|
||||||
ExitedAt: protobuf.ToTimestamp(time.Now()),
|
ExitedAt: protobuf.ToTimestamp(time.Now()),
|
||||||
}, cntr)
|
}, cntr, c)
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||||
|
|
||||||
containerstore "github.com/containerd/containerd/pkg/cri/store/container"
|
containerstore "github.com/containerd/containerd/pkg/cri/store/container"
|
||||||
|
sandboxstore "github.com/containerd/containerd/pkg/cri/store/sandbox"
|
||||||
ctrdutil "github.com/containerd/containerd/pkg/cri/util"
|
ctrdutil "github.com/containerd/containerd/pkg/cri/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -42,6 +43,24 @@ func (c *criService) UpdateContainerResources(ctx context.Context, r *runtime.Up
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to find container: %w", err)
|
return nil, fmt.Errorf("failed to find container: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sandbox sandboxstore.Sandbox
|
||||||
|
if c.nri.isEnabled() {
|
||||||
|
sandbox, err = c.sandboxStore.Get(container.SandboxID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resources := r.GetLinux()
|
||||||
|
updated, err := c.nri.updateContainer(ctx, &sandbox, &container, resources)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("NRI container update failed: %w", err)
|
||||||
|
}
|
||||||
|
if updated != nil {
|
||||||
|
*resources = *updated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update resources in status update transaction, so that:
|
// Update resources in status update transaction, so that:
|
||||||
// 1) There won't be race condition with container start.
|
// 1) There won't be race condition with container start.
|
||||||
// 2) There won't be concurrent resource update to the same container.
|
// 2) There won't be concurrent resource update to the same container.
|
||||||
@ -50,6 +69,14 @@ func (c *criService) UpdateContainerResources(ctx context.Context, r *runtime.Up
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, fmt.Errorf("failed to update resources: %w", err)
|
return nil, fmt.Errorf("failed to update resources: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.nri.isEnabled() {
|
||||||
|
err = c.nri.postUpdateContainer(ctx, &sandbox, &container)
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Errorf("NRI post-update notification failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &runtime.UpdateContainerResourcesResponse{}, nil
|
return &runtime.UpdateContainerResourcesResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ func (em *eventMonitor) startSandboxExitMonitor(ctx context.Context, id string,
|
|||||||
|
|
||||||
sb, err := em.c.sandboxStore.Get(e.ID)
|
sb, err := em.c.sandboxStore.Get(e.ID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if err := handleSandboxExit(dctx, e, sb); err != nil {
|
if err := handleSandboxExit(dctx, e, sb, em.c); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -187,7 +187,7 @@ func (em *eventMonitor) startContainerExitMonitor(ctx context.Context, id string
|
|||||||
|
|
||||||
cntr, err := em.c.containerStore.Get(e.ID)
|
cntr, err := em.c.containerStore.Get(e.ID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if err := handleContainerExit(dctx, e, cntr); err != nil {
|
if err := handleContainerExit(dctx, e, cntr, em.c); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -313,7 +313,7 @@ func (em *eventMonitor) handleEvent(any interface{}) error {
|
|||||||
// Use ID instead of ContainerID to rule out TaskExit event for exec.
|
// Use ID instead of ContainerID to rule out TaskExit event for exec.
|
||||||
cntr, err := em.c.containerStore.Get(e.ID)
|
cntr, err := em.c.containerStore.Get(e.ID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if err := handleContainerExit(ctx, e, cntr); err != nil {
|
if err := handleContainerExit(ctx, e, cntr, em.c); err != nil {
|
||||||
return fmt.Errorf("failed to handle container TaskExit event: %w", err)
|
return fmt.Errorf("failed to handle container TaskExit event: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -322,7 +322,7 @@ func (em *eventMonitor) handleEvent(any interface{}) error {
|
|||||||
}
|
}
|
||||||
sb, err := em.c.sandboxStore.Get(e.ID)
|
sb, err := em.c.sandboxStore.Get(e.ID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if err := handleSandboxExit(ctx, e, sb); err != nil {
|
if err := handleSandboxExit(ctx, e, sb, em.c); err != nil {
|
||||||
return fmt.Errorf("failed to handle sandbox TaskExit event: %w", err)
|
return fmt.Errorf("failed to handle sandbox TaskExit event: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -362,7 +362,7 @@ func (em *eventMonitor) handleEvent(any interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handleContainerExit handles TaskExit event for container.
|
// handleContainerExit handles TaskExit event for container.
|
||||||
func handleContainerExit(ctx context.Context, e *eventtypes.TaskExit, cntr containerstore.Container) error {
|
func handleContainerExit(ctx context.Context, e *eventtypes.TaskExit, cntr containerstore.Container, c *criService) error {
|
||||||
// Attach container IO so that `Delete` could cleanup the stream properly.
|
// Attach container IO so that `Delete` could cleanup the stream properly.
|
||||||
task, err := cntr.Container.Task(ctx,
|
task, err := cntr.Container.Task(ctx,
|
||||||
func(*containerdio.FIFOSet) (containerdio.IO, error) {
|
func(*containerdio.FIFOSet) (containerdio.IO, error) {
|
||||||
@ -384,7 +384,7 @@ func handleContainerExit(ctx context.Context, e *eventtypes.TaskExit, cntr conta
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO(random-liu): [P1] This may block the loop, we may want to spawn a worker
|
// TODO(random-liu): [P1] This may block the loop, we may want to spawn a worker
|
||||||
if _, err = task.Delete(ctx, WithNRISandboxDelete(cntr.SandboxID), containerd.WithProcessKill); err != nil {
|
if _, err = task.Delete(ctx, c.nri.WithContainerExit(&cntr), containerd.WithProcessKill); err != nil {
|
||||||
if !errdefs.IsNotFound(err) {
|
if !errdefs.IsNotFound(err) {
|
||||||
return fmt.Errorf("failed to stop container: %w", err)
|
return fmt.Errorf("failed to stop container: %w", err)
|
||||||
}
|
}
|
||||||
@ -415,7 +415,7 @@ func handleContainerExit(ctx context.Context, e *eventtypes.TaskExit, cntr conta
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handleSandboxExit handles TaskExit event for sandbox.
|
// handleSandboxExit handles TaskExit event for sandbox.
|
||||||
func handleSandboxExit(ctx context.Context, e *eventtypes.TaskExit, sb sandboxstore.Sandbox) error {
|
func handleSandboxExit(ctx context.Context, e *eventtypes.TaskExit, sb sandboxstore.Sandbox, c *criService) error {
|
||||||
// No stream attached to sandbox container.
|
// No stream attached to sandbox container.
|
||||||
task, err := sb.Container.Task(ctx, nil)
|
task, err := sb.Container.Task(ctx, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -424,7 +424,7 @@ func handleSandboxExit(ctx context.Context, e *eventtypes.TaskExit, sb sandboxst
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO(random-liu): [P1] This may block the loop, we may want to spawn a worker
|
// TODO(random-liu): [P1] This may block the loop, we may want to spawn a worker
|
||||||
if _, err = task.Delete(ctx, WithNRISandboxDelete(sb.ID), containerd.WithProcessKill); err != nil {
|
if _, err = task.Delete(ctx, containerd.WithProcessKill); err != nil {
|
||||||
if !errdefs.IsNotFound(err) {
|
if !errdefs.IsNotFound(err) {
|
||||||
return fmt.Errorf("failed to stop sandbox: %w", err)
|
return fmt.Errorf("failed to stop sandbox: %w", err)
|
||||||
}
|
}
|
||||||
|
782
pkg/cri/server/nri-api.go
Normal file
782
pkg/cri/server/nri-api.go
Normal file
@ -0,0 +1,782 @@
|
|||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/containerd/containerd/containers"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/containerd/containerd/pkg/cri/annotations"
|
||||||
|
cstore "github.com/containerd/containerd/pkg/cri/store/container"
|
||||||
|
sstore "github.com/containerd/containerd/pkg/cri/store/sandbox"
|
||||||
|
ctrdutil "github.com/containerd/containerd/pkg/cri/util"
|
||||||
|
"github.com/containerd/typeurl"
|
||||||
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/opencontainers/runtime-tools/generate"
|
||||||
|
cri "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/pkg/cri/constants"
|
||||||
|
"github.com/containerd/containerd/pkg/nri"
|
||||||
|
|
||||||
|
"github.com/containerd/nri/pkg/api"
|
||||||
|
|
||||||
|
nrigen "github.com/containerd/nri/pkg/runtime-tools/generate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type nriAPI struct {
|
||||||
|
cri *criService
|
||||||
|
nri nri.API
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) register() {
|
||||||
|
if !a.isEnabled() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
nri.RegisterDomain(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) isEnabled() bool {
|
||||||
|
return a != nil && a.nri != nil && a.nri.IsEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// CRI-NRI lifecycle hook interface
|
||||||
|
//
|
||||||
|
// These functions are used to hook NRI into the processing of
|
||||||
|
// the corresponding CRI lifecycle events using the common NRI
|
||||||
|
// interface.
|
||||||
|
//
|
||||||
|
|
||||||
|
func (a *nriAPI) runPodSandbox(ctx context.Context, criPod *sstore.Sandbox) error {
|
||||||
|
pod := a.nriPodSandbox(criPod)
|
||||||
|
err := a.nri.RunPodSandbox(ctx, pod)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
a.nri.StopPodSandbox(ctx, pod)
|
||||||
|
a.nri.RemovePodSandbox(ctx, pod)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) stopPodSandbox(ctx context.Context, criPod *sstore.Sandbox) error {
|
||||||
|
pod := a.nriPodSandbox(criPod)
|
||||||
|
err := a.nri.StopPodSandbox(ctx, pod)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) removePodSandbox(ctx context.Context, criPod *sstore.Sandbox) error {
|
||||||
|
pod := a.nriPodSandbox(criPod)
|
||||||
|
|
||||||
|
err := a.nri.RemovePodSandbox(ctx, pod)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) createContainer(ctx context.Context, ctrs *containers.Container, spec *specs.Spec) (*api.ContainerAdjustment, error) {
|
||||||
|
ctr := a.nriContainer(ctrs, spec)
|
||||||
|
|
||||||
|
criPod, err := a.cri.sandboxStore.Get(ctr.GetPodSandboxID())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pod := a.nriPodSandbox(&criPod)
|
||||||
|
|
||||||
|
adjust, err := a.nri.CreateContainer(ctx, pod, ctr)
|
||||||
|
|
||||||
|
return adjust, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) postCreateContainer(ctx context.Context, criPod *sstore.Sandbox, criCtr *cstore.Container) error {
|
||||||
|
pod := a.nriPodSandbox(criPod)
|
||||||
|
ctr := a.nriContainer(criCtr, nil)
|
||||||
|
|
||||||
|
err := a.nri.PostCreateContainer(ctx, pod, ctr)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) startContainer(ctx context.Context, criPod *sstore.Sandbox, criCtr *cstore.Container) error {
|
||||||
|
pod := a.nriPodSandbox(criPod)
|
||||||
|
ctr := a.nriContainer(criCtr, nil)
|
||||||
|
|
||||||
|
err := a.nri.StartContainer(ctx, pod, ctr)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) postStartContainer(ctx context.Context, criPod *sstore.Sandbox, criCtr *cstore.Container) error {
|
||||||
|
pod := a.nriPodSandbox(criPod)
|
||||||
|
ctr := a.nriContainer(criCtr, nil)
|
||||||
|
|
||||||
|
err := a.nri.PostStartContainer(ctx, pod, ctr)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) updateContainer(ctx context.Context, criPod *sstore.Sandbox, criCtr *cstore.Container, req *cri.LinuxContainerResources) (*cri.LinuxContainerResources, error) {
|
||||||
|
const noOomAdj = 0
|
||||||
|
|
||||||
|
pod := a.nriPodSandbox(criPod)
|
||||||
|
ctr := a.nriContainer(criCtr, nil)
|
||||||
|
|
||||||
|
r, err := a.nri.UpdateContainer(ctx, pod, ctr, api.FromCRILinuxResources(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.ToCRI(noOomAdj), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) postUpdateContainer(ctx context.Context, criPod *sstore.Sandbox, criCtr *cstore.Container) error {
|
||||||
|
pod := a.nriPodSandbox(criPod)
|
||||||
|
ctr := a.nriContainer(criCtr, nil)
|
||||||
|
|
||||||
|
err := a.nri.PostUpdateContainer(ctx, pod, ctr)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) stopContainer(ctx context.Context, criPod *sstore.Sandbox, criCtr *cstore.Container) error {
|
||||||
|
ctr := a.nriContainer(criCtr, nil)
|
||||||
|
|
||||||
|
if criPod == nil || criPod.ID == "" {
|
||||||
|
criPod = &sstore.Sandbox{
|
||||||
|
Metadata: sstore.Metadata{
|
||||||
|
ID: ctr.GetPodSandboxID(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pod := a.nriPodSandbox(criPod)
|
||||||
|
|
||||||
|
err := a.nri.StopContainer(ctx, pod, ctr)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) notifyContainerExit(ctx context.Context, criCtr *cstore.Container) {
|
||||||
|
ctr := a.nriContainer(criCtr, nil)
|
||||||
|
|
||||||
|
criPod, _ := a.cri.sandboxStore.Get(ctr.GetPodSandboxID())
|
||||||
|
if criPod.ID == "" {
|
||||||
|
criPod = sstore.Sandbox{
|
||||||
|
Metadata: sstore.Metadata{
|
||||||
|
ID: ctr.GetPodSandboxID(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pod := a.nriPodSandbox(&criPod)
|
||||||
|
|
||||||
|
a.nri.NotifyContainerExit(ctx, pod, ctr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) removeContainer(ctx context.Context, criPod *sstore.Sandbox, criCtr *cstore.Container) error {
|
||||||
|
pod := a.nriPodSandbox(criPod)
|
||||||
|
ctr := a.nriContainer(criCtr, nil)
|
||||||
|
|
||||||
|
err := a.nri.RemoveContainer(ctx, pod, ctr)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) undoCreateContainer(ctx context.Context, criPod *sstore.Sandbox, id string, spec *specs.Spec) {
|
||||||
|
pod := a.nriPodSandbox(criPod)
|
||||||
|
ctr := a.nriContainer(&containers.Container{ID: id}, spec)
|
||||||
|
|
||||||
|
err := a.nri.StopContainer(ctx, pod, ctr)
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Error("container creation undo (stop) failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = a.nri.RemoveContainer(ctx, pod, ctr)
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Error("container creation undo (remove) failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) WithContainerAdjustment() containerd.NewContainerOpts {
|
||||||
|
resourceCheckOpt := nrigen.WithResourceChecker(
|
||||||
|
func(r *runtimespec.LinuxResources) error {
|
||||||
|
if r != nil {
|
||||||
|
if a.cri.config.DisableHugetlbController {
|
||||||
|
r.HugepageLimits = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
rdtResolveOpt := nrigen.WithRdtResolver(
|
||||||
|
func(className string) (*runtimespec.LinuxIntelRdt, error) {
|
||||||
|
if className == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return &runtimespec.LinuxIntelRdt{
|
||||||
|
ClosID: className,
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
blkioResolveOpt := nrigen.WithBlockIOResolver(
|
||||||
|
func(className string) (*runtimespec.LinuxBlockIO, error) {
|
||||||
|
if className == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
blockIO, err := blockIOToLinuxOci(className)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return blockIO, nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return func(ctx context.Context, _ *containerd.Client, c *containers.Container) error {
|
||||||
|
spec := &specs.Spec{}
|
||||||
|
if err := json.Unmarshal(c.Spec.GetValue(), spec); err != nil {
|
||||||
|
return fmt.Errorf("failed to unmarshal container OCI Spec for NRI: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
adjust, err := a.createContainer(ctx, c, spec)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get NRI adjustment for container: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sgen := generate.Generator{Config: spec}
|
||||||
|
ngen := nrigen.SpecGenerator(&sgen, resourceCheckOpt, rdtResolveOpt, blkioResolveOpt)
|
||||||
|
|
||||||
|
err = ngen.Adjust(adjust)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to NRI-adjust container Spec: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
adjusted, err := typeurl.MarshalAny(spec)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to marshal NRI-adjusted Spec: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Spec = adjusted
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) WithContainerExit(criCtr *cstore.Container) containerd.ProcessDeleteOpts {
|
||||||
|
if !a.isEnabled() {
|
||||||
|
return func(_ context.Context, _ containerd.Process) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(_ context.Context, _ containerd.Process) error {
|
||||||
|
a.notifyContainerExit(context.Background(), criCtr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// NRI-CRI 'domain' interface
|
||||||
|
//
|
||||||
|
// These functions are used to interface CRI pods and containers
|
||||||
|
// from the common NRI interface. They implement pod and container
|
||||||
|
// discovery, lookup and updating of container parameters.
|
||||||
|
//
|
||||||
|
|
||||||
|
const (
|
||||||
|
nriDomain = constants.K8sContainerdNamespace
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *nriAPI) GetName() string {
|
||||||
|
return nriDomain
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) ListPodSandboxes() []nri.PodSandbox {
|
||||||
|
pods := []nri.PodSandbox{}
|
||||||
|
for _, pod := range a.cri.sandboxStore.List() {
|
||||||
|
if pod.Status.Get().State != sstore.StateUnknown {
|
||||||
|
pod := pod
|
||||||
|
pods = append(pods, a.nriPodSandbox(&pod))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pods
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) ListContainers() []nri.Container {
|
||||||
|
containers := []nri.Container{}
|
||||||
|
for _, ctr := range a.cri.containerStore.List() {
|
||||||
|
switch ctr.Status.Get().State() {
|
||||||
|
case cri.ContainerState_CONTAINER_EXITED:
|
||||||
|
continue
|
||||||
|
case cri.ContainerState_CONTAINER_UNKNOWN:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ctr := ctr
|
||||||
|
containers = append(containers, a.nriContainer(&ctr, nil))
|
||||||
|
}
|
||||||
|
return containers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) GetPodSandbox(id string) (nri.PodSandbox, bool) {
|
||||||
|
pod, err := a.cri.sandboxStore.Get(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.nriPodSandbox(&pod), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) GetContainer(id string) (nri.Container, bool) {
|
||||||
|
ctr, err := a.cri.containerStore.Get(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.nriContainer(&ctr, nil), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) UpdateContainer(ctx context.Context, u *api.ContainerUpdate) error {
|
||||||
|
ctr, err := a.cri.containerStore.Get(u.ContainerId)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ctr.Status.UpdateSync(
|
||||||
|
func(status cstore.Status) (cstore.Status, error) {
|
||||||
|
criReq := &cri.UpdateContainerResourcesRequest{
|
||||||
|
ContainerId: u.ContainerId,
|
||||||
|
Linux: u.GetLinux().GetResources().ToCRI(0),
|
||||||
|
}
|
||||||
|
newStatus, err := a.cri.updateContainerResources(ctx, ctr, criReq, status)
|
||||||
|
return newStatus, err
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
if !u.IgnoreFailure {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) EvictContainer(ctx context.Context, e *api.ContainerEviction) error {
|
||||||
|
ctr, err := a.cri.containerStore.Get(e.ContainerId)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err = a.cri.stopContainer(ctx, ctr, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// NRI integration wrapper for CRI Pods
|
||||||
|
//
|
||||||
|
|
||||||
|
type criPodSandbox struct {
|
||||||
|
*sstore.Sandbox
|
||||||
|
spec *specs.Spec
|
||||||
|
pid uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) nriPodSandbox(pod *sstore.Sandbox) *criPodSandbox {
|
||||||
|
criPod := &criPodSandbox{
|
||||||
|
Sandbox: pod,
|
||||||
|
spec: &specs.Spec{},
|
||||||
|
}
|
||||||
|
|
||||||
|
if pod == nil || pod.Container == nil {
|
||||||
|
return criPod
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := ctrdutil.NamespacedContext()
|
||||||
|
task, err := pod.Container.Task(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
if !errdefs.IsNotFound(err) {
|
||||||
|
log.L.WithError(err).Errorf("failed to get task for sandbox container %s",
|
||||||
|
pod.Container.ID())
|
||||||
|
}
|
||||||
|
return criPod
|
||||||
|
}
|
||||||
|
|
||||||
|
criPod.pid = task.Pid()
|
||||||
|
spec, err := task.Spec(ctx)
|
||||||
|
if err != nil {
|
||||||
|
if err != nil {
|
||||||
|
log.L.WithError(err).Errorf("failed to get spec for sandbox container %s",
|
||||||
|
pod.Container.ID())
|
||||||
|
}
|
||||||
|
return criPod
|
||||||
|
}
|
||||||
|
|
||||||
|
criPod.spec = spec
|
||||||
|
|
||||||
|
return criPod
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetDomain() string {
|
||||||
|
return nriDomain
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetID() string {
|
||||||
|
if p.Sandbox == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return p.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetName() string {
|
||||||
|
if p.Sandbox == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return p.Config.GetMetadata().GetName()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetUID() string {
|
||||||
|
if p.Sandbox == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return p.Config.GetMetadata().GetUid()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetNamespace() string {
|
||||||
|
if p.Sandbox == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return p.Config.GetMetadata().GetNamespace()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetAnnotations() map[string]string {
|
||||||
|
if p.Sandbox == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
annotations := map[string]string{}
|
||||||
|
|
||||||
|
for key, value := range p.Config.GetAnnotations() {
|
||||||
|
annotations[key] = value
|
||||||
|
}
|
||||||
|
for key, value := range p.spec.Annotations {
|
||||||
|
annotations[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
return annotations
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetLabels() map[string]string {
|
||||||
|
if p.Sandbox == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
labels := map[string]string{}
|
||||||
|
|
||||||
|
for key, value := range p.Config.GetLabels() {
|
||||||
|
labels[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Sandbox.Container == nil {
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := ctrdutil.NamespacedContext()
|
||||||
|
ctrd := p.Sandbox.Container
|
||||||
|
ctrs, err := ctrd.Info(ctx, containerd.WithoutRefreshedMetadata)
|
||||||
|
if err != nil {
|
||||||
|
log.L.WithError(err).Errorf("failed to get info for sandbox container %s", ctrd.ID())
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, value := range ctrs.Labels {
|
||||||
|
labels[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetRuntimeHandler() string {
|
||||||
|
if p.Sandbox == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return p.RuntimeHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetLinuxPodSandbox() nri.LinuxPodSandbox {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetLinuxNamespaces() []*api.LinuxNamespace {
|
||||||
|
if p.spec.Linux != nil {
|
||||||
|
return api.FromOCILinuxNamespaces(p.spec.Linux.Namespaces)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetPodLinuxOverhead() *api.LinuxResources {
|
||||||
|
if p.Sandbox == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return api.FromCRILinuxResources(p.Config.GetLinux().GetOverhead())
|
||||||
|
}
|
||||||
|
func (p *criPodSandbox) GetPodLinuxResources() *api.LinuxResources {
|
||||||
|
if p.Sandbox == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return api.FromCRILinuxResources(p.Config.GetLinux().GetResources())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetLinuxResources() *api.LinuxResources {
|
||||||
|
if p.spec.Linux == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return api.FromOCILinuxResources(p.spec.Linux.Resources, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetCgroupParent() string {
|
||||||
|
if p.Sandbox == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return p.Config.GetLinux().GetCgroupParent()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetCgroupsPath() string {
|
||||||
|
if p.spec.Linux == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return p.spec.Linux.CgroupsPath
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *criPodSandbox) GetPid() uint32 {
|
||||||
|
return p.pid
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// NRI integration wrapper for CRI Containers
|
||||||
|
//
|
||||||
|
|
||||||
|
type criContainer struct {
|
||||||
|
api *nriAPI
|
||||||
|
ctrs *containers.Container
|
||||||
|
spec *specs.Spec
|
||||||
|
meta *cstore.Metadata
|
||||||
|
pid uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) nriContainer(ctr interface{}, spec *specs.Spec) *criContainer {
|
||||||
|
switch c := ctr.(type) {
|
||||||
|
case *cstore.Container:
|
||||||
|
ctx := ctrdutil.NamespacedContext()
|
||||||
|
pid := uint32(0)
|
||||||
|
ctrd := c.Container
|
||||||
|
ctrs, err := ctrd.Info(ctx, containerd.WithoutRefreshedMetadata)
|
||||||
|
if err != nil {
|
||||||
|
log.L.WithError(err).Errorf("failed to get info for container %s", ctrd.ID())
|
||||||
|
}
|
||||||
|
spec, err := ctrd.Spec(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.L.WithError(err).Errorf("failed to get OCI Spec for container %s", ctrd.ID())
|
||||||
|
spec = &specs.Spec{}
|
||||||
|
}
|
||||||
|
task, err := ctrd.Task(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
if !errdefs.IsNotFound(err) {
|
||||||
|
log.L.WithError(err).Errorf("failed to get task for container %s", ctrd.ID())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pid = task.Pid()
|
||||||
|
}
|
||||||
|
|
||||||
|
return &criContainer{
|
||||||
|
api: a,
|
||||||
|
ctrs: &ctrs,
|
||||||
|
meta: &c.Metadata,
|
||||||
|
spec: spec,
|
||||||
|
pid: pid,
|
||||||
|
}
|
||||||
|
|
||||||
|
case *containers.Container:
|
||||||
|
ctrs := c
|
||||||
|
meta := &cstore.Metadata{}
|
||||||
|
if ext := ctrs.Extensions[containerMetadataExtension]; ext != nil {
|
||||||
|
err := typeurl.UnmarshalTo(ext, meta)
|
||||||
|
if err != nil {
|
||||||
|
log.L.WithError(err).Errorf("failed to get metadata for container %s", ctrs.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &criContainer{
|
||||||
|
api: a,
|
||||||
|
ctrs: ctrs,
|
||||||
|
meta: meta,
|
||||||
|
spec: spec,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.L.Errorf("can't wrap %T as NRI container", ctr)
|
||||||
|
return &criContainer{
|
||||||
|
api: a,
|
||||||
|
meta: &cstore.Metadata{},
|
||||||
|
spec: &specs.Spec{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetDomain() string {
|
||||||
|
return nriDomain
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetID() string {
|
||||||
|
if c.ctrs != nil {
|
||||||
|
return c.ctrs.ID
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetPodSandboxID() string {
|
||||||
|
return c.spec.Annotations[annotations.SandboxID]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetName() string {
|
||||||
|
return c.spec.Annotations[annotations.ContainerName]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetState() api.ContainerState {
|
||||||
|
criCtr, err := c.api.cri.containerStore.Get(c.GetID())
|
||||||
|
if err != nil {
|
||||||
|
return api.ContainerState_CONTAINER_UNKNOWN
|
||||||
|
}
|
||||||
|
switch criCtr.Status.Get().State() {
|
||||||
|
case cri.ContainerState_CONTAINER_CREATED:
|
||||||
|
return api.ContainerState_CONTAINER_CREATED
|
||||||
|
case cri.ContainerState_CONTAINER_RUNNING:
|
||||||
|
return api.ContainerState_CONTAINER_RUNNING
|
||||||
|
case cri.ContainerState_CONTAINER_EXITED:
|
||||||
|
return api.ContainerState_CONTAINER_STOPPED
|
||||||
|
}
|
||||||
|
|
||||||
|
return api.ContainerState_CONTAINER_UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetLabels() map[string]string {
|
||||||
|
if c.ctrs == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
labels := map[string]string{}
|
||||||
|
for key, value := range c.ctrs.Labels {
|
||||||
|
labels[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.meta != nil && c.meta.Config != nil {
|
||||||
|
for key, value := range c.meta.Config.Labels {
|
||||||
|
labels[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetAnnotations() map[string]string {
|
||||||
|
annotations := map[string]string{}
|
||||||
|
|
||||||
|
for key, value := range c.spec.Annotations {
|
||||||
|
annotations[key] = value
|
||||||
|
}
|
||||||
|
if c.meta != nil && c.meta.Config != nil {
|
||||||
|
for key, value := range c.meta.Config.Annotations {
|
||||||
|
annotations[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return annotations
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetArgs() []string {
|
||||||
|
if c.spec.Process == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return api.DupStringSlice(c.spec.Process.Args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetEnv() []string {
|
||||||
|
if c.spec.Process == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return api.DupStringSlice(c.spec.Process.Env)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetMounts() []*api.Mount {
|
||||||
|
return api.FromOCIMounts(c.spec.Mounts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetHooks() *api.Hooks {
|
||||||
|
return api.FromOCIHooks(c.spec.Hooks)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetLinuxContainer() nri.LinuxContainer {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetLinuxNamespaces() []*api.LinuxNamespace {
|
||||||
|
if c.spec.Linux == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return api.FromOCILinuxNamespaces(c.spec.Linux.Namespaces)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetLinuxDevices() []*api.LinuxDevice {
|
||||||
|
if c.spec.Linux == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return api.FromOCILinuxDevices(c.spec.Linux.Devices)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetLinuxResources() *api.LinuxResources {
|
||||||
|
if c.spec.Linux == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return api.FromOCILinuxResources(c.spec.Linux.Resources, c.spec.Annotations)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetOOMScoreAdj() *int {
|
||||||
|
if c.spec.Process == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.spec.Process.OOMScoreAdj
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetCgroupsPath() string {
|
||||||
|
if c.spec.Linux == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return c.spec.Linux.CgroupsPath
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criContainer) GetPid() uint32 {
|
||||||
|
return c.pid
|
||||||
|
}
|
134
pkg/cri/server/nri-api_other.go
Normal file
134
pkg/cri/server/nri-api_other.go
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
//go:build !linux
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/containerd/containerd/containers"
|
||||||
|
cstore "github.com/containerd/containerd/pkg/cri/store/container"
|
||||||
|
sstore "github.com/containerd/containerd/pkg/cri/store/sandbox"
|
||||||
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/pkg/cri/constants"
|
||||||
|
"github.com/containerd/containerd/pkg/nri"
|
||||||
|
|
||||||
|
"github.com/containerd/nri/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
type nriAPI struct {
|
||||||
|
cri *criService
|
||||||
|
nri nri.API
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) register() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *nriAPI) isEnabled() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// CRI-NRI lifecycle hook no-op interface
|
||||||
|
//
|
||||||
|
|
||||||
|
func (*nriAPI) runPodSandbox(context.Context, *sstore.Sandbox) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) stopPodSandbox(context.Context, *sstore.Sandbox) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) removePodSandbox(context.Context, *sstore.Sandbox) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) postCreateContainer(context.Context, *sstore.Sandbox, *cstore.Container) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) startContainer(context.Context, *sstore.Sandbox, *cstore.Container) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) postStartContainer(context.Context, *sstore.Sandbox, *cstore.Container) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) stopContainer(context.Context, *sstore.Sandbox, *cstore.Container) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) removeContainer(context.Context, *sstore.Sandbox, *cstore.Container) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) undoCreateContainer(context.Context, *sstore.Sandbox, string, *specs.Spec) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) WithContainerAdjustment() containerd.NewContainerOpts {
|
||||||
|
return func(ctx context.Context, _ *containerd.Client, c *containers.Container) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) WithContainerExit(*cstore.Container) containerd.ProcessDeleteOpts {
|
||||||
|
return func(_ context.Context, _ containerd.Process) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// NRI-CRI no-op 'domain' interface
|
||||||
|
//
|
||||||
|
|
||||||
|
const (
|
||||||
|
nriDomain = constants.K8sContainerdNamespace
|
||||||
|
)
|
||||||
|
|
||||||
|
func (*nriAPI) GetName() string {
|
||||||
|
return nriDomain
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) ListPodSandboxes() []nri.PodSandbox {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) ListContainers() []nri.Container {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) GetPodSandbox(string) (nri.PodSandbox, bool) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) GetContainer(string) (nri.Container, bool) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) UpdateContainer(context.Context, *api.ContainerUpdate) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) EvictContainer(context.Context, *api.ContainerEviction) error {
|
||||||
|
return nil
|
||||||
|
}
|
37
pkg/cri/server/nri-api_windows.go
Normal file
37
pkg/cri/server/nri-api_windows.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
cstore "github.com/containerd/containerd/pkg/cri/store/container"
|
||||||
|
sstore "github.com/containerd/containerd/pkg/cri/store/sandbox"
|
||||||
|
|
||||||
|
cri "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (*nriAPI) updateContainer(context.Context, *sstore.Sandbox, *cstore.Container, *cri.LinuxContainerResources) (*cri.LinuxContainerResources, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*nriAPI) postUpdateContainer(context.Context, *sstore.Sandbox, *cstore.Container) error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,51 +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 server
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/containerd/nri"
|
|
||||||
v1 "github.com/containerd/nri/types/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WithNRISandboxDelete calls delete for a sandbox'd task
|
|
||||||
func WithNRISandboxDelete(sandboxID string) containerd.ProcessDeleteOpts {
|
|
||||||
return func(ctx context.Context, p containerd.Process) error {
|
|
||||||
task, ok := p.(containerd.Task)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
nric, err := nri.New()
|
|
||||||
if err != nil {
|
|
||||||
log.G(ctx).WithError(err).Error("unable to create nri client")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if nric == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
sb := &nri.Sandbox{
|
|
||||||
ID: sandboxID,
|
|
||||||
}
|
|
||||||
if _, err := nric.InvokeWithSandbox(ctx, task, v1.Delete, sb); err != nil {
|
|
||||||
log.G(ctx).WithError(err).Errorf("Failed to delete nri for %q", task.ID())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
@ -101,6 +101,13 @@ func (c *criService) RemovePodSandbox(ctx context.Context, r *runtime.RemovePodS
|
|||||||
log.G(ctx).Tracef("Remove called for sandbox container %q that does not exist", id)
|
log.G(ctx).Tracef("Remove called for sandbox container %q that does not exist", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.nri.isEnabled() {
|
||||||
|
err = c.nri.removePodSandbox(ctx, &sandbox)
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Errorf("NRI pod removal notification failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove sandbox from sandbox store. Note that once the sandbox is successfully
|
// Remove sandbox from sandbox store. Note that once the sandbox is successfully
|
||||||
// deleted:
|
// deleted:
|
||||||
// 1) ListPodSandbox will not include this sandbox.
|
// 1) ListPodSandbox will not include this sandbox.
|
||||||
|
@ -28,8 +28,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
cni "github.com/containerd/go-cni"
|
cni "github.com/containerd/go-cni"
|
||||||
"github.com/containerd/nri"
|
|
||||||
v1 "github.com/containerd/nri/types/v1"
|
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
selinux "github.com/opencontainers/selinux/go-selinux"
|
selinux "github.com/opencontainers/selinux/go-selinux"
|
||||||
@ -346,7 +344,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
|||||||
deferCtx, deferCancel := ctrdutil.DeferContext()
|
deferCtx, deferCancel := ctrdutil.DeferContext()
|
||||||
defer deferCancel()
|
defer deferCancel()
|
||||||
// Cleanup the sandbox container if an error is returned.
|
// Cleanup the sandbox container if an error is returned.
|
||||||
if _, err := task.Delete(deferCtx, WithNRISandboxDelete(id), containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) {
|
if _, err := task.Delete(deferCtx, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) {
|
||||||
log.G(ctx).WithError(err).Errorf("Failed to delete sandbox container %q", id)
|
log.G(ctx).WithError(err).Errorf("Failed to delete sandbox container %q", id)
|
||||||
cleanupErr = err
|
cleanupErr = err
|
||||||
}
|
}
|
||||||
@ -359,18 +357,19 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
|||||||
return nil, fmt.Errorf("failed to wait for sandbox container task: %w", err)
|
return nil, fmt.Errorf("failed to wait for sandbox container task: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nric, err := nri.New()
|
if c.nri.isEnabled() {
|
||||||
if err != nil {
|
err = c.nri.runPodSandbox(ctx, &sandbox)
|
||||||
return nil, fmt.Errorf("unable to create nri client: %w", err)
|
if err != nil {
|
||||||
}
|
return nil, fmt.Errorf("NRI RunPodSandbox failed: %w", err)
|
||||||
if nric != nil {
|
|
||||||
nriSB := &nri.Sandbox{
|
|
||||||
ID: id,
|
|
||||||
Labels: config.Labels,
|
|
||||||
}
|
|
||||||
if _, err := nric.InvokeWithSandbox(ctx, task, v1.Create, nriSB); err != nil {
|
|
||||||
return nil, fmt.Errorf("nri invoke: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
deferCtx, deferCancel := ctrdutil.DeferContext()
|
||||||
|
defer deferCancel()
|
||||||
|
c.nri.removePodSandbox(deferCtx, &sandbox)
|
||||||
|
}
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := task.Start(ctx); err != nil {
|
if err := task.Start(ctx); err != nil {
|
||||||
|
@ -82,6 +82,13 @@ func (c *criService) stopPodSandbox(ctx context.Context, sandbox sandboxstore.Sa
|
|||||||
}
|
}
|
||||||
sandboxRuntimeStopTimer.WithValues(sandbox.RuntimeHandler).UpdateSince(stop)
|
sandboxRuntimeStopTimer.WithValues(sandbox.RuntimeHandler).UpdateSince(stop)
|
||||||
|
|
||||||
|
if c.nri.isEnabled() {
|
||||||
|
err := c.nri.stopPodSandbox(ctx, &sandbox)
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Errorf("NRI sandbox stop notification failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Teardown network for sandbox.
|
// Teardown network for sandbox.
|
||||||
if sandbox.NetNS != nil {
|
if sandbox.NetNS != nil {
|
||||||
netStop := time.Now()
|
netStop := time.Now()
|
||||||
@ -120,7 +127,7 @@ func (c *criService) stopSandboxContainer(ctx context.Context, sandbox sandboxst
|
|||||||
}
|
}
|
||||||
// Don't return for unknown state, some cleanup needs to be done.
|
// Don't return for unknown state, some cleanup needs to be done.
|
||||||
if state == sandboxstore.StateUnknown {
|
if state == sandboxstore.StateUnknown {
|
||||||
return cleanupUnknownSandbox(ctx, id, sandbox)
|
return c.cleanupUnknownSandbox(ctx, id, sandbox)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -136,7 +143,7 @@ func (c *criService) stopSandboxContainer(ctx context.Context, sandbox sandboxst
|
|||||||
if !errdefs.IsNotFound(err) {
|
if !errdefs.IsNotFound(err) {
|
||||||
return fmt.Errorf("failed to wait for task: %w", err)
|
return fmt.Errorf("failed to wait for task: %w", err)
|
||||||
}
|
}
|
||||||
return cleanupUnknownSandbox(ctx, id, sandbox)
|
return c.cleanupUnknownSandbox(ctx, id, sandbox)
|
||||||
}
|
}
|
||||||
|
|
||||||
exitCtx, exitCancel := context.WithCancel(context.Background())
|
exitCtx, exitCancel := context.WithCancel(context.Background())
|
||||||
@ -190,7 +197,7 @@ func (c *criService) teardownPodNetwork(ctx context.Context, sandbox sandboxstor
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cleanupUnknownSandbox cleanup stopped sandbox in unknown state.
|
// cleanupUnknownSandbox cleanup stopped sandbox in unknown state.
|
||||||
func cleanupUnknownSandbox(ctx context.Context, id string, sandbox sandboxstore.Sandbox) error {
|
func (c *criService) cleanupUnknownSandbox(ctx context.Context, id string, sandbox sandboxstore.Sandbox) error {
|
||||||
// Reuse handleSandboxExit to do the cleanup.
|
// Reuse handleSandboxExit to do the cleanup.
|
||||||
return handleSandboxExit(ctx, &eventtypes.TaskExit{
|
return handleSandboxExit(ctx, &eventtypes.TaskExit{
|
||||||
ContainerID: id,
|
ContainerID: id,
|
||||||
@ -198,5 +205,5 @@ func cleanupUnknownSandbox(ctx context.Context, id string, sandbox sandboxstore.
|
|||||||
Pid: 0,
|
Pid: 0,
|
||||||
ExitStatus: unknownExitCode,
|
ExitStatus: unknownExitCode,
|
||||||
ExitedAt: protobuf.ToTimestamp(time.Now()),
|
ExitedAt: protobuf.ToTimestamp(time.Now()),
|
||||||
}, sandbox)
|
}, sandbox, c)
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ import (
|
|||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
"github.com/containerd/containerd/pkg/cri/streaming"
|
"github.com/containerd/containerd/pkg/cri/streaming"
|
||||||
"github.com/containerd/containerd/pkg/kmutex"
|
"github.com/containerd/containerd/pkg/kmutex"
|
||||||
|
"github.com/containerd/containerd/pkg/nri"
|
||||||
"github.com/containerd/containerd/plugin"
|
"github.com/containerd/containerd/plugin"
|
||||||
runtime_alpha "github.com/containerd/containerd/third_party/k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime_alpha "github.com/containerd/containerd/third_party/k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
cni "github.com/containerd/go-cni"
|
cni "github.com/containerd/go-cni"
|
||||||
@ -67,6 +68,7 @@ type grpcAlphaServices interface {
|
|||||||
// CRIService is the interface implement CRI remote service server.
|
// CRIService is the interface implement CRI remote service server.
|
||||||
type CRIService interface {
|
type CRIService interface {
|
||||||
Run() error
|
Run() error
|
||||||
|
|
||||||
// io.Closer is used by containerd to gracefully stop cri service.
|
// io.Closer is used by containerd to gracefully stop cri service.
|
||||||
io.Closer
|
io.Closer
|
||||||
Register(*grpc.Server) error
|
Register(*grpc.Server) error
|
||||||
@ -118,10 +120,12 @@ type criService struct {
|
|||||||
// one in-flight fetch request or unpack handler for a given descriptor's
|
// one in-flight fetch request or unpack handler for a given descriptor's
|
||||||
// or chain ID.
|
// or chain ID.
|
||||||
unpackDuplicationSuppressor kmutex.KeyedLocker
|
unpackDuplicationSuppressor kmutex.KeyedLocker
|
||||||
|
|
||||||
|
nri *nriAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCRIService returns a new instance of CRIService
|
// NewCRIService returns a new instance of CRIService
|
||||||
func NewCRIService(config criconfig.Config, client *containerd.Client) (CRIService, error) {
|
func NewCRIService(config criconfig.Config, client *containerd.Client, nrip nri.API) (CRIService, error) {
|
||||||
var err error
|
var err error
|
||||||
labels := label.NewStore()
|
labels := label.NewStore()
|
||||||
c := &criService{
|
c := &criService{
|
||||||
@ -181,6 +185,13 @@ func NewCRIService(config criconfig.Config, client *containerd.Client) (CRIServi
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if nrip != nil {
|
||||||
|
c.nri = &nriAPI{
|
||||||
|
cri: c,
|
||||||
|
nri: nrip,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +260,8 @@ func (c *criService) Run() error {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
c.nri.register()
|
||||||
|
|
||||||
// Set the server as initialized. GRPC services could start serving traffic.
|
// Set the server as initialized. GRPC services could start serving traffic.
|
||||||
c.initialized.Set()
|
c.initialized.Set()
|
||||||
|
|
||||||
|
58
pkg/nri/config.go
Normal file
58
pkg/nri/config.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
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 nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config data for NRI.
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultConfig returns the default configuration.
|
||||||
|
func DefaultConfig() *Config {
|
||||||
|
return &Config{
|
||||||
|
Disable: true,
|
||||||
|
ConfigPath: nri.DefaultConfigPath,
|
||||||
|
SocketPath: nri.DefaultSocketPath,
|
||||||
|
PluginPath: nri.DefaultPluginPath,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
}
|
||||||
|
return opts
|
||||||
|
}
|
72
pkg/nri/container.go
Normal file
72
pkg/nri/container.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
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 nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Container interface for interacting with NRI.
|
||||||
|
type Container interface {
|
||||||
|
GetDomain() string
|
||||||
|
|
||||||
|
GetPodSandboxID() string
|
||||||
|
GetID() string
|
||||||
|
GetName() string
|
||||||
|
GetState() nri.ContainerState
|
||||||
|
GetLabels() map[string]string
|
||||||
|
GetAnnotations() map[string]string
|
||||||
|
GetArgs() []string
|
||||||
|
GetEnv() []string
|
||||||
|
GetMounts() []*nri.Mount
|
||||||
|
GetHooks() *nri.Hooks
|
||||||
|
GetLinuxContainer() LinuxContainer
|
||||||
|
|
||||||
|
GetPid() uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type LinuxContainer interface {
|
||||||
|
GetLinuxNamespaces() []*nri.LinuxNamespace
|
||||||
|
GetLinuxDevices() []*nri.LinuxDevice
|
||||||
|
GetLinuxResources() *nri.LinuxResources
|
||||||
|
GetOOMScoreAdj() *int
|
||||||
|
GetCgroupsPath() string
|
||||||
|
}
|
||||||
|
|
||||||
|
func commonContainerToNRI(ctr Container) *nri.Container {
|
||||||
|
return &nri.Container{
|
||||||
|
Id: ctr.GetID(),
|
||||||
|
PodSandboxId: ctr.GetPodSandboxID(),
|
||||||
|
Name: ctr.GetName(),
|
||||||
|
State: ctr.GetState(),
|
||||||
|
Labels: ctr.GetLabels(),
|
||||||
|
Annotations: ctr.GetAnnotations(),
|
||||||
|
Args: ctr.GetArgs(),
|
||||||
|
Env: ctr.GetEnv(),
|
||||||
|
Mounts: ctr.GetMounts(),
|
||||||
|
Hooks: ctr.GetHooks(),
|
||||||
|
Pid: ctr.GetPid(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func containersToNRI(ctrList []Container) []*nri.Container {
|
||||||
|
ctrs := []*nri.Container{}
|
||||||
|
for _, ctr := range ctrList {
|
||||||
|
ctrs = append(ctrs, containerToNRI(ctr))
|
||||||
|
}
|
||||||
|
return ctrs
|
||||||
|
}
|
37
pkg/nri/container_linux.go
Normal file
37
pkg/nri/container_linux.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
func containerToNRI(ctr Container) *nri.Container {
|
||||||
|
nriCtr := commonContainerToNRI(ctr)
|
||||||
|
lnxCtr := ctr.GetLinuxContainer()
|
||||||
|
nriCtr.Linux = &nri.LinuxContainer{
|
||||||
|
Namespaces: lnxCtr.GetLinuxNamespaces(),
|
||||||
|
Devices: lnxCtr.GetLinuxDevices(),
|
||||||
|
Resources: lnxCtr.GetLinuxResources(),
|
||||||
|
OomScoreAdj: nri.Int(lnxCtr.GetOOMScoreAdj()),
|
||||||
|
CgroupsPath: lnxCtr.GetCgroupsPath(),
|
||||||
|
}
|
||||||
|
return nriCtr
|
||||||
|
}
|
28
pkg/nri/container_other.go
Normal file
28
pkg/nri/container_other.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//go:build !linux
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
func containerToNRI(ctr Container) *nri.Container {
|
||||||
|
return commonContainerToNRI(ctr)
|
||||||
|
}
|
183
pkg/nri/domain.go
Normal file
183
pkg/nri/domain.go
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
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 nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/containerd/containerd/namespaces"
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Domain implements the functions the generic NRI interface needs to
|
||||||
|
// deal with pods and containers from a particular containerd namespace.
|
||||||
|
type Domain interface {
|
||||||
|
// GetName() returns the containerd namespace for this domain.
|
||||||
|
GetName() string
|
||||||
|
|
||||||
|
// ListPodSandboxes list all pods in this namespace.
|
||||||
|
ListPodSandboxes() []PodSandbox
|
||||||
|
|
||||||
|
// ListContainer list all containers in this namespace.
|
||||||
|
ListContainers() []Container
|
||||||
|
|
||||||
|
// GetPodSandbox returns the pod for the given ID.
|
||||||
|
GetPodSandbox(string) (PodSandbox, bool)
|
||||||
|
|
||||||
|
// GetContainer returns the container for the given ID.
|
||||||
|
GetContainer(string) (Container, bool)
|
||||||
|
|
||||||
|
// UpdateContainer applies an NRI container update request in the namespace.
|
||||||
|
UpdateContainer(context.Context, *nri.ContainerUpdate) error
|
||||||
|
|
||||||
|
// EvictContainer evicts the requested container in the namespace.
|
||||||
|
EvictContainer(context.Context, *nri.ContainerEviction) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterDomain registers an NRI domain for a containerd namespace.
|
||||||
|
func RegisterDomain(d Domain) {
|
||||||
|
err := domains.add(d)
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithError(err).Fatalf("Failed to register namespace %q with NRI", d.GetName())
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Infof("Registered namespace %q with NRI", d.GetName())
|
||||||
|
}
|
||||||
|
|
||||||
|
type domainTable struct {
|
||||||
|
sync.Mutex
|
||||||
|
domains map[string]Domain
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *domainTable) add(d Domain) error {
|
||||||
|
t.Lock()
|
||||||
|
defer t.Unlock()
|
||||||
|
|
||||||
|
namespace := d.GetName()
|
||||||
|
|
||||||
|
if _, ok := t.domains[namespace]; ok {
|
||||||
|
return errdefs.ErrAlreadyExists
|
||||||
|
}
|
||||||
|
|
||||||
|
t.domains[namespace] = d
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *domainTable) listPodSandboxes() []PodSandbox {
|
||||||
|
var pods []PodSandbox
|
||||||
|
|
||||||
|
t.Lock()
|
||||||
|
defer t.Unlock()
|
||||||
|
|
||||||
|
for _, d := range t.domains {
|
||||||
|
pods = append(pods, d.ListPodSandboxes()...)
|
||||||
|
}
|
||||||
|
return pods
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *domainTable) listContainers() []Container {
|
||||||
|
var ctrs []Container
|
||||||
|
|
||||||
|
t.Lock()
|
||||||
|
defer t.Unlock()
|
||||||
|
|
||||||
|
for _, d := range t.domains {
|
||||||
|
ctrs = append(ctrs, d.ListContainers()...)
|
||||||
|
}
|
||||||
|
return ctrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *domainTable) getContainer(id string) (Container, Domain) {
|
||||||
|
t.Lock()
|
||||||
|
defer t.Unlock()
|
||||||
|
|
||||||
|
// TODO(klihub): Are ID conflicts across namespaces possible ? Probably...
|
||||||
|
|
||||||
|
for _, d := range t.domains {
|
||||||
|
if ctr, ok := d.GetContainer(id); ok {
|
||||||
|
return ctr, d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *domainTable) updateContainers(ctx context.Context, updates []*nri.ContainerUpdate) ([]*nri.ContainerUpdate, error) {
|
||||||
|
var failed []*nri.ContainerUpdate
|
||||||
|
|
||||||
|
for _, u := range updates {
|
||||||
|
_, d := t.getContainer(u.ContainerId)
|
||||||
|
if d == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
domain := d.GetName()
|
||||||
|
err := d.UpdateContainer(namespaces.WithNamespace(ctx, domain), u)
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Errorf("NRI update of %s container %s failed",
|
||||||
|
domain, u.ContainerId)
|
||||||
|
if !u.IgnoreFailure {
|
||||||
|
failed = append(failed, u)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log.G(ctx).Tracef("NRI update of %s container %s successful", domain, u.ContainerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(failed) != 0 {
|
||||||
|
return failed, fmt.Errorf("NRI update of some containers failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *domainTable) evictContainers(ctx context.Context, evict []*nri.ContainerEviction) ([]*nri.ContainerEviction, error) {
|
||||||
|
var failed []*nri.ContainerEviction
|
||||||
|
|
||||||
|
for _, e := range evict {
|
||||||
|
_, d := t.getContainer(e.ContainerId)
|
||||||
|
if d == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
domain := d.GetName()
|
||||||
|
err := d.EvictContainer(namespaces.WithNamespace(ctx, domain), e)
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Errorf("NRI eviction of %s container %s failed",
|
||||||
|
domain, e.ContainerId)
|
||||||
|
failed = append(failed, e)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log.G(ctx).Tracef("NRI eviction of %s container %s successful", domain, e.ContainerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(failed) != 0 {
|
||||||
|
return failed, fmt.Errorf("NRI eviction of some containers failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var domains = &domainTable{
|
||||||
|
domains: make(map[string]Domain),
|
||||||
|
}
|
525
pkg/nri/nri.go
Normal file
525
pkg/nri/nri.go
Normal file
@ -0,0 +1,525 @@
|
|||||||
|
/*
|
||||||
|
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 nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"path"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/version"
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// API implements a common API for interfacing NRI from containerd. It is
|
||||||
|
// agnostic to any internal containerd implementation details of pods and
|
||||||
|
// containers. It needs corresponding Domain interfaces for each containerd
|
||||||
|
// namespace it needs to handle. These domains take care of the namespace-
|
||||||
|
// specific details of providing pod and container metadata to NRI and of
|
||||||
|
// applying NRI-requested adjustments to the state of containers.
|
||||||
|
type API interface {
|
||||||
|
// IsEnabled returns true if the NRI interface is enabled and initialized.
|
||||||
|
IsEnabled() bool
|
||||||
|
|
||||||
|
// Start start the NRI interface, allowing external NRI plugins to
|
||||||
|
// connect, register, and hook themselves into the lifecycle events
|
||||||
|
// of pods and containers.
|
||||||
|
Start() error
|
||||||
|
|
||||||
|
// Stop stops the NRI interface.
|
||||||
|
Stop()
|
||||||
|
|
||||||
|
// RunPodSandbox relays pod creation events to NRI.
|
||||||
|
RunPodSandbox(context.Context, PodSandbox) error
|
||||||
|
|
||||||
|
// StopPodSandbox relays pod shutdown events to NRI.
|
||||||
|
StopPodSandbox(context.Context, PodSandbox) error
|
||||||
|
|
||||||
|
// RemovePodSandbox relays pod removal events to NRI.
|
||||||
|
RemovePodSandbox(context.Context, PodSandbox) error
|
||||||
|
|
||||||
|
// CreateContainer relays container creation requests to NRI.
|
||||||
|
CreateContainer(context.Context, PodSandbox, Container) (*nri.ContainerAdjustment, error)
|
||||||
|
|
||||||
|
// PostCreateContainer relays successful container creation events to NRI.
|
||||||
|
PostCreateContainer(context.Context, PodSandbox, Container) error
|
||||||
|
|
||||||
|
// StartContainer relays container start request notifications to NRI.
|
||||||
|
StartContainer(context.Context, PodSandbox, Container) error
|
||||||
|
|
||||||
|
// PostStartContainer relays successful container startup events to NRI.
|
||||||
|
PostStartContainer(context.Context, PodSandbox, Container) error
|
||||||
|
|
||||||
|
// UpdateContainer relays container update requests to NRI.
|
||||||
|
UpdateContainer(context.Context, PodSandbox, Container, *nri.LinuxResources) (*nri.LinuxResources, error)
|
||||||
|
|
||||||
|
// PostUpdateContainer relays successful container update events to NRI.
|
||||||
|
PostUpdateContainer(context.Context, PodSandbox, Container) error
|
||||||
|
|
||||||
|
// StopContainer relays container stop requests to NRI.
|
||||||
|
StopContainer(context.Context, PodSandbox, Container) error
|
||||||
|
|
||||||
|
// NotifyContainerExit handles the exit event of a container.
|
||||||
|
NotifyContainerExit(context.Context, PodSandbox, Container)
|
||||||
|
|
||||||
|
// StopContainer relays container removal events to NRI.
|
||||||
|
RemoveContainer(context.Context, PodSandbox, Container) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type State int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Created State = iota + 1
|
||||||
|
Running
|
||||||
|
Stopped
|
||||||
|
Removed
|
||||||
|
)
|
||||||
|
|
||||||
|
type local struct {
|
||||||
|
sync.Mutex
|
||||||
|
cfg *Config
|
||||||
|
nri *nri.Adaptation
|
||||||
|
|
||||||
|
state map[string]State
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ API = &local{}
|
||||||
|
|
||||||
|
// New creates an instance of the NRI interface with the given configuration.
|
||||||
|
func New(cfg *Config) (API, error) {
|
||||||
|
l := &local{
|
||||||
|
cfg: cfg,
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.Disable {
|
||||||
|
logrus.Info("NRI interface is disabled by configuration.")
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
name = path.Base(version.Package)
|
||||||
|
version = version.Version
|
||||||
|
opts = cfg.toOptions()
|
||||||
|
syncFn = l.syncPlugin
|
||||||
|
updateFn = l.updateFromPlugin
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
l.nri, err = nri.New(name, version, syncFn, updateFn, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to initialize NRI interface: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
l.state = make(map[string]State)
|
||||||
|
|
||||||
|
logrus.Info("created NRI interface")
|
||||||
|
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) IsEnabled() bool {
|
||||||
|
return l != nil && !l.cfg.Disable
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) Start() error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.nri.Start()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to start NRI interface: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) Stop() {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
l.nri.Stop()
|
||||||
|
l.nri = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) RunPodSandbox(ctx context.Context, pod PodSandbox) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.RunPodSandboxRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.nri.RunPodSandbox(ctx, request)
|
||||||
|
l.setState(pod.GetID(), Running)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) StopPodSandbox(ctx context.Context, pod PodSandbox) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
if !l.needsStopping(pod.GetID()) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
request := &nri.StopPodSandboxRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.nri.StopPodSandbox(ctx, request)
|
||||||
|
l.setState(pod.GetID(), Stopped)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) RemovePodSandbox(ctx context.Context, pod PodSandbox) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
if !l.needsRemoval(pod.GetID()) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
request := &nri.RemovePodSandboxRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.nri.RemovePodSandbox(ctx, request)
|
||||||
|
l.setState(pod.GetID(), Removed)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) CreateContainer(ctx context.Context, pod PodSandbox, ctr Container) (*nri.ContainerAdjustment, error) {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.CreateContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := l.nri.CreateContainer(ctx, request)
|
||||||
|
l.setState(request.Container.Id, Created)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = l.evictContainers(ctx, response.Evict)
|
||||||
|
if err != nil {
|
||||||
|
// TODO(klihub): we ignore pre-create eviction failures for now
|
||||||
|
log.G(ctx).WithError(err).Warnf("pre-create eviction failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := l.applyUpdates(ctx, response.Update); err != nil {
|
||||||
|
// TODO(klihub): we ignore pre-create update failures for now
|
||||||
|
log.G(ctx).WithError(err).Warnf("pre-create update failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Adjust, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) PostCreateContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.PostCreateContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.nri.PostCreateContainer(ctx, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) StartContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.StartContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.nri.StartContainer(ctx, request)
|
||||||
|
l.setState(request.Container.Id, Running)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) PostStartContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.PostStartContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.nri.PostStartContainer(ctx, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) UpdateContainer(ctx context.Context, pod PodSandbox, ctr Container, req *nri.LinuxResources) (*nri.LinuxResources, error) {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.UpdateContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
LinuxResources: req,
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := l.nri.UpdateContainer(ctx, request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = l.evictContainers(ctx, response.Evict)
|
||||||
|
if err != nil {
|
||||||
|
// TODO(klihub): we ignore pre-update eviction failures for now
|
||||||
|
log.G(ctx).WithError(err).Warnf("pre-update eviction failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt := len(response.Update)
|
||||||
|
if cnt == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if cnt > 1 {
|
||||||
|
_, err = l.applyUpdates(ctx, response.Update[0:cnt-1])
|
||||||
|
if err != nil {
|
||||||
|
// TODO(klihub): we ignore pre-update update failures for now
|
||||||
|
log.G(ctx).WithError(err).Warnf("pre-update update failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Update[cnt-1].GetLinux().GetResources(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) PostUpdateContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.PostUpdateContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.nri.PostUpdateContainer(ctx, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) StopContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
return l.stopContainer(ctx, pod, ctr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) NotifyContainerExit(ctx context.Context, pod PodSandbox, ctr Container) {
|
||||||
|
go func() {
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
l.stopContainer(ctx, pod, ctr)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) stopContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.needsStopping(ctr.GetID()) {
|
||||||
|
log.G(ctx).Tracef("NRI stopContainer: container %s does not need stopping",
|
||||||
|
ctr.GetID())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
request := &nri.StopContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := l.nri.StopContainer(ctx, request)
|
||||||
|
l.setState(request.Container.Id, Stopped)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = l.applyUpdates(ctx, response.Update)
|
||||||
|
if err != nil {
|
||||||
|
// TODO(klihub): we ignore post-stop update failures for now
|
||||||
|
log.G(ctx).WithError(err).Warnf("post-stop update failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) RemoveContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
if !l.needsRemoval(ctr.GetID()) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.stopContainer(ctx, pod, ctr)
|
||||||
|
|
||||||
|
request := &nri.RemoveContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
err := l.nri.RemoveContainer(ctx, request)
|
||||||
|
l.setState(request.Container.Id, Removed)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) syncPlugin(ctx context.Context, syncFn nri.SyncCB) error {
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
log.G(ctx).Info("Synchronizing NRI (plugin) with current runtime state")
|
||||||
|
|
||||||
|
pods := podSandboxesToNRI(domains.listPodSandboxes())
|
||||||
|
containers := containersToNRI(domains.listContainers())
|
||||||
|
|
||||||
|
for _, ctr := range containers {
|
||||||
|
switch ctr.GetState() {
|
||||||
|
case nri.ContainerState_CONTAINER_CREATED:
|
||||||
|
l.setState(ctr.GetId(), Created)
|
||||||
|
case nri.ContainerState_CONTAINER_RUNNING, nri.ContainerState_CONTAINER_PAUSED:
|
||||||
|
l.setState(ctr.GetId(), Running)
|
||||||
|
case nri.ContainerState_CONTAINER_STOPPED:
|
||||||
|
l.setState(ctr.GetId(), Stopped)
|
||||||
|
default:
|
||||||
|
l.setState(ctr.GetId(), Removed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updates, err := syncFn(ctx, pods, containers)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = l.applyUpdates(ctx, updates)
|
||||||
|
if err != nil {
|
||||||
|
// TODO(klihub): we ignore post-sync update failures for now
|
||||||
|
log.G(ctx).WithError(err).Warnf("post-sync update failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) updateFromPlugin(ctx context.Context, req []*nri.ContainerUpdate) ([]*nri.ContainerUpdate, error) {
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
log.G(ctx).Trace("Unsolicited NRI container updates")
|
||||||
|
|
||||||
|
failed, err := l.applyUpdates(ctx, req)
|
||||||
|
return failed, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) applyUpdates(ctx context.Context, updates []*nri.ContainerUpdate) ([]*nri.ContainerUpdate, error) {
|
||||||
|
// TODO(klihub): should we pre-save state and attempt a rollback on failure ?
|
||||||
|
failed, err := domains.updateContainers(ctx, updates)
|
||||||
|
return failed, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) evictContainers(ctx context.Context, evict []*nri.ContainerEviction) ([]*nri.ContainerEviction, error) {
|
||||||
|
failed, err := domains.evictContainers(ctx, evict)
|
||||||
|
return failed, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) setState(id string, state State) {
|
||||||
|
if state != Removed {
|
||||||
|
l.state[id] = state
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(l.state, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) getState(id string) State {
|
||||||
|
if state, ok := l.state[id]; ok {
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
return Removed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) needsStopping(id string) bool {
|
||||||
|
s := l.getState(id)
|
||||||
|
if s == Created || s == Running {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) needsRemoval(id string) bool {
|
||||||
|
s := l.getState(id)
|
||||||
|
if s == Created || s == Running || s == Stopped {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
36
pkg/nri/plugin/plugin.go
Normal file
36
pkg/nri/plugin/plugin.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
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 plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containerd/containerd/pkg/nri"
|
||||||
|
"github.com/containerd/containerd/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
plugin.Register(&plugin.Registration{
|
||||||
|
Type: plugin.NRIApiPlugin,
|
||||||
|
ID: "nri",
|
||||||
|
Config: nri.DefaultConfig(),
|
||||||
|
InitFn: initFunc,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func initFunc(ic *plugin.InitContext) (interface{}, error) {
|
||||||
|
l, err := nri.New(ic.Config.(*nri.Config))
|
||||||
|
return l, err
|
||||||
|
}
|
67
pkg/nri/sandbox.go
Normal file
67
pkg/nri/sandbox.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
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 nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PodSandbox interface for interacting with NRI.
|
||||||
|
type PodSandbox interface {
|
||||||
|
GetDomain() string
|
||||||
|
|
||||||
|
GetID() string
|
||||||
|
GetName() string
|
||||||
|
GetUID() string
|
||||||
|
GetNamespace() string
|
||||||
|
GetLabels() map[string]string
|
||||||
|
GetAnnotations() map[string]string
|
||||||
|
GetRuntimeHandler() string
|
||||||
|
GetLinuxPodSandbox() LinuxPodSandbox
|
||||||
|
|
||||||
|
GetPid() uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type LinuxPodSandbox interface {
|
||||||
|
GetLinuxNamespaces() []*nri.LinuxNamespace
|
||||||
|
GetPodLinuxOverhead() *nri.LinuxResources
|
||||||
|
GetPodLinuxResources() *nri.LinuxResources
|
||||||
|
GetCgroupParent() string
|
||||||
|
GetCgroupsPath() string
|
||||||
|
GetLinuxResources() *nri.LinuxResources
|
||||||
|
}
|
||||||
|
|
||||||
|
func commonPodSandboxToNRI(pod PodSandbox) *nri.PodSandbox {
|
||||||
|
return &nri.PodSandbox{
|
||||||
|
Id: pod.GetID(),
|
||||||
|
Name: pod.GetName(),
|
||||||
|
Uid: pod.GetUID(),
|
||||||
|
Namespace: pod.GetNamespace(),
|
||||||
|
Labels: pod.GetLabels(),
|
||||||
|
Annotations: pod.GetAnnotations(),
|
||||||
|
RuntimeHandler: pod.GetRuntimeHandler(),
|
||||||
|
Pid: pod.GetPid(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func podSandboxesToNRI(podList []PodSandbox) []*nri.PodSandbox {
|
||||||
|
pods := []*nri.PodSandbox{}
|
||||||
|
for _, pod := range podList {
|
||||||
|
pods = append(pods, podSandboxToNRI(pod))
|
||||||
|
}
|
||||||
|
return pods
|
||||||
|
}
|
38
pkg/nri/sandbox_linux.go
Normal file
38
pkg/nri/sandbox_linux.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
func podSandboxToNRI(pod PodSandbox) *nri.PodSandbox {
|
||||||
|
nriPod := commonPodSandboxToNRI(pod)
|
||||||
|
lnxPod := pod.GetLinuxPodSandbox()
|
||||||
|
nriPod.Linux = &nri.LinuxPodSandbox{
|
||||||
|
Namespaces: lnxPod.GetLinuxNamespaces(),
|
||||||
|
PodOverhead: lnxPod.GetPodLinuxOverhead(),
|
||||||
|
PodResources: lnxPod.GetPodLinuxResources(),
|
||||||
|
CgroupParent: lnxPod.GetCgroupParent(),
|
||||||
|
CgroupsPath: lnxPod.GetCgroupsPath(),
|
||||||
|
Resources: lnxPod.GetLinuxResources(),
|
||||||
|
}
|
||||||
|
return nriPod
|
||||||
|
}
|
28
pkg/nri/sandbox_other.go
Normal file
28
pkg/nri/sandbox_other.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//go:build !linux
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
func podSandboxToNRI(pod PodSandbox) *nri.PodSandbox {
|
||||||
|
return commonPodSandboxToNRI(pod)
|
||||||
|
}
|
@ -80,6 +80,8 @@ const (
|
|||||||
LeasePlugin Type = "io.containerd.lease.v1"
|
LeasePlugin Type = "io.containerd.lease.v1"
|
||||||
// TracingProcessorPlugin implements a open telemetry span processor
|
// TracingProcessorPlugin implements a open telemetry span processor
|
||||||
TracingProcessorPlugin Type = "io.containerd.tracing.processor.v1"
|
TracingProcessorPlugin Type = "io.containerd.tracing.processor.v1"
|
||||||
|
// NRIApiPlugin implements the NRI adaptation interface for containerd.
|
||||||
|
NRIApiPlugin Type = "io.containerd.nri.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -51,6 +51,20 @@ EOF
|
|||||||
cat >>${config_file} <<EOF
|
cat >>${config_file} <<EOF
|
||||||
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
|
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
|
||||||
runtime_type = "${CONTAINERD_RUNTIME}"
|
runtime_type = "${CONTAINERD_RUNTIME}"
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
if [ $IS_WINDOWS -eq 0 ]; then
|
||||||
|
NRI_CONFIG_DIR="${CONTAINERD_CONFIG_DIR}/nri"
|
||||||
|
cat >>${config_file} <<EOF
|
||||||
|
[plugins."io.containerd.nri.v1.nri"]
|
||||||
|
disable = false
|
||||||
|
config_file = "${NRI_CONFIG_DIR}/nri.conf"
|
||||||
|
socket_path = "/var/run/nri-test.sock"
|
||||||
|
plugin_path = "/no/pre-launched/nri/plugins"
|
||||||
|
EOF
|
||||||
|
mkdir -p "${NRI_CONFIG_DIR}"
|
||||||
|
cat >"${NRI_CONFIG_DIR}/nri.conf" <<EOF
|
||||||
|
disableConnections: false
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
CONTAINERD_CONFIG_FILE="${config_file}"
|
CONTAINERD_CONFIG_FILE="${config_file}"
|
||||||
|
21
vendor/github.com/blang/semver/.travis.yml
generated
vendored
21
vendor/github.com/blang/semver/.travis.yml
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
language: go
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- go: 1.4.3
|
|
||||||
- go: 1.5.4
|
|
||||||
- go: 1.6.3
|
|
||||||
- go: 1.7
|
|
||||||
- go: tip
|
|
||||||
allow_failures:
|
|
||||||
- go: tip
|
|
||||||
install:
|
|
||||||
- go get golang.org/x/tools/cmd/cover
|
|
||||||
- go get github.com/mattn/goveralls
|
|
||||||
script:
|
|
||||||
- echo "Test and track coverage" ; $HOME/gopath/bin/goveralls -package "." -service=travis-ci
|
|
||||||
-repotoken $COVERALLS_TOKEN
|
|
||||||
- echo "Build examples" ; cd examples && go build
|
|
||||||
- echo "Check if gofmt'd" ; diff -u <(echo -n) <(gofmt -d -s .)
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
secure: HroGEAUQpVq9zX1b1VIkraLiywhGbzvNnTZq2TMxgK7JHP8xqNplAeF1izrR2i4QLL9nsY+9WtYss4QuPvEtZcVHUobw6XnL6radF7jS1LgfYZ9Y7oF+zogZ2I5QUMRLGA7rcxQ05s7mKq3XZQfeqaNts4bms/eZRefWuaFZbkw=
|
|
22
vendor/github.com/blang/semver/LICENSE
generated
vendored
22
vendor/github.com/blang/semver/LICENSE
generated
vendored
@ -1,22 +0,0 @@
|
|||||||
The MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2014 Benedikt Lang <github at benediktlang.de>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
|
|
194
vendor/github.com/blang/semver/README.md
generated
vendored
194
vendor/github.com/blang/semver/README.md
generated
vendored
@ -1,194 +0,0 @@
|
|||||||
semver for golang [](https://travis-ci.org/blang/semver) [](https://godoc.org/github.com/blang/semver) [](https://coveralls.io/r/blang/semver?branch=master)
|
|
||||||
======
|
|
||||||
|
|
||||||
semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`.
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
```bash
|
|
||||||
$ go get github.com/blang/semver
|
|
||||||
```
|
|
||||||
Note: Always vendor your dependencies or fix on a specific version tag.
|
|
||||||
|
|
||||||
```go
|
|
||||||
import github.com/blang/semver
|
|
||||||
v1, err := semver.Make("1.0.0-beta")
|
|
||||||
v2, err := semver.Make("2.0.0-beta")
|
|
||||||
v1.Compare(v2)
|
|
||||||
```
|
|
||||||
|
|
||||||
Also check the [GoDocs](http://godoc.org/github.com/blang/semver).
|
|
||||||
|
|
||||||
Why should I use this lib?
|
|
||||||
-----
|
|
||||||
|
|
||||||
- Fully spec compatible
|
|
||||||
- No reflection
|
|
||||||
- No regex
|
|
||||||
- Fully tested (Coverage >99%)
|
|
||||||
- Readable parsing/validation errors
|
|
||||||
- Fast (See [Benchmarks](#benchmarks))
|
|
||||||
- Only Stdlib
|
|
||||||
- Uses values instead of pointers
|
|
||||||
- Many features, see below
|
|
||||||
|
|
||||||
|
|
||||||
Features
|
|
||||||
-----
|
|
||||||
|
|
||||||
- Parsing and validation at all levels
|
|
||||||
- Comparator-like comparisons
|
|
||||||
- Compare Helper Methods
|
|
||||||
- InPlace manipulation
|
|
||||||
- Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1`
|
|
||||||
- Wildcards `>=1.x`, `<=2.5.x`
|
|
||||||
- Sortable (implements sort.Interface)
|
|
||||||
- database/sql compatible (sql.Scanner/Valuer)
|
|
||||||
- encoding/json compatible (json.Marshaler/Unmarshaler)
|
|
||||||
|
|
||||||
Ranges
|
|
||||||
------
|
|
||||||
|
|
||||||
A `Range` is a set of conditions which specify which versions satisfy the range.
|
|
||||||
|
|
||||||
A condition is composed of an operator and a version. The supported operators are:
|
|
||||||
|
|
||||||
- `<1.0.0` Less than `1.0.0`
|
|
||||||
- `<=1.0.0` Less than or equal to `1.0.0`
|
|
||||||
- `>1.0.0` Greater than `1.0.0`
|
|
||||||
- `>=1.0.0` Greater than or equal to `1.0.0`
|
|
||||||
- `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0`
|
|
||||||
- `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`.
|
|
||||||
|
|
||||||
Note that spaces between the operator and the version will be gracefully tolerated.
|
|
||||||
|
|
||||||
A `Range` can link multiple `Ranges` separated by space:
|
|
||||||
|
|
||||||
Ranges can be linked by logical AND:
|
|
||||||
|
|
||||||
- `>1.0.0 <2.0.0` would match between both ranges, so `1.1.1` and `1.8.7` but not `1.0.0` or `2.0.0`
|
|
||||||
- `>1.0.0 <3.0.0 !2.0.3-beta.2` would match every version between `1.0.0` and `3.0.0` except `2.0.3-beta.2`
|
|
||||||
|
|
||||||
Ranges can also be linked by logical OR:
|
|
||||||
|
|
||||||
- `<2.0.0 || >=3.0.0` would match `1.x.x` and `3.x.x` but not `2.x.x`
|
|
||||||
|
|
||||||
AND has a higher precedence than OR. It's not possible to use brackets.
|
|
||||||
|
|
||||||
Ranges can be combined by both AND and OR
|
|
||||||
|
|
||||||
- `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
|
|
||||||
|
|
||||||
Range usage:
|
|
||||||
|
|
||||||
```
|
|
||||||
v, err := semver.Parse("1.2.3")
|
|
||||||
range, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0")
|
|
||||||
if range(v) {
|
|
||||||
//valid
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Example
|
|
||||||
-----
|
|
||||||
|
|
||||||
Have a look at full examples in [examples/main.go](examples/main.go)
|
|
||||||
|
|
||||||
```go
|
|
||||||
import github.com/blang/semver
|
|
||||||
|
|
||||||
v, err := semver.Make("0.0.1-alpha.preview+123.github")
|
|
||||||
fmt.Printf("Major: %d\n", v.Major)
|
|
||||||
fmt.Printf("Minor: %d\n", v.Minor)
|
|
||||||
fmt.Printf("Patch: %d\n", v.Patch)
|
|
||||||
fmt.Printf("Pre: %s\n", v.Pre)
|
|
||||||
fmt.Printf("Build: %s\n", v.Build)
|
|
||||||
|
|
||||||
// Prerelease versions array
|
|
||||||
if len(v.Pre) > 0 {
|
|
||||||
fmt.Println("Prerelease versions:")
|
|
||||||
for i, pre := range v.Pre {
|
|
||||||
fmt.Printf("%d: %q\n", i, pre)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build meta data array
|
|
||||||
if len(v.Build) > 0 {
|
|
||||||
fmt.Println("Build meta data:")
|
|
||||||
for i, build := range v.Build {
|
|
||||||
fmt.Printf("%d: %q\n", i, build)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
v001, err := semver.Make("0.0.1")
|
|
||||||
// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE
|
|
||||||
v001.GT(v) == true
|
|
||||||
v.LT(v001) == true
|
|
||||||
v.GTE(v) == true
|
|
||||||
v.LTE(v) == true
|
|
||||||
|
|
||||||
// Or use v.Compare(v2) for comparisons (-1, 0, 1):
|
|
||||||
v001.Compare(v) == 1
|
|
||||||
v.Compare(v001) == -1
|
|
||||||
v.Compare(v) == 0
|
|
||||||
|
|
||||||
// Manipulate Version in place:
|
|
||||||
v.Pre[0], err = semver.NewPRVersion("beta")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error parsing pre release version: %q", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("\nValidate versions:")
|
|
||||||
v.Build[0] = "?"
|
|
||||||
|
|
||||||
err = v.Validate()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Validation failed: %s\n", err)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Benchmarks
|
|
||||||
-----
|
|
||||||
|
|
||||||
BenchmarkParseSimple-4 5000000 390 ns/op 48 B/op 1 allocs/op
|
|
||||||
BenchmarkParseComplex-4 1000000 1813 ns/op 256 B/op 7 allocs/op
|
|
||||||
BenchmarkParseAverage-4 1000000 1171 ns/op 163 B/op 4 allocs/op
|
|
||||||
BenchmarkStringSimple-4 20000000 119 ns/op 16 B/op 1 allocs/op
|
|
||||||
BenchmarkStringLarger-4 10000000 206 ns/op 32 B/op 2 allocs/op
|
|
||||||
BenchmarkStringComplex-4 5000000 324 ns/op 80 B/op 3 allocs/op
|
|
||||||
BenchmarkStringAverage-4 5000000 273 ns/op 53 B/op 2 allocs/op
|
|
||||||
BenchmarkValidateSimple-4 200000000 9.33 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkValidateComplex-4 3000000 469 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkValidateAverage-4 5000000 256 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkCompareSimple-4 100000000 11.8 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkCompareComplex-4 50000000 30.8 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkCompareAverage-4 30000000 41.5 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkSort-4 3000000 419 ns/op 256 B/op 2 allocs/op
|
|
||||||
BenchmarkRangeParseSimple-4 2000000 850 ns/op 192 B/op 5 allocs/op
|
|
||||||
BenchmarkRangeParseAverage-4 1000000 1677 ns/op 400 B/op 10 allocs/op
|
|
||||||
BenchmarkRangeParseComplex-4 300000 5214 ns/op 1440 B/op 30 allocs/op
|
|
||||||
BenchmarkRangeMatchSimple-4 50000000 25.6 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkRangeMatchAverage-4 30000000 56.4 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkRangeMatchComplex-4 10000000 153 ns/op 0 B/op 0 allocs/op
|
|
||||||
|
|
||||||
See benchmark cases at [semver_test.go](semver_test.go)
|
|
||||||
|
|
||||||
|
|
||||||
Motivation
|
|
||||||
-----
|
|
||||||
|
|
||||||
I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like.
|
|
||||||
|
|
||||||
|
|
||||||
Contribution
|
|
||||||
-----
|
|
||||||
|
|
||||||
Feel free to make a pull request. For bigger changes create a issue first to discuss about it.
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
-----
|
|
||||||
|
|
||||||
See [LICENSE](LICENSE) file.
|
|
23
vendor/github.com/blang/semver/json.go
generated
vendored
23
vendor/github.com/blang/semver/json.go
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
package semver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MarshalJSON implements the encoding/json.Marshaler interface.
|
|
||||||
func (v Version) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(v.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements the encoding/json.Unmarshaler interface.
|
|
||||||
func (v *Version) UnmarshalJSON(data []byte) (err error) {
|
|
||||||
var versionString string
|
|
||||||
|
|
||||||
if err = json.Unmarshal(data, &versionString); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
*v, err = Parse(versionString)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
17
vendor/github.com/blang/semver/package.json
generated
vendored
17
vendor/github.com/blang/semver/package.json
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"author": "blang",
|
|
||||||
"bugs": {
|
|
||||||
"URL": "https://github.com/blang/semver/issues",
|
|
||||||
"url": "https://github.com/blang/semver/issues"
|
|
||||||
},
|
|
||||||
"gx": {
|
|
||||||
"dvcsimport": "github.com/blang/semver"
|
|
||||||
},
|
|
||||||
"gxVersion": "0.10.0",
|
|
||||||
"language": "go",
|
|
||||||
"license": "MIT",
|
|
||||||
"name": "semver",
|
|
||||||
"releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
|
|
||||||
"version": "3.5.1"
|
|
||||||
}
|
|
||||||
|
|
416
vendor/github.com/blang/semver/range.go
generated
vendored
416
vendor/github.com/blang/semver/range.go
generated
vendored
@ -1,416 +0,0 @@
|
|||||||
package semver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
|
||||||
)
|
|
||||||
|
|
||||||
type wildcardType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
noneWildcard wildcardType = iota
|
|
||||||
majorWildcard wildcardType = 1
|
|
||||||
minorWildcard wildcardType = 2
|
|
||||||
patchWildcard wildcardType = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
func wildcardTypefromInt(i int) wildcardType {
|
|
||||||
switch i {
|
|
||||||
case 1:
|
|
||||||
return majorWildcard
|
|
||||||
case 2:
|
|
||||||
return minorWildcard
|
|
||||||
case 3:
|
|
||||||
return patchWildcard
|
|
||||||
default:
|
|
||||||
return noneWildcard
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type comparator func(Version, Version) bool
|
|
||||||
|
|
||||||
var (
|
|
||||||
compEQ comparator = func(v1 Version, v2 Version) bool {
|
|
||||||
return v1.Compare(v2) == 0
|
|
||||||
}
|
|
||||||
compNE = func(v1 Version, v2 Version) bool {
|
|
||||||
return v1.Compare(v2) != 0
|
|
||||||
}
|
|
||||||
compGT = func(v1 Version, v2 Version) bool {
|
|
||||||
return v1.Compare(v2) == 1
|
|
||||||
}
|
|
||||||
compGE = func(v1 Version, v2 Version) bool {
|
|
||||||
return v1.Compare(v2) >= 0
|
|
||||||
}
|
|
||||||
compLT = func(v1 Version, v2 Version) bool {
|
|
||||||
return v1.Compare(v2) == -1
|
|
||||||
}
|
|
||||||
compLE = func(v1 Version, v2 Version) bool {
|
|
||||||
return v1.Compare(v2) <= 0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
type versionRange struct {
|
|
||||||
v Version
|
|
||||||
c comparator
|
|
||||||
}
|
|
||||||
|
|
||||||
// rangeFunc creates a Range from the given versionRange.
|
|
||||||
func (vr *versionRange) rangeFunc() Range {
|
|
||||||
return Range(func(v Version) bool {
|
|
||||||
return vr.c(v, vr.v)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Range represents a range of versions.
|
|
||||||
// A Range can be used to check if a Version satisfies it:
|
|
||||||
//
|
|
||||||
// range, err := semver.ParseRange(">1.0.0 <2.0.0")
|
|
||||||
// range(semver.MustParse("1.1.1") // returns true
|
|
||||||
type Range func(Version) bool
|
|
||||||
|
|
||||||
// OR combines the existing Range with another Range using logical OR.
|
|
||||||
func (rf Range) OR(f Range) Range {
|
|
||||||
return Range(func(v Version) bool {
|
|
||||||
return rf(v) || f(v)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// AND combines the existing Range with another Range using logical AND.
|
|
||||||
func (rf Range) AND(f Range) Range {
|
|
||||||
return Range(func(v Version) bool {
|
|
||||||
return rf(v) && f(v)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseRange parses a range and returns a Range.
|
|
||||||
// If the range could not be parsed an error is returned.
|
|
||||||
//
|
|
||||||
// Valid ranges are:
|
|
||||||
// - "<1.0.0"
|
|
||||||
// - "<=1.0.0"
|
|
||||||
// - ">1.0.0"
|
|
||||||
// - ">=1.0.0"
|
|
||||||
// - "1.0.0", "=1.0.0", "==1.0.0"
|
|
||||||
// - "!1.0.0", "!=1.0.0"
|
|
||||||
//
|
|
||||||
// A Range can consist of multiple ranges separated by space:
|
|
||||||
// Ranges can be linked by logical AND:
|
|
||||||
// - ">1.0.0 <2.0.0" would match between both ranges, so "1.1.1" and "1.8.7" but not "1.0.0" or "2.0.0"
|
|
||||||
// - ">1.0.0 <3.0.0 !2.0.3-beta.2" would match every version between 1.0.0 and 3.0.0 except 2.0.3-beta.2
|
|
||||||
//
|
|
||||||
// Ranges can also be linked by logical OR:
|
|
||||||
// - "<2.0.0 || >=3.0.0" would match "1.x.x" and "3.x.x" but not "2.x.x"
|
|
||||||
//
|
|
||||||
// AND has a higher precedence than OR. It's not possible to use brackets.
|
|
||||||
//
|
|
||||||
// Ranges can be combined by both AND and OR
|
|
||||||
//
|
|
||||||
// - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
|
|
||||||
func ParseRange(s string) (Range, error) {
|
|
||||||
parts := splitAndTrim(s)
|
|
||||||
orParts, err := splitORParts(parts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
expandedParts, err := expandWildcardVersion(orParts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var orFn Range
|
|
||||||
for _, p := range expandedParts {
|
|
||||||
var andFn Range
|
|
||||||
for _, ap := range p {
|
|
||||||
opStr, vStr, err := splitComparatorVersion(ap)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
vr, err := buildVersionRange(opStr, vStr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Could not parse Range %q: %s", ap, err)
|
|
||||||
}
|
|
||||||
rf := vr.rangeFunc()
|
|
||||||
|
|
||||||
// Set function
|
|
||||||
if andFn == nil {
|
|
||||||
andFn = rf
|
|
||||||
} else { // Combine with existing function
|
|
||||||
andFn = andFn.AND(rf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if orFn == nil {
|
|
||||||
orFn = andFn
|
|
||||||
} else {
|
|
||||||
orFn = orFn.OR(andFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return orFn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// splitORParts splits the already cleaned parts by '||'.
|
|
||||||
// Checks for invalid positions of the operator and returns an
|
|
||||||
// error if found.
|
|
||||||
func splitORParts(parts []string) ([][]string, error) {
|
|
||||||
var ORparts [][]string
|
|
||||||
last := 0
|
|
||||||
for i, p := range parts {
|
|
||||||
if p == "||" {
|
|
||||||
if i == 0 {
|
|
||||||
return nil, fmt.Errorf("First element in range is '||'")
|
|
||||||
}
|
|
||||||
ORparts = append(ORparts, parts[last:i])
|
|
||||||
last = i + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if last == len(parts) {
|
|
||||||
return nil, fmt.Errorf("Last element in range is '||'")
|
|
||||||
}
|
|
||||||
ORparts = append(ORparts, parts[last:])
|
|
||||||
return ORparts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildVersionRange takes a slice of 2: operator and version
|
|
||||||
// and builds a versionRange, otherwise an error.
|
|
||||||
func buildVersionRange(opStr, vStr string) (*versionRange, error) {
|
|
||||||
c := parseComparator(opStr)
|
|
||||||
if c == nil {
|
|
||||||
return nil, fmt.Errorf("Could not parse comparator %q in %q", opStr, strings.Join([]string{opStr, vStr}, ""))
|
|
||||||
}
|
|
||||||
v, err := Parse(vStr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Could not parse version %q in %q: %s", vStr, strings.Join([]string{opStr, vStr}, ""), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &versionRange{
|
|
||||||
v: v,
|
|
||||||
c: c,
|
|
||||||
}, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// inArray checks if a byte is contained in an array of bytes
|
|
||||||
func inArray(s byte, list []byte) bool {
|
|
||||||
for _, el := range list {
|
|
||||||
if el == s {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// splitAndTrim splits a range string by spaces and cleans whitespaces
|
|
||||||
func splitAndTrim(s string) (result []string) {
|
|
||||||
last := 0
|
|
||||||
var lastChar byte
|
|
||||||
excludeFromSplit := []byte{'>', '<', '='}
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
if s[i] == ' ' && !inArray(lastChar, excludeFromSplit) {
|
|
||||||
if last < i-1 {
|
|
||||||
result = append(result, s[last:i])
|
|
||||||
}
|
|
||||||
last = i + 1
|
|
||||||
} else if s[i] != ' ' {
|
|
||||||
lastChar = s[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if last < len(s)-1 {
|
|
||||||
result = append(result, s[last:])
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, v := range result {
|
|
||||||
result[i] = strings.Replace(v, " ", "", -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parts := strings.Split(s, " ")
|
|
||||||
// for _, x := range parts {
|
|
||||||
// if s := strings.TrimSpace(x); len(s) != 0 {
|
|
||||||
// result = append(result, s)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// splitComparatorVersion splits the comparator from the version.
|
|
||||||
// Input must be free of leading or trailing spaces.
|
|
||||||
func splitComparatorVersion(s string) (string, string, error) {
|
|
||||||
i := strings.IndexFunc(s, unicode.IsDigit)
|
|
||||||
if i == -1 {
|
|
||||||
return "", "", fmt.Errorf("Could not get version from string: %q", s)
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(s[0:i]), s[i:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getWildcardType will return the type of wildcard that the
|
|
||||||
// passed version contains
|
|
||||||
func getWildcardType(vStr string) wildcardType {
|
|
||||||
parts := strings.Split(vStr, ".")
|
|
||||||
nparts := len(parts)
|
|
||||||
wildcard := parts[nparts-1]
|
|
||||||
|
|
||||||
possibleWildcardType := wildcardTypefromInt(nparts)
|
|
||||||
if wildcard == "x" {
|
|
||||||
return possibleWildcardType
|
|
||||||
}
|
|
||||||
|
|
||||||
return noneWildcard
|
|
||||||
}
|
|
||||||
|
|
||||||
// createVersionFromWildcard will convert a wildcard version
|
|
||||||
// into a regular version, replacing 'x's with '0's, handling
|
|
||||||
// special cases like '1.x.x' and '1.x'
|
|
||||||
func createVersionFromWildcard(vStr string) string {
|
|
||||||
// handle 1.x.x
|
|
||||||
vStr2 := strings.Replace(vStr, ".x.x", ".x", 1)
|
|
||||||
vStr2 = strings.Replace(vStr2, ".x", ".0", 1)
|
|
||||||
parts := strings.Split(vStr2, ".")
|
|
||||||
|
|
||||||
// handle 1.x
|
|
||||||
if len(parts) == 2 {
|
|
||||||
return vStr2 + ".0"
|
|
||||||
}
|
|
||||||
|
|
||||||
return vStr2
|
|
||||||
}
|
|
||||||
|
|
||||||
// incrementMajorVersion will increment the major version
|
|
||||||
// of the passed version
|
|
||||||
func incrementMajorVersion(vStr string) (string, error) {
|
|
||||||
parts := strings.Split(vStr, ".")
|
|
||||||
i, err := strconv.Atoi(parts[0])
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
parts[0] = strconv.Itoa(i + 1)
|
|
||||||
|
|
||||||
return strings.Join(parts, "."), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// incrementMajorVersion will increment the minor version
|
|
||||||
// of the passed version
|
|
||||||
func incrementMinorVersion(vStr string) (string, error) {
|
|
||||||
parts := strings.Split(vStr, ".")
|
|
||||||
i, err := strconv.Atoi(parts[1])
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
parts[1] = strconv.Itoa(i + 1)
|
|
||||||
|
|
||||||
return strings.Join(parts, "."), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// expandWildcardVersion will expand wildcards inside versions
|
|
||||||
// following these rules:
|
|
||||||
//
|
|
||||||
// * when dealing with patch wildcards:
|
|
||||||
// >= 1.2.x will become >= 1.2.0
|
|
||||||
// <= 1.2.x will become < 1.3.0
|
|
||||||
// > 1.2.x will become >= 1.3.0
|
|
||||||
// < 1.2.x will become < 1.2.0
|
|
||||||
// != 1.2.x will become < 1.2.0 >= 1.3.0
|
|
||||||
//
|
|
||||||
// * when dealing with minor wildcards:
|
|
||||||
// >= 1.x will become >= 1.0.0
|
|
||||||
// <= 1.x will become < 2.0.0
|
|
||||||
// > 1.x will become >= 2.0.0
|
|
||||||
// < 1.0 will become < 1.0.0
|
|
||||||
// != 1.x will become < 1.0.0 >= 2.0.0
|
|
||||||
//
|
|
||||||
// * when dealing with wildcards without
|
|
||||||
// version operator:
|
|
||||||
// 1.2.x will become >= 1.2.0 < 1.3.0
|
|
||||||
// 1.x will become >= 1.0.0 < 2.0.0
|
|
||||||
func expandWildcardVersion(parts [][]string) ([][]string, error) {
|
|
||||||
var expandedParts [][]string
|
|
||||||
for _, p := range parts {
|
|
||||||
var newParts []string
|
|
||||||
for _, ap := range p {
|
|
||||||
if strings.Index(ap, "x") != -1 {
|
|
||||||
opStr, vStr, err := splitComparatorVersion(ap)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
versionWildcardType := getWildcardType(vStr)
|
|
||||||
flatVersion := createVersionFromWildcard(vStr)
|
|
||||||
|
|
||||||
var resultOperator string
|
|
||||||
var shouldIncrementVersion bool
|
|
||||||
switch opStr {
|
|
||||||
case ">":
|
|
||||||
resultOperator = ">="
|
|
||||||
shouldIncrementVersion = true
|
|
||||||
case ">=":
|
|
||||||
resultOperator = ">="
|
|
||||||
case "<":
|
|
||||||
resultOperator = "<"
|
|
||||||
case "<=":
|
|
||||||
resultOperator = "<"
|
|
||||||
shouldIncrementVersion = true
|
|
||||||
case "", "=", "==":
|
|
||||||
newParts = append(newParts, ">="+flatVersion)
|
|
||||||
resultOperator = "<"
|
|
||||||
shouldIncrementVersion = true
|
|
||||||
case "!=", "!":
|
|
||||||
newParts = append(newParts, "<"+flatVersion)
|
|
||||||
resultOperator = ">="
|
|
||||||
shouldIncrementVersion = true
|
|
||||||
}
|
|
||||||
|
|
||||||
var resultVersion string
|
|
||||||
if shouldIncrementVersion {
|
|
||||||
switch versionWildcardType {
|
|
||||||
case patchWildcard:
|
|
||||||
resultVersion, _ = incrementMinorVersion(flatVersion)
|
|
||||||
case minorWildcard:
|
|
||||||
resultVersion, _ = incrementMajorVersion(flatVersion)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
resultVersion = flatVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
ap = resultOperator + resultVersion
|
|
||||||
}
|
|
||||||
newParts = append(newParts, ap)
|
|
||||||
}
|
|
||||||
expandedParts = append(expandedParts, newParts)
|
|
||||||
}
|
|
||||||
|
|
||||||
return expandedParts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseComparator(s string) comparator {
|
|
||||||
switch s {
|
|
||||||
case "==":
|
|
||||||
fallthrough
|
|
||||||
case "":
|
|
||||||
fallthrough
|
|
||||||
case "=":
|
|
||||||
return compEQ
|
|
||||||
case ">":
|
|
||||||
return compGT
|
|
||||||
case ">=":
|
|
||||||
return compGE
|
|
||||||
case "<":
|
|
||||||
return compLT
|
|
||||||
case "<=":
|
|
||||||
return compLE
|
|
||||||
case "!":
|
|
||||||
fallthrough
|
|
||||||
case "!=":
|
|
||||||
return compNE
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustParseRange is like ParseRange but panics if the range cannot be parsed.
|
|
||||||
func MustParseRange(s string) Range {
|
|
||||||
r, err := ParseRange(s)
|
|
||||||
if err != nil {
|
|
||||||
panic(`semver: ParseRange(` + s + `): ` + err.Error())
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
418
vendor/github.com/blang/semver/semver.go
generated
vendored
418
vendor/github.com/blang/semver/semver.go
generated
vendored
@ -1,418 +0,0 @@
|
|||||||
package semver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
numbers string = "0123456789"
|
|
||||||
alphas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-"
|
|
||||||
alphanum = alphas + numbers
|
|
||||||
)
|
|
||||||
|
|
||||||
// SpecVersion is the latest fully supported spec version of semver
|
|
||||||
var SpecVersion = Version{
|
|
||||||
Major: 2,
|
|
||||||
Minor: 0,
|
|
||||||
Patch: 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version represents a semver compatible version
|
|
||||||
type Version struct {
|
|
||||||
Major uint64
|
|
||||||
Minor uint64
|
|
||||||
Patch uint64
|
|
||||||
Pre []PRVersion
|
|
||||||
Build []string //No Precendence
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version to string
|
|
||||||
func (v Version) String() string {
|
|
||||||
b := make([]byte, 0, 5)
|
|
||||||
b = strconv.AppendUint(b, v.Major, 10)
|
|
||||||
b = append(b, '.')
|
|
||||||
b = strconv.AppendUint(b, v.Minor, 10)
|
|
||||||
b = append(b, '.')
|
|
||||||
b = strconv.AppendUint(b, v.Patch, 10)
|
|
||||||
|
|
||||||
if len(v.Pre) > 0 {
|
|
||||||
b = append(b, '-')
|
|
||||||
b = append(b, v.Pre[0].String()...)
|
|
||||||
|
|
||||||
for _, pre := range v.Pre[1:] {
|
|
||||||
b = append(b, '.')
|
|
||||||
b = append(b, pre.String()...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(v.Build) > 0 {
|
|
||||||
b = append(b, '+')
|
|
||||||
b = append(b, v.Build[0]...)
|
|
||||||
|
|
||||||
for _, build := range v.Build[1:] {
|
|
||||||
b = append(b, '.')
|
|
||||||
b = append(b, build...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Equals checks if v is equal to o.
|
|
||||||
func (v Version) Equals(o Version) bool {
|
|
||||||
return (v.Compare(o) == 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EQ checks if v is equal to o.
|
|
||||||
func (v Version) EQ(o Version) bool {
|
|
||||||
return (v.Compare(o) == 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NE checks if v is not equal to o.
|
|
||||||
func (v Version) NE(o Version) bool {
|
|
||||||
return (v.Compare(o) != 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GT checks if v is greater than o.
|
|
||||||
func (v Version) GT(o Version) bool {
|
|
||||||
return (v.Compare(o) == 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GTE checks if v is greater than or equal to o.
|
|
||||||
func (v Version) GTE(o Version) bool {
|
|
||||||
return (v.Compare(o) >= 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GE checks if v is greater than or equal to o.
|
|
||||||
func (v Version) GE(o Version) bool {
|
|
||||||
return (v.Compare(o) >= 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LT checks if v is less than o.
|
|
||||||
func (v Version) LT(o Version) bool {
|
|
||||||
return (v.Compare(o) == -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LTE checks if v is less than or equal to o.
|
|
||||||
func (v Version) LTE(o Version) bool {
|
|
||||||
return (v.Compare(o) <= 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LE checks if v is less than or equal to o.
|
|
||||||
func (v Version) LE(o Version) bool {
|
|
||||||
return (v.Compare(o) <= 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare compares Versions v to o:
|
|
||||||
// -1 == v is less than o
|
|
||||||
// 0 == v is equal to o
|
|
||||||
// 1 == v is greater than o
|
|
||||||
func (v Version) Compare(o Version) int {
|
|
||||||
if v.Major != o.Major {
|
|
||||||
if v.Major > o.Major {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if v.Minor != o.Minor {
|
|
||||||
if v.Minor > o.Minor {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if v.Patch != o.Patch {
|
|
||||||
if v.Patch > o.Patch {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Quick comparison if a version has no prerelease versions
|
|
||||||
if len(v.Pre) == 0 && len(o.Pre) == 0 {
|
|
||||||
return 0
|
|
||||||
} else if len(v.Pre) == 0 && len(o.Pre) > 0 {
|
|
||||||
return 1
|
|
||||||
} else if len(v.Pre) > 0 && len(o.Pre) == 0 {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for ; i < len(v.Pre) && i < len(o.Pre); i++ {
|
|
||||||
if comp := v.Pre[i].Compare(o.Pre[i]); comp == 0 {
|
|
||||||
continue
|
|
||||||
} else if comp == 1 {
|
|
||||||
return 1
|
|
||||||
} else {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If all pr versions are the equal but one has further prversion, this one greater
|
|
||||||
if i == len(v.Pre) && i == len(o.Pre) {
|
|
||||||
return 0
|
|
||||||
} else if i == len(v.Pre) && i < len(o.Pre) {
|
|
||||||
return -1
|
|
||||||
} else {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate validates v and returns error in case
|
|
||||||
func (v Version) Validate() error {
|
|
||||||
// Major, Minor, Patch already validated using uint64
|
|
||||||
|
|
||||||
for _, pre := range v.Pre {
|
|
||||||
if !pre.IsNum { //Numeric prerelease versions already uint64
|
|
||||||
if len(pre.VersionStr) == 0 {
|
|
||||||
return fmt.Errorf("Prerelease can not be empty %q", pre.VersionStr)
|
|
||||||
}
|
|
||||||
if !containsOnly(pre.VersionStr, alphanum) {
|
|
||||||
return fmt.Errorf("Invalid character(s) found in prerelease %q", pre.VersionStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, build := range v.Build {
|
|
||||||
if len(build) == 0 {
|
|
||||||
return fmt.Errorf("Build meta data can not be empty %q", build)
|
|
||||||
}
|
|
||||||
if !containsOnly(build, alphanum) {
|
|
||||||
return fmt.Errorf("Invalid character(s) found in build meta data %q", build)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error
|
|
||||||
func New(s string) (vp *Version, err error) {
|
|
||||||
v, err := Parse(s)
|
|
||||||
vp = &v
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make is an alias for Parse, parses version string and returns a validated Version or error
|
|
||||||
func Make(s string) (Version, error) {
|
|
||||||
return Parse(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseTolerant allows for certain version specifications that do not strictly adhere to semver
|
|
||||||
// specs to be parsed by this library. It does so by normalizing versions before passing them to
|
|
||||||
// Parse(). It currently trims spaces, removes a "v" prefix, and adds a 0 patch number to versions
|
|
||||||
// with only major and minor components specified
|
|
||||||
func ParseTolerant(s string) (Version, error) {
|
|
||||||
s = strings.TrimSpace(s)
|
|
||||||
s = strings.TrimPrefix(s, "v")
|
|
||||||
|
|
||||||
// Split into major.minor.(patch+pr+meta)
|
|
||||||
parts := strings.SplitN(s, ".", 3)
|
|
||||||
if len(parts) < 3 {
|
|
||||||
if strings.ContainsAny(parts[len(parts)-1], "+-") {
|
|
||||||
return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data")
|
|
||||||
}
|
|
||||||
for len(parts) < 3 {
|
|
||||||
parts = append(parts, "0")
|
|
||||||
}
|
|
||||||
s = strings.Join(parts, ".")
|
|
||||||
}
|
|
||||||
|
|
||||||
return Parse(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse parses version string and returns a validated Version or error
|
|
||||||
func Parse(s string) (Version, error) {
|
|
||||||
if len(s) == 0 {
|
|
||||||
return Version{}, errors.New("Version string empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split into major.minor.(patch+pr+meta)
|
|
||||||
parts := strings.SplitN(s, ".", 3)
|
|
||||||
if len(parts) != 3 {
|
|
||||||
return Version{}, errors.New("No Major.Minor.Patch elements found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Major
|
|
||||||
if !containsOnly(parts[0], numbers) {
|
|
||||||
return Version{}, fmt.Errorf("Invalid character(s) found in major number %q", parts[0])
|
|
||||||
}
|
|
||||||
if hasLeadingZeroes(parts[0]) {
|
|
||||||
return Version{}, fmt.Errorf("Major number must not contain leading zeroes %q", parts[0])
|
|
||||||
}
|
|
||||||
major, err := strconv.ParseUint(parts[0], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return Version{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Minor
|
|
||||||
if !containsOnly(parts[1], numbers) {
|
|
||||||
return Version{}, fmt.Errorf("Invalid character(s) found in minor number %q", parts[1])
|
|
||||||
}
|
|
||||||
if hasLeadingZeroes(parts[1]) {
|
|
||||||
return Version{}, fmt.Errorf("Minor number must not contain leading zeroes %q", parts[1])
|
|
||||||
}
|
|
||||||
minor, err := strconv.ParseUint(parts[1], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return Version{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
v := Version{}
|
|
||||||
v.Major = major
|
|
||||||
v.Minor = minor
|
|
||||||
|
|
||||||
var build, prerelease []string
|
|
||||||
patchStr := parts[2]
|
|
||||||
|
|
||||||
if buildIndex := strings.IndexRune(patchStr, '+'); buildIndex != -1 {
|
|
||||||
build = strings.Split(patchStr[buildIndex+1:], ".")
|
|
||||||
patchStr = patchStr[:buildIndex]
|
|
||||||
}
|
|
||||||
|
|
||||||
if preIndex := strings.IndexRune(patchStr, '-'); preIndex != -1 {
|
|
||||||
prerelease = strings.Split(patchStr[preIndex+1:], ".")
|
|
||||||
patchStr = patchStr[:preIndex]
|
|
||||||
}
|
|
||||||
|
|
||||||
if !containsOnly(patchStr, numbers) {
|
|
||||||
return Version{}, fmt.Errorf("Invalid character(s) found in patch number %q", patchStr)
|
|
||||||
}
|
|
||||||
if hasLeadingZeroes(patchStr) {
|
|
||||||
return Version{}, fmt.Errorf("Patch number must not contain leading zeroes %q", patchStr)
|
|
||||||
}
|
|
||||||
patch, err := strconv.ParseUint(patchStr, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return Version{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
v.Patch = patch
|
|
||||||
|
|
||||||
// Prerelease
|
|
||||||
for _, prstr := range prerelease {
|
|
||||||
parsedPR, err := NewPRVersion(prstr)
|
|
||||||
if err != nil {
|
|
||||||
return Version{}, err
|
|
||||||
}
|
|
||||||
v.Pre = append(v.Pre, parsedPR)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build meta data
|
|
||||||
for _, str := range build {
|
|
||||||
if len(str) == 0 {
|
|
||||||
return Version{}, errors.New("Build meta data is empty")
|
|
||||||
}
|
|
||||||
if !containsOnly(str, alphanum) {
|
|
||||||
return Version{}, fmt.Errorf("Invalid character(s) found in build meta data %q", str)
|
|
||||||
}
|
|
||||||
v.Build = append(v.Build, str)
|
|
||||||
}
|
|
||||||
|
|
||||||
return v, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustParse is like Parse but panics if the version cannot be parsed.
|
|
||||||
func MustParse(s string) Version {
|
|
||||||
v, err := Parse(s)
|
|
||||||
if err != nil {
|
|
||||||
panic(`semver: Parse(` + s + `): ` + err.Error())
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// PRVersion represents a PreRelease Version
|
|
||||||
type PRVersion struct {
|
|
||||||
VersionStr string
|
|
||||||
VersionNum uint64
|
|
||||||
IsNum bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPRVersion creates a new valid prerelease version
|
|
||||||
func NewPRVersion(s string) (PRVersion, error) {
|
|
||||||
if len(s) == 0 {
|
|
||||||
return PRVersion{}, errors.New("Prerelease is empty")
|
|
||||||
}
|
|
||||||
v := PRVersion{}
|
|
||||||
if containsOnly(s, numbers) {
|
|
||||||
if hasLeadingZeroes(s) {
|
|
||||||
return PRVersion{}, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s)
|
|
||||||
}
|
|
||||||
num, err := strconv.ParseUint(s, 10, 64)
|
|
||||||
|
|
||||||
// Might never be hit, but just in case
|
|
||||||
if err != nil {
|
|
||||||
return PRVersion{}, err
|
|
||||||
}
|
|
||||||
v.VersionNum = num
|
|
||||||
v.IsNum = true
|
|
||||||
} else if containsOnly(s, alphanum) {
|
|
||||||
v.VersionStr = s
|
|
||||||
v.IsNum = false
|
|
||||||
} else {
|
|
||||||
return PRVersion{}, fmt.Errorf("Invalid character(s) found in prerelease %q", s)
|
|
||||||
}
|
|
||||||
return v, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNumeric checks if prerelease-version is numeric
|
|
||||||
func (v PRVersion) IsNumeric() bool {
|
|
||||||
return v.IsNum
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare compares two PreRelease Versions v and o:
|
|
||||||
// -1 == v is less than o
|
|
||||||
// 0 == v is equal to o
|
|
||||||
// 1 == v is greater than o
|
|
||||||
func (v PRVersion) Compare(o PRVersion) int {
|
|
||||||
if v.IsNum && !o.IsNum {
|
|
||||||
return -1
|
|
||||||
} else if !v.IsNum && o.IsNum {
|
|
||||||
return 1
|
|
||||||
} else if v.IsNum && o.IsNum {
|
|
||||||
if v.VersionNum == o.VersionNum {
|
|
||||||
return 0
|
|
||||||
} else if v.VersionNum > o.VersionNum {
|
|
||||||
return 1
|
|
||||||
} else {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
} else { // both are Alphas
|
|
||||||
if v.VersionStr == o.VersionStr {
|
|
||||||
return 0
|
|
||||||
} else if v.VersionStr > o.VersionStr {
|
|
||||||
return 1
|
|
||||||
} else {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PreRelease version to string
|
|
||||||
func (v PRVersion) String() string {
|
|
||||||
if v.IsNum {
|
|
||||||
return strconv.FormatUint(v.VersionNum, 10)
|
|
||||||
}
|
|
||||||
return v.VersionStr
|
|
||||||
}
|
|
||||||
|
|
||||||
func containsOnly(s string, set string) bool {
|
|
||||||
return strings.IndexFunc(s, func(r rune) bool {
|
|
||||||
return !strings.ContainsRune(set, r)
|
|
||||||
}) == -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasLeadingZeroes(s string) bool {
|
|
||||||
return len(s) > 1 && s[0] == '0'
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBuildVersion creates a new valid build version
|
|
||||||
func NewBuildVersion(s string) (string, error) {
|
|
||||||
if len(s) == 0 {
|
|
||||||
return "", errors.New("Buildversion is empty")
|
|
||||||
}
|
|
||||||
if !containsOnly(s, alphanum) {
|
|
||||||
return "", fmt.Errorf("Invalid character(s) found in build meta data %q", s)
|
|
||||||
}
|
|
||||||
return s, nil
|
|
||||||
}
|
|
28
vendor/github.com/blang/semver/sort.go
generated
vendored
28
vendor/github.com/blang/semver/sort.go
generated
vendored
@ -1,28 +0,0 @@
|
|||||||
package semver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Versions represents multiple versions.
|
|
||||||
type Versions []Version
|
|
||||||
|
|
||||||
// Len returns length of version collection
|
|
||||||
func (s Versions) Len() int {
|
|
||||||
return len(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap swaps two versions inside the collection by its indices
|
|
||||||
func (s Versions) Swap(i, j int) {
|
|
||||||
s[i], s[j] = s[j], s[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Less checks if version at index i is less than version at index j
|
|
||||||
func (s Versions) Less(i, j int) bool {
|
|
||||||
return s[i].LT(s[j])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort sorts a slice of versions
|
|
||||||
func Sort(versions []Version) {
|
|
||||||
sort.Sort(Versions(versions))
|
|
||||||
}
|
|
30
vendor/github.com/blang/semver/sql.go
generated
vendored
30
vendor/github.com/blang/semver/sql.go
generated
vendored
@ -1,30 +0,0 @@
|
|||||||
package semver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql/driver"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Scan implements the database/sql.Scanner interface.
|
|
||||||
func (v *Version) Scan(src interface{}) (err error) {
|
|
||||||
var str string
|
|
||||||
switch src := src.(type) {
|
|
||||||
case string:
|
|
||||||
str = src
|
|
||||||
case []byte:
|
|
||||||
str = string(src)
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Version.Scan: cannot convert %T to string.", src)
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, err := Parse(str); err == nil {
|
|
||||||
*v = t
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value implements the database/sql/driver.Valuer interface.
|
|
||||||
func (v Version) Value() (driver.Value, error) {
|
|
||||||
return v.String(), nil
|
|
||||||
}
|
|
25
vendor/github.com/containerd/nri/.golangci.yml
generated
vendored
25
vendor/github.com/containerd/nri/.golangci.yml
generated
vendored
@ -1,22 +1,41 @@
|
|||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
- structcheck
|
|
||||||
- varcheck
|
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- unconvert
|
- unconvert
|
||||||
- gofmt
|
- gofmt
|
||||||
- goimports
|
- goimports
|
||||||
- golint
|
|
||||||
- ineffassign
|
- ineffassign
|
||||||
- vet
|
- vet
|
||||||
- unused
|
- unused
|
||||||
- misspell
|
- misspell
|
||||||
|
- revive
|
||||||
disable:
|
disable:
|
||||||
- errcheck
|
- errcheck
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
include:
|
include:
|
||||||
- EXC0002
|
- EXC0002
|
||||||
|
exclude-rules:
|
||||||
|
# We have protoc-generated ttRPC/gRPC code. When adding extra functions
|
||||||
|
# for generated types we want to consistently violate golint's semantic
|
||||||
|
# function name spelling rules, instead of inconsistently doing so only
|
||||||
|
# from automatically generated files. These rules are for that.
|
||||||
|
- path: pkg/adaptation/result.go
|
||||||
|
linters:
|
||||||
|
- golint
|
||||||
|
- revive
|
||||||
|
text: "should be claim"
|
||||||
|
# Ignore naming violation in the test suite as well.
|
||||||
|
- path: pkg/adaptation/adaptation_suite_test.go
|
||||||
|
linters:
|
||||||
|
- golint
|
||||||
|
- revive
|
||||||
|
text: "should be strip"
|
||||||
|
# Differ copies pods and containers with Mutexes for diffing. Should be harmless.
|
||||||
|
- path: plugins/differ/nri-differ.go
|
||||||
|
linters:
|
||||||
|
- govet
|
||||||
|
text: "copylocks: .*protobuf/internal/impl.MessageState.*"
|
||||||
|
|
||||||
run:
|
run:
|
||||||
timeout: 2m
|
timeout: 2m
|
||||||
|
165
vendor/github.com/containerd/nri/Makefile
generated
vendored
165
vendor/github.com/containerd/nri/Makefile
generated
vendored
@ -12,5 +12,166 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
all:
|
PROTO_SOURCES = $(shell find . -name '*.proto' | grep -v /vendor/)
|
||||||
go build -v
|
PROTO_GOFILES = $(patsubst %.proto,%.pb.go,$(PROTO_SOURCES))
|
||||||
|
PROTO_INCLUDE = -I$(PWD):/usr/local/include:/usr/include
|
||||||
|
PROTO_OPTIONS = --proto_path=. $(PROTO_INCLUDE) \
|
||||||
|
--go_opt=paths=source_relative --go_out=. \
|
||||||
|
--go-ttrpc_opt=paths=source_relative --go-ttrpc_out=.
|
||||||
|
PROTO_COMPILE = PATH=$(PATH):$(shell go env GOPATH)/bin; protoc $(PROTO_OPTIONS)
|
||||||
|
|
||||||
|
GO_CMD := go
|
||||||
|
GO_BUILD := $(GO_CMD) build
|
||||||
|
GO_INSTALL := $(GO_CMD) install
|
||||||
|
GO_TEST := $(GO_CMD) test
|
||||||
|
GO_LINT := golint -set_exit_status
|
||||||
|
GO_FMT := gofmt
|
||||||
|
GO_VET := $(GO_CMD) vet
|
||||||
|
|
||||||
|
GO_MODULES := $(shell $(GO_CMD) list ./...)
|
||||||
|
|
||||||
|
GOLANG_CILINT := golangci-lint
|
||||||
|
GINKGO := ginkgo
|
||||||
|
|
||||||
|
BUILD_PATH := $(shell pwd)/build
|
||||||
|
BIN_PATH := $(BUILD_PATH)/bin
|
||||||
|
COVERAGE_PATH := $(BUILD_PATH)/coverage
|
||||||
|
|
||||||
|
PLUGINS := \
|
||||||
|
$(BIN_PATH)/logger \
|
||||||
|
$(BIN_PATH)/device-injector \
|
||||||
|
$(BIN_PATH)/hook-injector \
|
||||||
|
$(BIN_PATH)/differ \
|
||||||
|
$(BIN_PATH)/v010-adapter \
|
||||||
|
$(BIN_PATH)/template
|
||||||
|
|
||||||
|
|
||||||
|
ifneq ($(V),1)
|
||||||
|
Q := @
|
||||||
|
endif
|
||||||
|
|
||||||
|
#
|
||||||
|
# top-level targets
|
||||||
|
#
|
||||||
|
|
||||||
|
all: build build-plugins
|
||||||
|
|
||||||
|
build: build-proto build-check
|
||||||
|
|
||||||
|
clean: clean-plugins
|
||||||
|
|
||||||
|
allclean: clean clean-cache
|
||||||
|
|
||||||
|
test: test-gopkgs
|
||||||
|
|
||||||
|
#
|
||||||
|
# build targets
|
||||||
|
#
|
||||||
|
|
||||||
|
build-proto: $(PROTO_GOFILES)
|
||||||
|
|
||||||
|
build-plugins: $(PLUGINS)
|
||||||
|
|
||||||
|
build-check:
|
||||||
|
$(Q)$(GO_BUILD) -v $(GO_MODULES)
|
||||||
|
|
||||||
|
#
|
||||||
|
# clean targets
|
||||||
|
#
|
||||||
|
|
||||||
|
clean-plugins:
|
||||||
|
$(Q)rm -f $(PLUGINS)
|
||||||
|
|
||||||
|
clean-cache:
|
||||||
|
$(Q)$(GO_CMD) clean -cache -testcache
|
||||||
|
|
||||||
|
#
|
||||||
|
# plugins build targets
|
||||||
|
#
|
||||||
|
|
||||||
|
$(BIN_PATH)/logger: $(wildcard plugins/logger/*.go)
|
||||||
|
$(Q)echo "Building $@..."; \
|
||||||
|
cd $(dir $<) && $(GO_BUILD) -o $@ .
|
||||||
|
|
||||||
|
$(BIN_PATH)/device-injector: $(wildcard plugins/device-injector/*.go)
|
||||||
|
$(Q)echo "Building $@..."; \
|
||||||
|
cd $(dir $<) && $(GO_BUILD) -o $@ .
|
||||||
|
|
||||||
|
$(BIN_PATH)/hook-injector: $(wildcard plugins/hook-injector/*.go)
|
||||||
|
$(Q)echo "Building $@..."; \
|
||||||
|
cd $(dir $<) && $(GO_BUILD) -o $@ .
|
||||||
|
|
||||||
|
$(BIN_PATH)/differ: $(wildcard plugins/differ/*.go)
|
||||||
|
$(Q)echo "Building $@..."; \
|
||||||
|
cd $(dir $<) && $(GO_BUILD) -o $@ .
|
||||||
|
|
||||||
|
$(BIN_PATH)/v010-adapter: $(wildcard plugins/v010-adapter/*.go)
|
||||||
|
$(Q)echo "Building $@..."; \
|
||||||
|
cd $(dir $<) && $(GO_BUILD) -o $@ .
|
||||||
|
|
||||||
|
$(BIN_PATH)/template: $(wildcard plugins/template/*.go)
|
||||||
|
$(Q)echo "Building $@..."; \
|
||||||
|
cd $(dir $<) && $(GO_BUILD) -o $@ .
|
||||||
|
|
||||||
|
#
|
||||||
|
# test targets
|
||||||
|
#
|
||||||
|
|
||||||
|
test-gopkgs: ginkgo-tests
|
||||||
|
|
||||||
|
ginkgo-tests:
|
||||||
|
$(Q)$(GINKGO) run \
|
||||||
|
--race \
|
||||||
|
--trace \
|
||||||
|
--cover \
|
||||||
|
--covermode atomic \
|
||||||
|
--output-dir $(COVERAGE_PATH) \
|
||||||
|
--junit-report junit.xml \
|
||||||
|
--coverprofile coverprofile \
|
||||||
|
--succinct \
|
||||||
|
-r .; \
|
||||||
|
$(GO_CMD) tool cover -html=$(COVERAGE_PATH)/coverprofile -o $(COVERAGE_PATH)/coverage.html
|
||||||
|
|
||||||
|
codecov: SHELL := $(shell which bash)
|
||||||
|
codecov:
|
||||||
|
bash <(curl -s https://codecov.io/bash) -f $(COVERAGE_PATH)/coverprofile
|
||||||
|
|
||||||
|
#
|
||||||
|
# other validation targets
|
||||||
|
#
|
||||||
|
|
||||||
|
fmt format:
|
||||||
|
$(Q)$(GO_FMT) -s -d -e .
|
||||||
|
|
||||||
|
lint:
|
||||||
|
$(Q)$(GO_LINT) -set_exit_status ./...
|
||||||
|
|
||||||
|
vet:
|
||||||
|
$(Q)$(GO_VET) ./...
|
||||||
|
|
||||||
|
golangci-lint:
|
||||||
|
$(Q)$(GOLANG_CILINT) run
|
||||||
|
|
||||||
|
#
|
||||||
|
# proto generation targets
|
||||||
|
#
|
||||||
|
|
||||||
|
%.pb.go: %.proto
|
||||||
|
$(Q)echo "Generating $@..."; \
|
||||||
|
$(PROTO_COMPILE) $<
|
||||||
|
|
||||||
|
#
|
||||||
|
# targets for installing dependencies
|
||||||
|
#
|
||||||
|
|
||||||
|
install-protoc install-protobuf:
|
||||||
|
$(Q)./scripts/install-protobuf && \
|
||||||
|
|
||||||
|
install-ttrpc-plugin:
|
||||||
|
$(Q)$(GO_INSTALL) github.com/containerd/ttrpc/cmd/protoc-gen-go-ttrpc@74421d10189e8c118870d294c9f7f62db2d33ec1
|
||||||
|
|
||||||
|
install-protoc-dependencies:
|
||||||
|
$(Q)$(GO_INSTALL) google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.0
|
||||||
|
|
||||||
|
install-ginkgo:
|
||||||
|
$(Q)$(GO_INSTALL) -mod=mod github.com/onsi/ginkgo/v2/ginkgo
|
||||||
|
115
vendor/github.com/containerd/nri/README-v0.1.0.md
generated
vendored
Normal file
115
vendor/github.com/containerd/nri/README-v0.1.0.md
generated
vendored
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
# nri - Node Resource Interface
|
||||||
|
|
||||||
|
[](https://pkg.go.dev/github.com/containerd/nri)
|
||||||
|
[](https://github.com/containerd/nri/actions?query=workflow%3ACI)
|
||||||
|
[](https://codecov.io/gh/containerd/nri)
|
||||||
|
[](https://goreportcard.com/report/github.com/containerd/nri)
|
||||||
|
|
||||||
|
*This project is currently in DRAFT status*
|
||||||
|
|
||||||
|
This project is a WIP for a new, CNI like, interface for managing resources on a node for Pods and Containers.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
The basic interface, concepts and plugin design of the Container Network Interface (CNI) is an elegant way to handle multiple implementations of the network stack for containers.
|
||||||
|
This concept can be used for additional interfaces to customize a container's runtime environment.
|
||||||
|
This proposal covers a new interface for resource management on a node with a structured API and plugin design for containers.
|
||||||
|
|
||||||
|
## Lifecycle
|
||||||
|
|
||||||
|
The big selling point for CNI is that it has a structured interface for modifying the network namespace for a container.
|
||||||
|
This is different from generic hooks as they lack a type safe API injected into the lifecycle of a container.
|
||||||
|
The lifecycle point that CNI and NRI plugins will be injected into is the point between `Create` and `Start` of the container's init process.
|
||||||
|
|
||||||
|
`Create->NRI->Start`
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Configuration is split into two parts. One is the payload that is specific to a plugin invocation while the second is the host level configuration and options that specify what plugins to run and provide additional configuration to a plugin.
|
||||||
|
|
||||||
|
### Filepath and Binaries
|
||||||
|
|
||||||
|
Plugin binary paths can be configured via the consumer but will default to `/opt/nri/bin`.
|
||||||
|
Binaries are named with their type as the binary name, same as the CNI plugin naming scheme.
|
||||||
|
|
||||||
|
### Host Level Config
|
||||||
|
|
||||||
|
The config's default location will be `/etc/nri/resource.d/*.conf`.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": "0.1",
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"type": "konfine",
|
||||||
|
"conf": {
|
||||||
|
"systemReserved": [0, 1]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "clearcfs"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Input
|
||||||
|
|
||||||
|
Input to a plugin is provided via `STDIN` as a `json` payload.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": "0.1",
|
||||||
|
"state": "create",
|
||||||
|
"id": "redis",
|
||||||
|
"pid": 1234,
|
||||||
|
"spec": {
|
||||||
|
"resources": {},
|
||||||
|
"cgroupsPath": "default/redis",
|
||||||
|
"namespaces": {
|
||||||
|
"pid": "/proc/44/ns/pid",
|
||||||
|
"mount": "/proc/44/ns/mnt",
|
||||||
|
"net": "/proc/44/ns/net"
|
||||||
|
},
|
||||||
|
"annotations": {
|
||||||
|
"qos.class": "ls"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Output
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": "0.1",
|
||||||
|
"state": "create",
|
||||||
|
"id": "redis",
|
||||||
|
"pid": 1234,
|
||||||
|
"cgroupsPath": "qos-ls/default/redis"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
* Invoke - provides invocations into different lifecycle changes of a container
|
||||||
|
- states: `setup|pause|resume|update|delete`
|
||||||
|
|
||||||
|
## Packages
|
||||||
|
|
||||||
|
A Go based API and client package will be created for both producers of plugins and consumers, commonly being the container runtime (containerd).
|
||||||
|
|
||||||
|
### Sample Plugin
|
||||||
|
|
||||||
|
* [clearcfs](examples/clearcfs/main.go)
|
||||||
|
|
||||||
|
## Project details
|
||||||
|
|
||||||
|
nri is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
|
||||||
|
As a containerd sub-project, you will find the:
|
||||||
|
|
||||||
|
* [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md),
|
||||||
|
* [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS),
|
||||||
|
* and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md)
|
||||||
|
|
||||||
|
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
395
vendor/github.com/containerd/nri/README.md
generated
vendored
395
vendor/github.com/containerd/nri/README.md
generated
vendored
@ -1,167 +1,306 @@
|
|||||||
# nri - Node Resource Interface
|
## Node Resource Interface, Revisited
|
||||||
|
|
||||||
[](https://pkg.go.dev/github.com/containerd/nri)
|
### Goal
|
||||||
[](https://github.com/containerd/nri/actions?query=workflow%3ACI)
|
|
||||||
[](https://codecov.io/gh/containerd/nri)
|
|
||||||
[](https://goreportcard.com/report/github.com/containerd/nri)
|
|
||||||
|
|
||||||
*This project is currently in DRAFT status*
|
NRI allows plugging domain- or vendor-specific custom logic into OCI-
|
||||||
|
compatible runtimes. This logic can make controlled changes to containers
|
||||||
|
or perform extra actions outside the scope of OCI at certain points in a
|
||||||
|
containers lifecycle. This can be used, for instance, for improved allocation
|
||||||
|
and management of devices and other container resources.
|
||||||
|
|
||||||
This project is a WIP for a new, CNI like, interface for managing resources on a node for Pods and Containers.
|
NRI defines the interfaces and implements the common infrastructure for
|
||||||
|
enabling such pluggable runtime extensions, NRI plugins. This also keeps
|
||||||
|
the plugins themselves runtime-agnostic.
|
||||||
|
|
||||||
## Documentation
|
The goal is to enable NRI support in the most commonly used OCI runtimes,
|
||||||
|
[containerd](https://github.com/containerd/containerd) and
|
||||||
|
[CRI-O](https://github.com/cri-o/cri-o).
|
||||||
|
|
||||||
The basic interface, concepts and plugin design of the Container Network Interface (CNI) is an elegant way to handle multiple implementations of the network stack for containers.
|
### Background
|
||||||
This concept can be used for additional interfaces to customize a container's runtime environment.
|
|
||||||
This proposal covers a new interface for resource management on a node with a structured API and plugin design for containers.
|
|
||||||
|
|
||||||
## Lifecycle
|
The revisited API is a major rewrite of NRI. It changes the scope of NRI
|
||||||
|
and how it gets integrated into runtimes. It reworks how plugins are
|
||||||
|
implemented, how they communicate with the runtime, and what kind of
|
||||||
|
changes they can make to containers.
|
||||||
|
|
||||||
The big selling point for CNI is that it has a structured interface for modifying the network namespace for a container.
|
[NRI v0.1.0](README-v0.1.0.md) used an OCI hook-like one-shot plugin invocation
|
||||||
This is different from generic hooks as they lack a type safe API injected into the lifecycle of a container.
|
mechanism where a separate instance of a plugin was spawned for every NRI
|
||||||
The lifecycle point that CNI and NRI plugins will be injected into is the point between `Create` and `Start` of the container's init process.
|
event. This instance then used its standard input and output to receive a
|
||||||
|
request and provide a response, both as JSON data.
|
||||||
|
|
||||||
`Create->NRI->Start`
|
Plugins in NRI are daemon-like entities. A single instance of a plugin is
|
||||||
|
now responsible for handling the full stream of NRI events and requests. A
|
||||||
|
unix-domain socket is used as the transport for communication. Instead of
|
||||||
|
JSON requests and responses NRI is defined as a formal, protobuf-based
|
||||||
|
'NRI plugin protocol' which is compiled into ttRPC bindings. This should
|
||||||
|
result in improved communication efficiency with lower per-message overhead,
|
||||||
|
and enable straightforward implementation of stateful NRI plugins.
|
||||||
|
|
||||||
## Configuration
|
### Components
|
||||||
|
|
||||||
Configuration is split into two parts. One is the payload that is specific to a plugin invocation while the second is the host level configuration and options that specify what plugins to run and provide additional configuration to a plugin.
|
The NRI implementation consists of a number of components. The core of
|
||||||
|
these are essential for implementing working end-to-end NRI support in
|
||||||
|
runtimes. These core components are the actual [NRI protocol](pkg/api),
|
||||||
|
and the [NRI runtime adaptation](pkg/adaptation).
|
||||||
|
|
||||||
### Filepath and Binaries
|
Together these establish the model of how a runtime interacts with NRI and
|
||||||
|
how plugins interact with containers in the runtime through NRI. They also
|
||||||
|
define under which conditions plugins can make changes to containers and
|
||||||
|
the extent of these changes.
|
||||||
|
|
||||||
Plugin binary paths can be configured via the consumer but will default to `/opt/nri/bin`.
|
The rest of the components are the [NRI plugin stub library](pkg/stub)
|
||||||
Binaries are named with their type as the binary name, same as the CNI plugin naming scheme.
|
and [some sample NRI plugins](plugins). [Some plugins](plugins/hook-injector)
|
||||||
|
implement useful functionality in real world scenarios. [A few](plugins/differ)
|
||||||
|
[others](plugins/logger) are useful for debugging. All of the sample plugins
|
||||||
|
serve as practical examples of how the stub library can be used to implement
|
||||||
|
NRI plugins.
|
||||||
|
|
||||||
### Host Level Config
|
### Protocol, Plugin API
|
||||||
|
|
||||||
The config's default location will be `/etc/nri/resource.d/*.conf`.
|
The core of NRI is defined by a protobuf [protocol definition](pkg/api/api.proto)
|
||||||
|
of the low-level plugin API. The API defines two services, Runtime and Plugin.
|
||||||
|
|
||||||
```json
|
The Runtime service is the public interface runtimes expose for NRI plugins. All
|
||||||
{
|
requests on this interface are initiated by the plugin. The interface provides
|
||||||
"version": "0.1",
|
functions for
|
||||||
"plugins": [
|
|
||||||
{
|
|
||||||
"type": "konfine",
|
|
||||||
"conf": {
|
|
||||||
"systemReserved": [0, 1]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "clearcfs"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Input
|
- initiating plugin registration
|
||||||
|
- requesting unsolicited updates to containers
|
||||||
|
|
||||||
Input to a plugin is provided via `STDIN` as a `json` payload.
|
The Plugin service is the public interface NRI uses to interact with plugins.
|
||||||
|
All requests on this interface are initiated by NRI/the runtime. The interface
|
||||||
|
provides functions for
|
||||||
|
|
||||||
```json
|
- configuring the plugin
|
||||||
{
|
- getting initial list of already existing pods and containers
|
||||||
"version": "0.1",
|
- hooking the plugin into pod/container lifecycle events
|
||||||
"state": "create",
|
- shutting down the plugin
|
||||||
"id": "redis",
|
|
||||||
"pid": 1234,
|
|
||||||
"spec": {
|
|
||||||
"resources": {},
|
|
||||||
"cgroupsPath": "default/redis",
|
|
||||||
"namespaces": {
|
|
||||||
"pid": "/proc/44/ns/pid",
|
|
||||||
"mount": "/proc/44/ns/mnt",
|
|
||||||
"net": "/proc/44/ns/net"
|
|
||||||
},
|
|
||||||
"annotations": {
|
|
||||||
"qos.class": "ls"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Output
|
#### Plugin Registration
|
||||||
|
|
||||||
```json
|
Before a plugin can start receiving and processing container events, it needs
|
||||||
{
|
to register itself with NRI. During registration the plugin and NRI perform a
|
||||||
"version": "0.1",
|
handshake sequence which consists of the following steps:
|
||||||
"state": "create",
|
|
||||||
"id": "redis",
|
|
||||||
"pid": 1234,
|
|
||||||
"cgroupsPath": "qos-ls/default/redis"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Commands
|
1. the plugin identifies itself to the runtime
|
||||||
|
2. NRI provides plugin-specific configuration data to the plugin
|
||||||
|
3. the plugin subscribes to pod and container lifecycle events of interest
|
||||||
|
4. NRI sends list of existing pods and containers to plugin
|
||||||
|
5. the plugin requests any updates deemed necessary to existing containers
|
||||||
|
|
||||||
* Invoke - provides invocations into different lifecycle changes of a container
|
The plugin identifies itself to NRI by a plugin name and a plugin index. The
|
||||||
- states: `setup|pause|resume|update|delete`
|
plugin index is used by NRI to determine in which order the plugin is hooked
|
||||||
|
into pod and container lifecycle event processing with respect to any other
|
||||||
|
plugins.
|
||||||
|
|
||||||
## Packages
|
The plugin name is used to pick plugin-specific data to send to the plugin
|
||||||
|
as configuration. This data is only present if the plugin has been launched
|
||||||
|
by NRI. If the plugin has been externally started it is expected to acquire
|
||||||
|
its configuration also by external means. The plugin subscribes to pod and
|
||||||
|
container lifecycle events of interest in its response to configuration.
|
||||||
|
|
||||||
A Go based API and client package will be created for both producers of plugins and consumers, commonly being the container runtime (containerd).
|
As the last step in the registration and handshaking process, NRI sends the
|
||||||
|
full set of pods and containers known to the runtime. The plugin can request
|
||||||
|
updates it considers necessary to any of the known containers in response.
|
||||||
|
|
||||||
### Sample Plugin
|
Once the handshake sequence is over and the plugin has registered with NRI,
|
||||||
|
it will start receiving pod and container lifecycle events according to its
|
||||||
|
subscription.
|
||||||
|
|
||||||
**clearcfs**
|
#### Pod Data and Available Lifecycle Events
|
||||||
|
|
||||||
Clear the cfs quotas for `ls` services.
|
<details>
|
||||||
|
<summary>NRI Pod Lifecycle Events</summary>
|
||||||
|
<p align="center">
|
||||||
|
<img src="./docs/nri-pod-lifecycle.svg" title="NRI Pod Lifecycle Events">
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
NRI plugins can subscribe to the following pod lifecycle events:
|
||||||
|
|
||||||
|
- creation
|
||||||
|
- stopping
|
||||||
|
- removal
|
||||||
|
|
||||||
|
The following pieces of pod metadata are available to plugins in NRI:
|
||||||
|
|
||||||
|
- ID
|
||||||
|
- name
|
||||||
|
- UID
|
||||||
|
- namespace
|
||||||
|
- labels
|
||||||
|
- annotations
|
||||||
|
- cgroup parent directory
|
||||||
|
- runtime handler name
|
||||||
|
|
||||||
|
#### Container Data and Available Lifecycle Events
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>NRI Container Lifecycle Events</summary>
|
||||||
|
<p align="center">
|
||||||
|
<img src="./docs/nri-container-lifecycle.svg" title="NRI Container Lifecycle Events">
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
NRI plugins can subscribe to the following container lifecycle events:
|
||||||
|
|
||||||
|
- creation (*)
|
||||||
|
- post-creation
|
||||||
|
- starting
|
||||||
|
- post-start
|
||||||
|
- updating (*)
|
||||||
|
- post-update
|
||||||
|
- stopping (*)
|
||||||
|
- removal
|
||||||
|
|
||||||
|
*) Plugins can request adjustment or updates to containers in response to
|
||||||
|
these events.
|
||||||
|
|
||||||
|
The following pieces of container metadata are available to plugins in NRI:
|
||||||
|
|
||||||
|
- ID
|
||||||
|
- pod ID
|
||||||
|
- name
|
||||||
|
- state
|
||||||
|
- labels
|
||||||
|
- annotations
|
||||||
|
- command line arguments
|
||||||
|
- environment variables
|
||||||
|
- mounts
|
||||||
|
- OCI hooks
|
||||||
|
- linux
|
||||||
|
- namespace IDs
|
||||||
|
- devices
|
||||||
|
- resources
|
||||||
|
- memory
|
||||||
|
- limit
|
||||||
|
- reservation
|
||||||
|
- swap limit
|
||||||
|
- kernel limit
|
||||||
|
- kernel TCP limit
|
||||||
|
- swappiness
|
||||||
|
- OOM disabled flag
|
||||||
|
- hierarchical accounting flag
|
||||||
|
- hugepage limits
|
||||||
|
- CPU
|
||||||
|
- shares
|
||||||
|
- quota
|
||||||
|
- period
|
||||||
|
- realtime runtime
|
||||||
|
- realtime period
|
||||||
|
- cpuset CPUs
|
||||||
|
- cpuset memory
|
||||||
|
- Block I/O class
|
||||||
|
- RDT class
|
||||||
|
|
||||||
|
Apart from data identifying the container, these pieces of information
|
||||||
|
represent the corresponding data in the container's OCI Spec.
|
||||||
|
|
||||||
|
#### Container Adjustment
|
||||||
|
|
||||||
|
During container creation plugins can request changes to the following
|
||||||
|
container parameters:
|
||||||
|
|
||||||
|
- annotations
|
||||||
|
- mounts
|
||||||
|
- environment variables
|
||||||
|
- OCI hooks
|
||||||
|
- linux
|
||||||
|
- devices
|
||||||
|
- resources
|
||||||
|
- memory
|
||||||
|
- limit
|
||||||
|
- reservation
|
||||||
|
- swap limit
|
||||||
|
- kernel limit
|
||||||
|
- kernel TCP limit
|
||||||
|
- swappiness
|
||||||
|
- OOM disabled flag
|
||||||
|
- hierarchical accounting flag
|
||||||
|
- hugepage limits
|
||||||
|
- CPU
|
||||||
|
- shares
|
||||||
|
- quota
|
||||||
|
- period
|
||||||
|
- realtime runtime
|
||||||
|
- realtime period
|
||||||
|
- cpuset CPUs
|
||||||
|
- cpuset memory
|
||||||
|
- Block I/O class
|
||||||
|
- RDT class
|
||||||
|
|
||||||
|
#### Container Updates
|
||||||
|
|
||||||
|
Once a container has been created plugins can request updates to them.
|
||||||
|
These updates can be requested in response to another containers creation
|
||||||
|
request, in response to any containers update request, in response to any
|
||||||
|
containers stop request, or they can be requested as part of a separate
|
||||||
|
unsolicited container update request. The following container parameters
|
||||||
|
can be updated this way:
|
||||||
|
|
||||||
|
- resources
|
||||||
|
- memory
|
||||||
|
- limit
|
||||||
|
- reservation
|
||||||
|
- swap limit
|
||||||
|
- kernel limit
|
||||||
|
- kernel TCP limit
|
||||||
|
- swappiness
|
||||||
|
- OOM disabled flag
|
||||||
|
- hierarchical accounting flag
|
||||||
|
- hugepage limits
|
||||||
|
- CPU
|
||||||
|
- shares
|
||||||
|
- quota
|
||||||
|
- period
|
||||||
|
- realtime runtime
|
||||||
|
- realtime period
|
||||||
|
- cpuset CPUs
|
||||||
|
- cpuset memory
|
||||||
|
- Block I/O class
|
||||||
|
- RDT class
|
||||||
|
|
||||||
|
|
||||||
```go
|
### Runtime Adaptation
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
The NRI [runtime adaptation](pkg/adaptation) package is the interface
|
||||||
"context"
|
runtimes use to integrate to NRI and interact with NRI plugins. It
|
||||||
"fmt"
|
implements basic plugin discovery, startup and configuration. It also
|
||||||
"os"
|
provides the functions necessary to hook NRI plugins into lifecycle
|
||||||
|
events of pods and containers from the runtime.
|
||||||
|
|
||||||
"github.com/containerd/containerd/pkg/nri/skel"
|
The package hides the fact that multiple NRI plugins might be processing
|
||||||
"github.com/containerd/containerd/pkg/nri/types"
|
any single pod or container lifecycle event. It takes care of invoking
|
||||||
"github.com/sirupsen/logrus"
|
plugins in the correct order and combining responses by multiple plugins
|
||||||
)
|
into a single one. While combining responses, the package detects any
|
||||||
|
unintentional conflicting changes made by multiple plugins to a single
|
||||||
|
container and flags such an event as an error to the runtime.
|
||||||
|
|
||||||
var max = []byte("max")
|
### Wrapped OCI Spec Generator
|
||||||
|
|
||||||
// clearCFS clears any cfs quotas for the containers
|
The [OCI Spec generator](pkg/runtime-tools/generate) package wraps the
|
||||||
type clearCFS struct {
|
[corresponding package](https://github.com/opencontainers/runtime-tools/tree/master/generate)
|
||||||
}
|
and adds functions for applying NRI container adjustments and updates to
|
||||||
|
OCI Specs. This package can be used by runtime NRI integration code to
|
||||||
|
apply NRI responses to containers.
|
||||||
|
|
||||||
func (c *clearCFS) Type() string {
|
### Plugin Stub Library
|
||||||
return "clearcfs"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *clearCFS) Invoke(ctx context.Context, r *types.Request) (*types.Result, error) {
|
The plugin stub hides many of the low-level details of implementing an NRI
|
||||||
result := r.NewResult()
|
plugin. It takes care of connection establishment, plugin registration,
|
||||||
if r.State != types.Create {
|
configuration, and event subscription. All [sample plugins](pkg/plugins)
|
||||||
return result, nil
|
are implemented using the stub. Any of these can be used as a tutorial on
|
||||||
}
|
how the stub library should be used.
|
||||||
switch r.Spec.Annotations["qos.class"] {
|
|
||||||
case "ls":
|
|
||||||
logrus.Debugf("clearing cfs for %s", r.ID)
|
|
||||||
group, err := cg.Load(r.Spec.CgroupsPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result, group.Write(cg.CFSMax)
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
### Sample Plugins
|
||||||
ctx := context.Background()
|
|
||||||
if err := skel.Run(ctx, &clearCFS{}); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Project details
|
The following sample plugins exist for NRI:
|
||||||
|
|
||||||
nri is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
|
- [logger](plugins/logger)
|
||||||
As a containerd sub-project, you will find the:
|
- [differ](plugins/differ)
|
||||||
|
- [device injector](plugins/device-injector)
|
||||||
|
- [OCI hook injector](plugins/hook-injector)
|
||||||
|
- [NRI v0.1.0 plugin adapter](plugins/v010-adapter)
|
||||||
|
|
||||||
* [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md),
|
Please see the documentation of these plugins for further details
|
||||||
* [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS),
|
about what and how each of these plugins can be used for.
|
||||||
* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
|
|
||||||
|
|
||||||
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
|
||||||
|
5
vendor/github.com/containerd/nri/client.go
generated
vendored
5
vendor/github.com/containerd/nri/client.go
generated
vendored
@ -28,7 +28,6 @@ import (
|
|||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
types "github.com/containerd/nri/types/v1"
|
types "github.com/containerd/nri/types/v1"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -107,7 +106,7 @@ func (c *Client) InvokeWithSandbox(ctx context.Context, task containerd.Task, st
|
|||||||
r.Conf = p.Conf
|
r.Conf = p.Conf
|
||||||
result, err := c.invokePlugin(ctx, p.Type, r)
|
result, err := c.invokePlugin(ctx, p.Type, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "plugin: %s", p.Type)
|
return nil, fmt.Errorf("plugin: %s: %w", p.Type, err)
|
||||||
}
|
}
|
||||||
r.Results = append(r.Results, result)
|
r.Results = append(r.Results, result)
|
||||||
}
|
}
|
||||||
@ -141,7 +140,7 @@ func (c *Client) invokePlugin(ctx context.Context, name string, r *types.Request
|
|||||||
}
|
}
|
||||||
var result types.Result
|
var result types.Result
|
||||||
if err := json.Unmarshal(out, &result); err != nil {
|
if err := json.Unmarshal(out, &result); err != nil {
|
||||||
return nil, errors.Errorf("failed to unmarshal plugin output: %s: %s", err.Error(), msg)
|
return nil, fmt.Errorf("failed to unmarshal plugin output %s: %w", msg, err)
|
||||||
}
|
}
|
||||||
if result.Err() != nil {
|
if result.Err() != nil {
|
||||||
return nil, result.Err()
|
return nil, result.Err()
|
||||||
|
504
vendor/github.com/containerd/nri/pkg/adaptation/adaptation.go
generated
vendored
Normal file
504
vendor/github.com/containerd/nri/pkg/adaptation/adaptation.go
generated
vendored
Normal file
@ -0,0 +1,504 @@
|
|||||||
|
/*
|
||||||
|
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 (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/containerd/nri/pkg/api"
|
||||||
|
"github.com/containerd/nri/pkg/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
// SyncFn is a container runtime function for state synchronization.
|
||||||
|
type SyncFn func(context.Context, SyncCB) error
|
||||||
|
|
||||||
|
// SyncCB is an NRI function used to synchronize plugins with the runtime.
|
||||||
|
type SyncCB func(context.Context, []*PodSandbox, []*Container) ([]*ContainerUpdate, error)
|
||||||
|
|
||||||
|
// UpdateFn is a container runtime function for unsolicited container updates.
|
||||||
|
type UpdateFn func(context.Context, []*ContainerUpdate) ([]*ContainerUpdate, error)
|
||||||
|
|
||||||
|
// Adaptation is the NRI abstraction for container runtime NRI adaptation/integration.
|
||||||
|
type Adaptation struct {
|
||||||
|
sync.Mutex
|
||||||
|
name string
|
||||||
|
version string
|
||||||
|
configPath string
|
||||||
|
pluginPath string
|
||||||
|
socketPath string
|
||||||
|
syncFn SyncFn
|
||||||
|
updateFn UpdateFn
|
||||||
|
cfg *Config
|
||||||
|
listener net.Listener
|
||||||
|
plugins []*plugin
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Used instead of nil Context in logging.
|
||||||
|
noCtx = context.TODO()
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
r.pluginPath = path
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSocketPath returns an option to override the default NRI socket path.
|
||||||
|
func WithSocketPath(path string) Option {
|
||||||
|
return func(r *Adaptation) error {
|
||||||
|
r.socketPath = path
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new NRI Runtime.
|
||||||
|
func New(name, version string, syncFn SyncFn, updateFn UpdateFn, opts ...Option) (*Adaptation, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
r := &Adaptation{
|
||||||
|
name: name,
|
||||||
|
version: version,
|
||||||
|
syncFn: syncFn,
|
||||||
|
updateFn: updateFn,
|
||||||
|
configPath: DefaultConfigPath,
|
||||||
|
pluginPath: DefaultPluginPath,
|
||||||
|
socketPath: DefaultSocketPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o := range opts {
|
||||||
|
if err = o(r); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to apply option: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start up the NRI runtime.
|
||||||
|
func (r *Adaptation) Start() error {
|
||||||
|
log.Infof(noCtx, "runtime interface starting up...")
|
||||||
|
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
|
||||||
|
if err := r.startPlugins(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.startListener(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the NRI runtime.
|
||||||
|
func (r *Adaptation) Stop() {
|
||||||
|
log.Infof(noCtx, "runtime interface shutting down...")
|
||||||
|
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
|
||||||
|
r.stopListener()
|
||||||
|
r.stopPlugins()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunPodSandbox relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) RunPodSandbox(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_RUN_POD_SANDBOX
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopPodSandbox relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) StopPodSandbox(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_STOP_POD_SANDBOX
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemovePodSandbox relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) RemovePodSandbox(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_REMOVE_POD_SANDBOX
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateContainer relays the corresponding CRI request to plugins.
|
||||||
|
func (r *Adaptation) CreateContainer(ctx context.Context, req *CreateContainerRequest) (*CreateContainerResponse, error) {
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
defer r.removeClosedPlugins()
|
||||||
|
|
||||||
|
result := collectCreateContainerResult(req)
|
||||||
|
for _, plugin := range r.plugins {
|
||||||
|
rpl, err := plugin.createContainer(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = result.apply(rpl, plugin.name())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.createContainerResponse(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostCreateContainer relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) PostCreateContainer(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_POST_CREATE_CONTAINER
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartContainer relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) StartContainer(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_START_CONTAINER
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostStartContainer relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) PostStartContainer(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_POST_START_CONTAINER
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateContainer relays the corresponding CRI request to plugins.
|
||||||
|
func (r *Adaptation) UpdateContainer(ctx context.Context, req *UpdateContainerRequest) (*UpdateContainerResponse, error) {
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
defer r.removeClosedPlugins()
|
||||||
|
|
||||||
|
result := collectUpdateContainerResult(req)
|
||||||
|
for _, plugin := range r.plugins {
|
||||||
|
rpl, err := plugin.updateContainer(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = result.apply(rpl, plugin.name())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.updateContainerResponse(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostUpdateContainer relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) PostUpdateContainer(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_POST_UPDATE_CONTAINER
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopContainer relays the corresponding CRI request to plugins.
|
||||||
|
func (r *Adaptation) StopContainer(ctx context.Context, req *StopContainerRequest) (*StopContainerResponse, error) {
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
defer r.removeClosedPlugins()
|
||||||
|
|
||||||
|
result := collectStopContainerResult()
|
||||||
|
for _, plugin := range r.plugins {
|
||||||
|
rpl, err := plugin.stopContainer(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = result.apply(rpl, plugin.name())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.stopContainerResponse(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveContainer relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) RemoveContainer(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_REMOVE_CONTAINER
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StateChange relays pod- or container events to plugins.
|
||||||
|
func (r *Adaptation) StateChange(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
if evt.Event == Event_UNKNOWN {
|
||||||
|
return errors.New("invalid (unset) event in state change notification")
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
defer r.removeClosedPlugins()
|
||||||
|
|
||||||
|
for _, plugin := range r.plugins {
|
||||||
|
err := plugin.StateChange(ctx, evt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a set of unsolicited container updates requested by a plugin.
|
||||||
|
func (r *Adaptation) updateContainers(ctx context.Context, req []*ContainerUpdate) ([]*ContainerUpdate, error) {
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
|
||||||
|
return r.updateFn(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start up pre-installed plugins.
|
||||||
|
func (r *Adaptation) startPlugins() (retErr error) {
|
||||||
|
var plugins []*plugin
|
||||||
|
|
||||||
|
log.Infof(noCtx, "starting plugins...")
|
||||||
|
|
||||||
|
ids, names, configs, err := r.discoverPlugins()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
for _, p := range plugins {
|
||||||
|
p.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for i, name := range names {
|
||||||
|
log.Infof(noCtx, "starting plugin %q...", name)
|
||||||
|
|
||||||
|
id := ids[i]
|
||||||
|
|
||||||
|
p, err := newLaunchedPlugin(r.pluginPath, id, name, configs[i])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to start NRI plugin %q: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := p.start(r.name, r.version); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins = append(plugins, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.plugins = plugins
|
||||||
|
r.sortPlugins()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop plugins.
|
||||||
|
func (r *Adaptation) stopPlugins() {
|
||||||
|
log.Infof(noCtx, "stopping plugins...")
|
||||||
|
|
||||||
|
for _, p := range r.plugins {
|
||||||
|
p.stop()
|
||||||
|
}
|
||||||
|
r.plugins = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Adaptation) removeClosedPlugins() {
|
||||||
|
active := []*plugin{}
|
||||||
|
for _, p := range r.plugins {
|
||||||
|
if !p.isClosed() {
|
||||||
|
active = append(active, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.plugins = active
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Adaptation) startListener() error {
|
||||||
|
if r.cfg.DisableConnections {
|
||||||
|
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 {
|
||||||
|
return fmt.Errorf("failed to create socket %q: %w", r.socketPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := net.ListenUnix("unix", &net.UnixAddr{
|
||||||
|
Name: r.socketPath,
|
||||||
|
Net: "unix",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create socket %q: %w", r.socketPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.acceptPluginConnections(l)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Adaptation) stopListener() {
|
||||||
|
if r.listener != nil {
|
||||||
|
r.listener.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Adaptation) acceptPluginConnections(l net.Listener) error {
|
||||||
|
r.listener = l
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
conn, err := l.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.Infof(ctx, "stopped accepting plugin connections (%v)", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p, err := newExternalPlugin(conn)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf(ctx, "failed to create external plugin: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := p.start(r.name, r.version); err != nil {
|
||||||
|
log.Errorf(ctx, "failed to start external plugin: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Lock()
|
||||||
|
|
||||||
|
err = r.syncFn(ctx, p.synchronize)
|
||||||
|
if err != nil {
|
||||||
|
log.Infof(ctx, "failed to synchronize plugin: %v", err)
|
||||||
|
} else {
|
||||||
|
r.plugins = append(r.plugins, p)
|
||||||
|
r.sortPlugins()
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Unlock()
|
||||||
|
|
||||||
|
log.Infof(ctx, "plugin %q connected", p.name())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Adaptation) discoverPlugins() ([]string, []string, []string, error) {
|
||||||
|
var (
|
||||||
|
plugins []string
|
||||||
|
indices []string
|
||||||
|
configs []string
|
||||||
|
entries []os.DirEntry
|
||||||
|
info fs.FileInfo
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if entries, err = os.ReadDir(r.pluginPath); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil, nil, nil, nil
|
||||||
|
}
|
||||||
|
return nil, nil, nil, fmt.Errorf("failed to discover plugins in %s: %w",
|
||||||
|
r.pluginPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, e := range entries {
|
||||||
|
if e.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if info, err = e.Info(); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if info.Mode()&fs.FileMode(0o111) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
name := e.Name()
|
||||||
|
idx, base, err := api.ParsePluginName(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, fmt.Errorf("failed to discover plugins in %s: %w",
|
||||||
|
r.pluginPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, err := r.cfg.getPluginConfig(idx, base)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, fmt.Errorf("failed to discover plugins in %s: %w",
|
||||||
|
r.pluginPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof(noCtx, "discovered plugin %s", name)
|
||||||
|
|
||||||
|
indices = append(indices, idx)
|
||||||
|
plugins = append(plugins, base)
|
||||||
|
configs = append(configs, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return indices, plugins, configs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Adaptation) sortPlugins() {
|
||||||
|
r.removeClosedPlugins()
|
||||||
|
sort.Slice(r.plugins, func(i, j int) bool {
|
||||||
|
return r.plugins[i].idx < r.plugins[j].idx
|
||||||
|
})
|
||||||
|
if len(r.plugins) > 0 {
|
||||||
|
log.Infof(noCtx, "plugin invocation order")
|
||||||
|
for i, p := range r.plugins {
|
||||||
|
log.Infof(noCtx, " #%d: %q (%s)", i+1, p.name(), p.qualifiedName())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
151
vendor/github.com/containerd/nri/pkg/adaptation/api.go
generated
vendored
Normal file
151
vendor/github.com/containerd/nri/pkg/adaptation/api.go
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
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 (
|
||||||
|
"github.com/containerd/nri/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Alias types, consts and functions from api for the runtime.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Aliased request/response/event types for api/api.proto.
|
||||||
|
// nolint
|
||||||
|
type (
|
||||||
|
RegisterPluginRequest = api.RegisterPluginRequest
|
||||||
|
RegisterPluginResponse = api.Empty
|
||||||
|
UpdateContainersRequest = api.UpdateContainersRequest
|
||||||
|
UpdateContainersResponse = api.UpdateContainersResponse
|
||||||
|
|
||||||
|
ConfigureRequest = api.ConfigureRequest
|
||||||
|
ConfigureResponse = api.ConfigureResponse
|
||||||
|
SynchronizeRequest = api.SynchronizeRequest
|
||||||
|
SynchronizeResponse = api.SynchronizeResponse
|
||||||
|
|
||||||
|
CreateContainerRequest = api.CreateContainerRequest
|
||||||
|
CreateContainerResponse = api.CreateContainerResponse
|
||||||
|
UpdateContainerRequest = api.UpdateContainerRequest
|
||||||
|
UpdateContainerResponse = api.UpdateContainerResponse
|
||||||
|
StopContainerRequest = api.StopContainerRequest
|
||||||
|
StopContainerResponse = api.StopContainerResponse
|
||||||
|
|
||||||
|
StateChangeEvent = api.StateChangeEvent
|
||||||
|
StateChangeResponse = api.StateChangeResponse
|
||||||
|
RunPodSandboxRequest = api.RunPodSandboxRequest
|
||||||
|
StopPodSandboxRequest = api.StopPodSandboxRequest
|
||||||
|
RemovePodSandboxRequest = api.RemovePodSandboxRequest
|
||||||
|
StartContainerRequest = api.StartContainerRequest
|
||||||
|
StartContainerResponse = api.StartContainerResponse
|
||||||
|
RemoveContainerRequest = api.RemoveContainerRequest
|
||||||
|
RemoveContainerResponse = api.RemoveContainerResponse
|
||||||
|
PostCreateContainerRequest = api.PostCreateContainerRequest
|
||||||
|
PostCreateContainerResponse = api.PostCreateContainerResponse
|
||||||
|
PostStartContainerRequest = api.PostStartContainerRequest
|
||||||
|
PostStartContainerResponse = api.PostStartContainerResponse
|
||||||
|
PostUpdateContainerRequest = api.PostUpdateContainerRequest
|
||||||
|
PostUpdateContainerResponse = api.PostUpdateContainerResponse
|
||||||
|
|
||||||
|
PodSandbox = api.PodSandbox
|
||||||
|
LinuxPodSandbox = api.LinuxPodSandbox
|
||||||
|
Container = api.Container
|
||||||
|
ContainerAdjustment = api.ContainerAdjustment
|
||||||
|
LinuxContainerAdjustment = api.LinuxContainerAdjustment
|
||||||
|
ContainerUpdate = api.ContainerUpdate
|
||||||
|
LinuxContainerUpdate = api.LinuxContainerUpdate
|
||||||
|
ContainerEviction = api.ContainerEviction
|
||||||
|
ContainerState = api.ContainerState
|
||||||
|
KeyValue = api.KeyValue
|
||||||
|
Mount = api.Mount
|
||||||
|
LinuxContainer = api.LinuxContainer
|
||||||
|
LinuxNamespace = api.LinuxNamespace
|
||||||
|
LinuxResources = api.LinuxResources
|
||||||
|
LinuxCPU = api.LinuxCPU
|
||||||
|
LinuxMemory = api.LinuxMemory
|
||||||
|
LinuxDevice = api.LinuxDevice
|
||||||
|
LinuxDeviceCgroup = api.LinuxDeviceCgroup
|
||||||
|
HugepageLimit = api.HugepageLimit
|
||||||
|
Hooks = api.Hooks
|
||||||
|
Hook = api.Hook
|
||||||
|
|
||||||
|
EventMask = api.EventMask
|
||||||
|
)
|
||||||
|
|
||||||
|
// Aliased consts for api/api.proto.
|
||||||
|
// nolint
|
||||||
|
const (
|
||||||
|
Event_UNKNOWN = api.Event_UNKNOWN
|
||||||
|
Event_RUN_POD_SANDBOX = api.Event_RUN_POD_SANDBOX
|
||||||
|
Event_STOP_POD_SANDBOX = api.Event_STOP_POD_SANDBOX
|
||||||
|
Event_REMOVE_POD_SANDBOX = api.Event_REMOVE_POD_SANDBOX
|
||||||
|
Event_CREATE_CONTAINER = api.Event_CREATE_CONTAINER
|
||||||
|
Event_POST_CREATE_CONTAINER = api.Event_POST_CREATE_CONTAINER
|
||||||
|
Event_START_CONTAINER = api.Event_START_CONTAINER
|
||||||
|
Event_POST_START_CONTAINER = api.Event_POST_START_CONTAINER
|
||||||
|
Event_UPDATE_CONTAINER = api.Event_UPDATE_CONTAINER
|
||||||
|
Event_POST_UPDATE_CONTAINER = api.Event_POST_UPDATE_CONTAINER
|
||||||
|
Event_STOP_CONTAINER = api.Event_STOP_CONTAINER
|
||||||
|
Event_REMOVE_CONTAINER = api.Event_REMOVE_CONTAINER
|
||||||
|
ValidEvents = api.ValidEvents
|
||||||
|
|
||||||
|
ContainerState_CONTAINER_UNKNOWN = api.ContainerState_CONTAINER_UNKNOWN
|
||||||
|
ContainerState_CONTAINER_CREATED = api.ContainerState_CONTAINER_CREATED
|
||||||
|
ContainerState_CONTAINER_PAUSED = api.ContainerState_CONTAINER_PAUSED
|
||||||
|
ContainerState_CONTAINER_RUNNING = api.ContainerState_CONTAINER_RUNNING
|
||||||
|
ContainerState_CONTAINER_STOPPED = api.ContainerState_CONTAINER_STOPPED
|
||||||
|
ContainerState_CONTAINER_EXITED = api.ContainerState_CONTAINER_STOPPED
|
||||||
|
)
|
||||||
|
|
||||||
|
// Aliased types for api/optional.go.
|
||||||
|
// nolint
|
||||||
|
type (
|
||||||
|
OptionalString = api.OptionalString
|
||||||
|
OptionalInt = api.OptionalInt
|
||||||
|
OptionalInt32 = api.OptionalInt32
|
||||||
|
OptionalUInt32 = api.OptionalUInt32
|
||||||
|
OptionalInt64 = api.OptionalInt64
|
||||||
|
OptionalUInt64 = api.OptionalUInt64
|
||||||
|
OptionalBool = api.OptionalBool
|
||||||
|
OptionalFileMode = api.OptionalFileMode
|
||||||
|
)
|
||||||
|
|
||||||
|
// Aliased functions for api/optional.go.
|
||||||
|
// nolint
|
||||||
|
var (
|
||||||
|
String = api.String
|
||||||
|
Int = api.Int
|
||||||
|
Int32 = api.Int32
|
||||||
|
UInt32 = api.UInt32
|
||||||
|
Int64 = api.Int64
|
||||||
|
UInt64 = api.UInt64
|
||||||
|
Bool = api.Bool
|
||||||
|
FileMode = api.FileMode
|
||||||
|
)
|
||||||
|
|
||||||
|
// Aliased functions for api/types.go.
|
||||||
|
// nolint
|
||||||
|
var (
|
||||||
|
FromOCIMounts = api.FromOCIMounts
|
||||||
|
FromOCIHooks = api.FromOCIHooks
|
||||||
|
FromOCILinuxNamespaces = api.FromOCILinuxNamespaces
|
||||||
|
FromOCILinuxDevices = api.FromOCILinuxDevices
|
||||||
|
FromOCILinuxResources = api.FromOCILinuxResources
|
||||||
|
DupStringSlice = api.DupStringSlice
|
||||||
|
DupStringMap = api.DupStringMap
|
||||||
|
IsMarkedForRemoval = api.IsMarkedForRemoval
|
||||||
|
MarkForRemoval = api.MarkForRemoval
|
||||||
|
)
|
95
vendor/github.com/containerd/nri/pkg/adaptation/config.go
generated
vendored
Normal file
95
vendor/github.com/containerd/nri/pkg/adaptation/config.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
}
|
468
vendor/github.com/containerd/nri/pkg/adaptation/plugin.go
generated
vendored
Normal file
468
vendor/github.com/containerd/nri/pkg/adaptation/plugin.go
generated
vendored
Normal file
@ -0,0 +1,468 @@
|
|||||||
|
/*
|
||||||
|
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 (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
stdnet "net"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/nri/pkg/api"
|
||||||
|
"github.com/containerd/nri/pkg/log"
|
||||||
|
"github.com/containerd/nri/pkg/net"
|
||||||
|
"github.com/containerd/nri/pkg/net/multiplex"
|
||||||
|
"github.com/containerd/ttrpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
pluginRegistrationTimeout = 2 * time.Second
|
||||||
|
pluginRequestTimeout = 2 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
|
type plugin struct {
|
||||||
|
sync.Mutex
|
||||||
|
idx string
|
||||||
|
base string
|
||||||
|
cfg string
|
||||||
|
pid int
|
||||||
|
cmd *exec.Cmd
|
||||||
|
mux multiplex.Mux
|
||||||
|
rpcc *ttrpc.Client
|
||||||
|
rpcl stdnet.Listener
|
||||||
|
rpcs *ttrpc.Server
|
||||||
|
events EventMask
|
||||||
|
closed bool
|
||||||
|
stub api.PluginService
|
||||||
|
regC chan error
|
||||||
|
closeC chan struct{}
|
||||||
|
r *Adaptation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Launch a pre-installed plugin with a pre-connected socketpair.
|
||||||
|
func newLaunchedPlugin(dir, idx, base, cfg string) (p *plugin, retErr error) {
|
||||||
|
name := idx + "-" + base
|
||||||
|
|
||||||
|
sockets, err := net.NewSocketPair()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create plugin connection for plugin %q: %w", name, err)
|
||||||
|
}
|
||||||
|
defer sockets.Close()
|
||||||
|
|
||||||
|
conn, err := sockets.LocalConn()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to set up local connection for plugin %q: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
peerFile := sockets.PeerFile()
|
||||||
|
defer func() {
|
||||||
|
peerFile.Close()
|
||||||
|
if retErr != nil {
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
cmd := exec.Command(filepath.Join(dir, name))
|
||||||
|
cmd.ExtraFiles = []*os.File{peerFile}
|
||||||
|
cmd.Env = []string{
|
||||||
|
api.PluginNameEnvVar + "=" + name,
|
||||||
|
api.PluginIdxEnvVar + "=" + idx,
|
||||||
|
api.PluginSocketEnvVar + "=3",
|
||||||
|
}
|
||||||
|
|
||||||
|
p = &plugin{
|
||||||
|
cfg: cfg,
|
||||||
|
cmd: cmd,
|
||||||
|
idx: idx,
|
||||||
|
base: base,
|
||||||
|
regC: make(chan error, 1),
|
||||||
|
closeC: make(chan struct{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = p.cmd.Start(); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed launch plugin %q: %w", p.name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = p.connect(conn); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a plugin (stub) for an accepted external plugin connection.
|
||||||
|
func newExternalPlugin(conn stdnet.Conn) (p *plugin, retErr error) {
|
||||||
|
p = &plugin{
|
||||||
|
regC: make(chan error, 1),
|
||||||
|
closeC: make(chan struct{}),
|
||||||
|
}
|
||||||
|
if err := p.connect(conn); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the plugin is external (was not launched by us).
|
||||||
|
func (p *plugin) isExternal() bool {
|
||||||
|
return p.cmd == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'connect' a plugin, setting up multiplexing on its socket.
|
||||||
|
func (p *plugin) connect(conn stdnet.Conn) (retErr error) {
|
||||||
|
mux := multiplex.Multiplex(conn, multiplex.WithBlockedRead())
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
mux.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
pconn, err := mux.Open(multiplex.PluginServiceConn)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to mux plugin connection for plugin %q: %w", p.name(), err)
|
||||||
|
}
|
||||||
|
rpcc := ttrpc.NewClient(pconn, ttrpc.WithOnClose(
|
||||||
|
func() {
|
||||||
|
log.Infof(noCtx, "connection to plugin %q closed", p.name())
|
||||||
|
close(p.closeC)
|
||||||
|
p.close()
|
||||||
|
}))
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
rpcc.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
stub := api.NewPluginClient(rpcc)
|
||||||
|
|
||||||
|
rpcs, err := ttrpc.NewServer()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create ttrpc server for plugin %q: %w", p.name(), err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
rpcs.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
rpcl, err := mux.Listen(multiplex.RuntimeServiceConn)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create mux runtime listener for plugin %q: %w", p.name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.mux = mux
|
||||||
|
p.rpcc = rpcc
|
||||||
|
p.rpcl = rpcl
|
||||||
|
p.rpcs = rpcs
|
||||||
|
p.stub = stub
|
||||||
|
|
||||||
|
p.pid, err = getPeerPid(p.mux.Trunk())
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf(noCtx, "failed to determine plugin pid pid: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
api.RegisterRuntimeService(p.rpcs, p)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start Runtime service, wait for plugin to register, then configure it.
|
||||||
|
func (p *plugin) start(name, version string) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err := p.rpcs.Serve(context.Background(), p.rpcl)
|
||||||
|
if err != ttrpc.ErrServerClosed {
|
||||||
|
log.Infof(noCtx, "ttrpc server for plugin %q closed (%v)", p.name(), err)
|
||||||
|
}
|
||||||
|
p.close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
p.mux.Unblock()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case err = <-p.regC:
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to register plugin: %w", err)
|
||||||
|
}
|
||||||
|
case <-p.closeC:
|
||||||
|
return fmt.Errorf("failed to register plugin, connection closed: %w", err)
|
||||||
|
case <-time.After(pluginRegistrationTimeout):
|
||||||
|
p.close()
|
||||||
|
p.stop()
|
||||||
|
return errors.New("plugin registration timed out")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = p.configure(context.Background(), name, version, p.cfg)
|
||||||
|
if err != nil {
|
||||||
|
p.close()
|
||||||
|
p.stop()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// close a plugin shutting down its multiplexed ttrpc connections.
|
||||||
|
func (p *plugin) close() {
|
||||||
|
p.Lock()
|
||||||
|
defer p.Unlock()
|
||||||
|
if p.closed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p.closed = true
|
||||||
|
p.mux.Close()
|
||||||
|
p.rpcc.Close()
|
||||||
|
p.rpcs.Close()
|
||||||
|
p.rpcl.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *plugin) isClosed() bool {
|
||||||
|
p.Lock()
|
||||||
|
defer p.Unlock()
|
||||||
|
return p.closed
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop a plugin (if it was launched by us)
|
||||||
|
func (p *plugin) stop() error {
|
||||||
|
if p.isExternal() || p.cmd.Process == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(klihub):
|
||||||
|
// We should attempt a graceful shutdown of the process here...
|
||||||
|
// - send it SIGINT
|
||||||
|
// - give the it some slack waiting with a timeout
|
||||||
|
// - butcher it with SIGKILL after the timeout
|
||||||
|
|
||||||
|
p.cmd.Process.Kill()
|
||||||
|
p.cmd.Process.Wait()
|
||||||
|
p.cmd.Process.Release()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns a string indentication for the plugin.
|
||||||
|
func (p *plugin) name() string {
|
||||||
|
return p.idx + "-" + p.base
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *plugin) qualifiedName() string {
|
||||||
|
var kind, idx, base string
|
||||||
|
if p.isExternal() {
|
||||||
|
kind = "external"
|
||||||
|
} else {
|
||||||
|
kind = "pre-connected"
|
||||||
|
}
|
||||||
|
if idx = p.idx; idx == "" {
|
||||||
|
idx = "??"
|
||||||
|
}
|
||||||
|
if base = p.base; base == "" {
|
||||||
|
base = "plugin"
|
||||||
|
}
|
||||||
|
return kind + ":" + idx + "-" + base + "[" + strconv.Itoa(p.pid) + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterPlugin handles the plugin's registration request.
|
||||||
|
func (p *plugin) RegisterPlugin(ctx context.Context, req *RegisterPluginRequest) (*RegisterPluginResponse, error) {
|
||||||
|
if p.isExternal() {
|
||||||
|
if req.PluginName == "" {
|
||||||
|
p.regC <- fmt.Errorf("plugin %q registered empty name", p.qualifiedName())
|
||||||
|
return &RegisterPluginResponse{}, errors.New("invalid (empty) plugin name")
|
||||||
|
}
|
||||||
|
if err := api.CheckPluginIndex(req.PluginIdx); err != nil {
|
||||||
|
p.regC <- fmt.Errorf("plugin %q registered invalid index: %w", req.PluginName, err)
|
||||||
|
return &RegisterPluginResponse{}, fmt.Errorf("invalid plugin index: %w", err)
|
||||||
|
}
|
||||||
|
p.base = req.PluginName
|
||||||
|
p.idx = req.PluginIdx
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof(ctx, "plugin %q registered as %q", p.qualifiedName(), p.name())
|
||||||
|
|
||||||
|
p.regC <- nil
|
||||||
|
return &RegisterPluginResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateContainers relays container update request to the runtime.
|
||||||
|
func (p *plugin) UpdateContainers(ctx context.Context, req *UpdateContainersRequest) (*UpdateContainersResponse, error) {
|
||||||
|
log.Infof(ctx, "plugin %q requested container updates", p.name())
|
||||||
|
|
||||||
|
failed, err := p.r.updateContainers(ctx, req.Update)
|
||||||
|
return &UpdateContainersResponse{
|
||||||
|
Failed: failed,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
rpl, err := p.stub.Configure(ctx, &ConfigureRequest{
|
||||||
|
Config: config,
|
||||||
|
RuntimeName: name,
|
||||||
|
RuntimeVersion: version,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to configure plugin: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
events := EventMask(rpl.Events)
|
||||||
|
if events != 0 {
|
||||||
|
if extra := events &^ ValidEvents; extra != 0 {
|
||||||
|
return fmt.Errorf("invalid plugin events: 0x%x", extra)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
events = ValidEvents
|
||||||
|
}
|
||||||
|
p.events = events
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// synchronize the plugin with the current state of the runtime.
|
||||||
|
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)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
req := &SynchronizeRequest{
|
||||||
|
Pods: pods,
|
||||||
|
Containers: containers,
|
||||||
|
}
|
||||||
|
rpl, err := p.stub.Synchronize(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rpl.Update, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relay CreateContainer request to plugin.
|
||||||
|
func (p *plugin) createContainer(ctx context.Context, req *CreateContainerRequest) (*CreateContainerResponse, error) {
|
||||||
|
if !p.events.IsSet(Event_CREATE_CONTAINER) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
rpl, err := p.stub.CreateContainer(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
if isFatalError(err) {
|
||||||
|
log.Errorf(ctx, "closing plugin %s, failed to handle CreateContainer request: %w",
|
||||||
|
p.name(), err)
|
||||||
|
p.close()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rpl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relay UpdateContainer request to plugin.
|
||||||
|
func (p *plugin) updateContainer(ctx context.Context, req *UpdateContainerRequest) (*UpdateContainerResponse, error) {
|
||||||
|
if !p.events.IsSet(Event_UPDATE_CONTAINER) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
rpl, err := p.stub.UpdateContainer(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
if isFatalError(err) {
|
||||||
|
log.Errorf(ctx, "closing plugin %s, failed to handle UpdateContainer request: %w",
|
||||||
|
p.name(), err)
|
||||||
|
p.close()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rpl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relay StopContainer request to the plugin.
|
||||||
|
func (p *plugin) stopContainer(ctx context.Context, req *StopContainerRequest) (*StopContainerResponse, error) {
|
||||||
|
if !p.events.IsSet(Event_STOP_CONTAINER) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
rpl, err := p.stub.StopContainer(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
if isFatalError(err) {
|
||||||
|
log.Errorf(ctx, "closing plugin %s, failed to handle StopContainer request: %w",
|
||||||
|
p.name(), err)
|
||||||
|
p.close()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rpl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relay other pod or container state change events to the plugin.
|
||||||
|
func (p *plugin) StateChange(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
if !p.events.IsSet(evt.Event) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
_, err := p.stub.StateChange(ctx, evt)
|
||||||
|
if err != nil {
|
||||||
|
if isFatalError(err) {
|
||||||
|
log.Errorf(ctx, "closing plugin %s, failed to handle event %d: %w",
|
||||||
|
p.name(), evt.Event, err)
|
||||||
|
p.close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// isFatalError returns true if the error is fatal and the plugin connection shoudld be closed.
|
||||||
|
func isFatalError(err error) bool {
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, ttrpc.ErrClosed):
|
||||||
|
return true
|
||||||
|
case errors.Is(err, ttrpc.ErrServerClosed):
|
||||||
|
return true
|
||||||
|
case errors.Is(err, ttrpc.ErrProtocol):
|
||||||
|
return true
|
||||||
|
case errors.Is(err, context.DeadlineExceeded):
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
55
vendor/github.com/containerd/nri/pkg/adaptation/plugin_linux.go
generated
vendored
Normal file
55
vendor/github.com/containerd/nri/pkg/adaptation/plugin_linux.go
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
stdnet "net"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// getPeerPid returns the process id at the other end of the connection.
|
||||||
|
func getPeerPid(conn stdnet.Conn) (int, error) {
|
||||||
|
var cred *unix.Ucred
|
||||||
|
|
||||||
|
uc, ok := conn.(*stdnet.UnixConn)
|
||||||
|
if !ok {
|
||||||
|
return 0, errors.New("invalid connection, not *net.UnixConn")
|
||||||
|
}
|
||||||
|
|
||||||
|
raw, err := uc.SyscallConn()
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("failed get raw unix domain connection: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrlErr := raw.Control(func(fd uintptr) {
|
||||||
|
cred, err = unix.GetsockoptUcred(int(fd), unix.SOL_SOCKET, unix.SO_PEERCRED)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("failed to get process credentials: %w", err)
|
||||||
|
}
|
||||||
|
if ctrlErr != nil {
|
||||||
|
return 0, fmt.Errorf("uc.SyscallConn().Control() failed: %w", ctrlErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(cred.Pid), nil
|
||||||
|
}
|
31
vendor/github.com/containerd/nri/pkg/adaptation/plugin_other.go
generated
vendored
Normal file
31
vendor/github.com/containerd/nri/pkg/adaptation/plugin_other.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
//go:build !linux
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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"
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// getPeerPid returns the process id at the other end of the connection.
|
||||||
|
func getPeerPid(conn net.Conn) (int, error) {
|
||||||
|
return 0, fmt.Errorf("getPeerPid() unimplemented on %s", runtime.GOOS)
|
||||||
|
}
|
1245
vendor/github.com/containerd/nri/pkg/adaptation/result.go
generated
vendored
Normal file
1245
vendor/github.com/containerd/nri/pkg/adaptation/result.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
295
vendor/github.com/containerd/nri/pkg/api/adjustment.go
generated
vendored
Normal file
295
vendor/github.com/containerd/nri/pkg/api/adjustment.go
generated
vendored
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
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 api
|
||||||
|
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// Adjustment of metadata that is stored in maps (labels and annotations)
|
||||||
|
// currently assumes that a single plugin will never do an add prior to a
|
||||||
|
// delete for any key. IOW, it is always assumed that if both a deletion
|
||||||
|
// and an addition/setting was recorded for a key then the final desired
|
||||||
|
// state is the addition. This seems like a reasonably safe assumption. A
|
||||||
|
// removal is usually done only to protect against triggering the conflict
|
||||||
|
// in the runtime when a plugin intends to touch a key which is known to
|
||||||
|
// have been put there or already modified by another plugin.
|
||||||
|
//
|
||||||
|
// An alternative without this implicit ordering assumption would be to
|
||||||
|
// store the adjustment for such data as a sequence of add/del operations
|
||||||
|
// in a slice. At the moment that does not seem to be necessary.
|
||||||
|
//
|
||||||
|
|
||||||
|
// AddAnnotation records the addition of the annotation key=value.
|
||||||
|
func (a *ContainerAdjustment) AddAnnotation(key, value string) {
|
||||||
|
a.initAnnotations()
|
||||||
|
a.Annotations[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAnnotation records the removal of the annotation for the given key.
|
||||||
|
// Normally it is an error for a plugin to try and alter an annotation
|
||||||
|
// touched by another plugin. However, this is not an error if the plugin
|
||||||
|
// removes that annotation prior to touching it.
|
||||||
|
func (a *ContainerAdjustment) RemoveAnnotation(key string) {
|
||||||
|
a.initAnnotations()
|
||||||
|
a.Annotations[MarkForRemoval(key)] = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMount records the addition of a mount to a container.
|
||||||
|
func (a *ContainerAdjustment) AddMount(m *Mount) {
|
||||||
|
a.Mounts = append(a.Mounts, m) // TODO: should we dup m here ?
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveMount records the removal of a mount from a container.
|
||||||
|
// Normally it is an error for a plugin to try and alter a mount
|
||||||
|
// touched by another plugin. However, this is not an error if the
|
||||||
|
// plugin removes that mount prior to touching it.
|
||||||
|
func (a *ContainerAdjustment) RemoveMount(ContainerPath string) {
|
||||||
|
a.Mounts = append(a.Mounts, &Mount{
|
||||||
|
Destination: MarkForRemoval(ContainerPath),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEnv records the addition of an environment variable to a container.
|
||||||
|
func (a *ContainerAdjustment) AddEnv(key, value string) {
|
||||||
|
a.Env = append(a.Env, &KeyValue{
|
||||||
|
Key: key,
|
||||||
|
Value: value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveEnv records the removal of an environment variable from a container.
|
||||||
|
// Normally it is an error for a plugin to try and alter an environment
|
||||||
|
// variable touched by another container. However, this is not an error if
|
||||||
|
// the plugin removes that variable prior to touching it.
|
||||||
|
func (a *ContainerAdjustment) RemoveEnv(key string) {
|
||||||
|
a.Env = append(a.Env, &KeyValue{
|
||||||
|
Key: MarkForRemoval(key),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddHooks records the addition of the given hooks to a container.
|
||||||
|
func (a *ContainerAdjustment) AddHooks(h *Hooks) {
|
||||||
|
a.initHooks()
|
||||||
|
if h.Prestart != nil {
|
||||||
|
a.Hooks.Prestart = append(a.Hooks.Prestart, h.Prestart...)
|
||||||
|
}
|
||||||
|
if h.CreateRuntime != nil {
|
||||||
|
a.Hooks.CreateRuntime = append(a.Hooks.CreateRuntime, h.CreateRuntime...)
|
||||||
|
}
|
||||||
|
if h.CreateContainer != nil {
|
||||||
|
a.Hooks.CreateContainer = append(a.Hooks.CreateContainer, h.CreateContainer...)
|
||||||
|
}
|
||||||
|
if h.StartContainer != nil {
|
||||||
|
a.Hooks.StartContainer = append(a.Hooks.StartContainer, h.StartContainer...)
|
||||||
|
}
|
||||||
|
if h.Poststart != nil {
|
||||||
|
a.Hooks.Poststart = append(a.Hooks.Poststart, h.Poststart...)
|
||||||
|
}
|
||||||
|
if h.Poststop != nil {
|
||||||
|
a.Hooks.Poststop = append(a.Hooks.Poststop, h.Poststop...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddDevice records the addition of the given device to a container.
|
||||||
|
func (a *ContainerAdjustment) AddDevice(d *LinuxDevice) {
|
||||||
|
a.initLinux()
|
||||||
|
a.Linux.Devices = append(a.Linux.Devices, d) // TODO: should we dup d here ?
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveDevice records the removal of a device from a container.
|
||||||
|
// Normally it is an error for a plugin to try and alter an device
|
||||||
|
// touched by another container. However, this is not an error if
|
||||||
|
// the plugin removes that device prior to touching it.
|
||||||
|
func (a *ContainerAdjustment) RemoveDevice(path string) {
|
||||||
|
a.initLinux()
|
||||||
|
a.Linux.Devices = append(a.Linux.Devices, &LinuxDevice{
|
||||||
|
Path: MarkForRemoval(path),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryLimit records setting the memory limit for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemoryLimit(value int64) {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.Limit = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryReservation records setting the memory reservation for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemoryReservation(value int64) {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.Reservation = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemorySwap records records setting the memory swap limit for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemorySwap(value int64) {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.Swap = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryKernel records setting the memory kernel limit for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemoryKernel(value int64) {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.Kernel = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryKernelTCP records setting the memory kernel TCP limit for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemoryKernelTCP(value int64) {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.KernelTcp = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemorySwappiness records setting the memory swappiness for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemorySwappiness(value uint64) {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.Swappiness = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryDisableOomKiller records disabling the OOM killer for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemoryDisableOomKiller() {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.DisableOomKiller = Bool(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryUseHierarchy records enabling hierarchical memory accounting for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemoryUseHierarchy() {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.UseHierarchy = Bool(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUShares records setting the scheduler's CPU shares for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPUShares(value uint64) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.Shares = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUQuota records setting the scheduler's CPU quota for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPUQuota(value int64) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.Quota = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUPeriod records setting the scheduler's CPU period for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPUPeriod(value int64) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.Period = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPURealtimeRuntime records setting the scheduler's realtime runtime for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPURealtimeRuntime(value int64) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.RealtimeRuntime = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPURealtimePeriod records setting the scheduler's realtime period for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPURealtimePeriod(value uint64) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.RealtimePeriod = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUSetCPUs records setting the cpuset CPUs for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPUSetCPUs(value string) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.Cpus = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUSetMems records setting the cpuset memory for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPUSetMems(value string) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.Mems = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLinuxHugepageLimit records adding a hugepage limit for a container.
|
||||||
|
func (a *ContainerAdjustment) AddLinuxHugepageLimit(pageSize string, value uint64) {
|
||||||
|
a.initLinuxResources()
|
||||||
|
a.Linux.Resources.HugepageLimits = append(a.Linux.Resources.HugepageLimits,
|
||||||
|
&HugepageLimit{
|
||||||
|
PageSize: pageSize,
|
||||||
|
Limit: value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxBlockIOClass records setting the Block I/O class for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxBlockIOClass(value string) {
|
||||||
|
a.initLinuxResources()
|
||||||
|
a.Linux.Resources.BlockioClass = String(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxRDTClass records setting the RDT class for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxRDTClass(value string) {
|
||||||
|
a.initLinuxResources()
|
||||||
|
a.Linux.Resources.RdtClass = String(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLinuxUnified sets a cgroupv2 unified resource.
|
||||||
|
func (a *ContainerAdjustment) AddLinuxUnified(key, value string) {
|
||||||
|
a.initLinuxResourcesUnified()
|
||||||
|
a.Linux.Resources.Unified[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCgroupsPath records setting the cgroups path for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCgroupsPath(value string) {
|
||||||
|
a.initLinux()
|
||||||
|
a.Linux.CgroupsPath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initializing a container adjustment and container update.
|
||||||
|
//
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initAnnotations() {
|
||||||
|
if a.Annotations == nil {
|
||||||
|
a.Annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initHooks() {
|
||||||
|
if a.Hooks == nil {
|
||||||
|
a.Hooks = &Hooks{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initLinux() {
|
||||||
|
if a.Linux == nil {
|
||||||
|
a.Linux = &LinuxContainerAdjustment{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initLinuxResources() {
|
||||||
|
a.initLinux()
|
||||||
|
if a.Linux.Resources == nil {
|
||||||
|
a.Linux.Resources = &LinuxResources{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initLinuxResourcesMemory() {
|
||||||
|
a.initLinuxResources()
|
||||||
|
if a.Linux.Resources.Memory == nil {
|
||||||
|
a.Linux.Resources.Memory = &LinuxMemory{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initLinuxResourcesCPU() {
|
||||||
|
a.initLinuxResources()
|
||||||
|
if a.Linux.Resources.Cpu == nil {
|
||||||
|
a.Linux.Resources.Cpu = &LinuxCPU{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initLinuxResourcesUnified() {
|
||||||
|
a.initLinuxResources()
|
||||||
|
if a.Linux.Resources.Unified == nil {
|
||||||
|
a.Linux.Resources.Unified = make(map[string]string)
|
||||||
|
}
|
||||||
|
}
|
4295
vendor/github.com/containerd/nri/pkg/api/api.pb.go
generated
vendored
Normal file
4295
vendor/github.com/containerd/nri/pkg/api/api.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
441
vendor/github.com/containerd/nri/pkg/api/api.proto
generated
vendored
Normal file
441
vendor/github.com/containerd/nri/pkg/api/api.proto
generated
vendored
Normal file
@ -0,0 +1,441 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package nri.pkg.api.v1alpha1;
|
||||||
|
|
||||||
|
option go_package = "github.com/containerd/nri/pkg/api;api";
|
||||||
|
|
||||||
|
// Runtime service is the public API runtimes expose for NRI plugins.
|
||||||
|
// On this interface RPC requests are initiated by the plugin. This
|
||||||
|
// only covers plugin registration and unsolicited container updates.
|
||||||
|
// The rest of the API is defined by the Plugin service.
|
||||||
|
service Runtime {
|
||||||
|
// RegisterPlugin registers the plugin with the runtime.
|
||||||
|
rpc RegisterPlugin(RegisterPluginRequest) returns (Empty);
|
||||||
|
// UpdateContainers requests unsolicited updates to a set of containers.
|
||||||
|
rpc UpdateContainers(UpdateContainersRequest) returns (UpdateContainersResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
message RegisterPluginRequest {
|
||||||
|
// Name of the plugin to register.
|
||||||
|
string plugin_name = 1;
|
||||||
|
// Plugin invocation index. Plugins are called in ascending index order.
|
||||||
|
string plugin_idx = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateContainersRequest {
|
||||||
|
// List of containers to update.
|
||||||
|
repeated ContainerUpdate update = 1;
|
||||||
|
// List of containers to evict.
|
||||||
|
repeated ContainerEviction evict = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateContainersResponse {
|
||||||
|
// Containers that the runtime failed to udpate.
|
||||||
|
repeated ContainerUpdate failed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Plugin is the API NRI uses to interact with plugins. It is used to
|
||||||
|
// - configure a plugin and subscribe it for lifecycle events
|
||||||
|
// - synchronize the state of a plugin with that of the runtime
|
||||||
|
// - hook a plugin into the lifecycle events of its interest
|
||||||
|
//
|
||||||
|
// During configuration the plugin tells the runtime which lifecycle events
|
||||||
|
// it wishes to get hooked into. Once configured, the plugin is synchronized
|
||||||
|
// with the runtime by receiving the list of pods and containers known to
|
||||||
|
// the runtime. The plugin can request changes to any of the containers in
|
||||||
|
// response. After initial synchronization the plugin starts receiving the
|
||||||
|
// events it subscribed for as they occur in the runtime. For container
|
||||||
|
// creation, update, and stop events, the plugin can request changes, both
|
||||||
|
// to the container that triggered the event or any other existing container
|
||||||
|
// in the runtime.
|
||||||
|
//
|
||||||
|
// For a subset of the container lifecycle events, NRI defines an additional
|
||||||
|
// Post-variant of the event. These variants are defined for CreateContainer,
|
||||||
|
// StartContainer, and UpdateContainer. For creation and update, these events
|
||||||
|
// can be used by plugins to discover the full extent of changes applied to
|
||||||
|
// the container, including any changes made by other active plugins.
|
||||||
|
//
|
||||||
|
service Plugin {
|
||||||
|
// Configure the plugin and get its event subscription.
|
||||||
|
rpc Configure(ConfigureRequest) returns (ConfigureResponse);
|
||||||
|
|
||||||
|
// Synchronize the plugin with the state of the runtime.
|
||||||
|
rpc Synchronize(SynchronizeRequest) returns (SynchronizeResponse);
|
||||||
|
|
||||||
|
// Shutdown a plugin (let it know the runtime is going down).
|
||||||
|
rpc Shutdown(Empty) returns (Empty);
|
||||||
|
|
||||||
|
// CreateContainer relays the corresponding request to the plugin. In
|
||||||
|
// response, the plugin can adjust the container being created, and
|
||||||
|
// update other containers in the runtime. Container adjustment can
|
||||||
|
// alter labels, annotations, mounts, devices, environment variables,
|
||||||
|
// OCI hooks, and assigned container resources. Updates can alter
|
||||||
|
// assigned container resources.
|
||||||
|
rpc CreateContainer(CreateContainerRequest) returns (CreateContainerResponse);
|
||||||
|
|
||||||
|
// UpdateContainer relays the corresponding request to the plugin.
|
||||||
|
// The plugin can alter how the container is updated and request updates
|
||||||
|
// to additional containers in the runtime.
|
||||||
|
rpc UpdateContainer(UpdateContainerRequest) returns (UpdateContainerResponse);
|
||||||
|
|
||||||
|
// StopContainer relays the corresponding request to the plugin. The plugin
|
||||||
|
// can update any of the remaining containers in the runtime in response.
|
||||||
|
rpc StopContainer(StopContainerRequest) returns (StopContainerResponse);
|
||||||
|
|
||||||
|
// StateChange relays any remaining pod or container lifecycle/state change
|
||||||
|
// events the plugin has subscribed for. These can be used to trigger any
|
||||||
|
// plugin-specific processing which needs to occur in connection with any of
|
||||||
|
// these events.
|
||||||
|
rpc StateChange(StateChangeEvent) returns (Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
message ConfigureRequest {
|
||||||
|
// Any plugin-specific data, if present among the NRI configuration.
|
||||||
|
string config = 1;
|
||||||
|
// Name of the runtime NRI is running in.
|
||||||
|
string runtime_name = 2;
|
||||||
|
// Version of the runtime NRI is running in.
|
||||||
|
string runtime_version = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ConfigureResponse {
|
||||||
|
// Events to subscribe the plugin for. Each bit set corresponds to an
|
||||||
|
// enumerated Event.
|
||||||
|
int32 events = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SynchronizeRequest {
|
||||||
|
// Pods known to the runtime.
|
||||||
|
repeated PodSandbox pods = 1;
|
||||||
|
// Containers known to the runtime.
|
||||||
|
repeated Container containers = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SynchronizeResponse {
|
||||||
|
// Updates to containers requested by the plugin.
|
||||||
|
repeated ContainerUpdate update = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateContainerRequest {
|
||||||
|
// Pod of container being created.
|
||||||
|
PodSandbox pod = 1;
|
||||||
|
// Container being created.
|
||||||
|
Container container = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateContainerResponse {
|
||||||
|
// Requested adjustments to container being created.
|
||||||
|
ContainerAdjustment adjust = 1;
|
||||||
|
// Requested updates to other existing containers.
|
||||||
|
repeated ContainerUpdate update = 2;
|
||||||
|
// Requested eviction of existing containers.
|
||||||
|
repeated ContainerEviction evict = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateContainerRequest {
|
||||||
|
// Pod of container being updated.
|
||||||
|
PodSandbox pod = 1;
|
||||||
|
// Container being updated.
|
||||||
|
Container container = 2;
|
||||||
|
// Resources to update.
|
||||||
|
LinuxResources linux_resources = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateContainerResponse {
|
||||||
|
// Requested updates to containers.
|
||||||
|
repeated ContainerUpdate update = 1;
|
||||||
|
// Requested eviction of containers.
|
||||||
|
repeated ContainerEviction evict = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StopContainerRequest {
|
||||||
|
// Pod of container being stopped.
|
||||||
|
PodSandbox pod = 1;
|
||||||
|
// Container being stopped.
|
||||||
|
Container container = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StopContainerResponse {
|
||||||
|
// Requested updates to containers.
|
||||||
|
repeated ContainerUpdate update = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StateChangeEvent {
|
||||||
|
// Event type of notification.
|
||||||
|
Event event = 1;
|
||||||
|
// Pod this notification is sent for. If this event is related to a container,
|
||||||
|
// pod is set to the pod of the container.
|
||||||
|
PodSandbox pod = 2;
|
||||||
|
// Container this notification is sent for. If the event is related to a pod,
|
||||||
|
// container is nil.
|
||||||
|
Container container = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty response for those *Requests that are semantically events.
|
||||||
|
message Empty {}
|
||||||
|
|
||||||
|
// Events that plugins can subscribe to in ConfigureResponse.
|
||||||
|
enum Event {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
RUN_POD_SANDBOX = 1;
|
||||||
|
STOP_POD_SANDBOX = 2;
|
||||||
|
REMOVE_POD_SANDBOX = 3;
|
||||||
|
CREATE_CONTAINER = 4;
|
||||||
|
POST_CREATE_CONTAINER = 5;
|
||||||
|
START_CONTAINER = 6;
|
||||||
|
POST_START_CONTAINER = 7;
|
||||||
|
UPDATE_CONTAINER = 8;
|
||||||
|
POST_UPDATE_CONTAINER = 9;
|
||||||
|
STOP_CONTAINER = 10;
|
||||||
|
REMOVE_CONTAINER = 11;
|
||||||
|
LAST = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pod metadata that is considered relevant for a plugin.
|
||||||
|
message PodSandbox {
|
||||||
|
string id = 1;
|
||||||
|
string name = 2;
|
||||||
|
string uid = 3;
|
||||||
|
string namespace = 4;
|
||||||
|
map<string, string> labels = 5;
|
||||||
|
map<string, string> annotations = 6;
|
||||||
|
string runtime_handler = 7;
|
||||||
|
LinuxPodSandbox linux = 8;
|
||||||
|
uint32 pid = 9; // for NRI v1 emulation
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodSandbox linux-specific metadata
|
||||||
|
message LinuxPodSandbox {
|
||||||
|
LinuxResources pod_overhead = 1;
|
||||||
|
LinuxResources pod_resources = 2;
|
||||||
|
string cgroup_parent = 3;
|
||||||
|
string cgroups_path = 4; // for NRI v1 emulation
|
||||||
|
repeated LinuxNamespace namespaces = 5; // for NRI v1 emulation
|
||||||
|
LinuxResources resources = 6; // for NRI v1 emulation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container metadata that is considered relevant for a plugin.
|
||||||
|
message Container {
|
||||||
|
string id = 1;
|
||||||
|
string pod_sandbox_id = 2;
|
||||||
|
string name = 3;
|
||||||
|
ContainerState state = 4;
|
||||||
|
map<string, string> labels = 5;
|
||||||
|
map<string, string> annotations = 6;
|
||||||
|
repeated string args = 7;
|
||||||
|
repeated string env = 8;
|
||||||
|
repeated Mount mounts = 9;
|
||||||
|
Hooks hooks = 10;
|
||||||
|
LinuxContainer linux = 11;
|
||||||
|
uint32 pid = 12; // for NRI v1 emulation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Possible container states.
|
||||||
|
enum ContainerState {
|
||||||
|
CONTAINER_UNKNOWN = 0;
|
||||||
|
CONTAINER_CREATED = 1;
|
||||||
|
CONTAINER_PAUSED = 2; // is this useful/necessary ?
|
||||||
|
CONTAINER_RUNNING = 3;
|
||||||
|
CONTAINER_STOPPED = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A container mount.
|
||||||
|
message Mount {
|
||||||
|
string destination = 1;
|
||||||
|
string type = 2;
|
||||||
|
string source = 3;
|
||||||
|
repeated string options = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container OCI hooks.
|
||||||
|
message Hooks {
|
||||||
|
repeated Hook prestart = 1;
|
||||||
|
repeated Hook create_runtime = 2;
|
||||||
|
repeated Hook create_container = 3;
|
||||||
|
repeated Hook start_container = 4;
|
||||||
|
repeated Hook poststart = 5;
|
||||||
|
repeated Hook poststop = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// One OCI hook.
|
||||||
|
message Hook {
|
||||||
|
string path = 1;
|
||||||
|
repeated string args = 2;
|
||||||
|
repeated string env = 3;
|
||||||
|
OptionalInt timeout = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container (linux) metadata.
|
||||||
|
message LinuxContainer {
|
||||||
|
repeated LinuxNamespace namespaces = 1;
|
||||||
|
repeated LinuxDevice devices = 2;
|
||||||
|
LinuxResources resources = 3;
|
||||||
|
OptionalInt oom_score_adj = 4;
|
||||||
|
string cgroups_path = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A linux namespace.
|
||||||
|
message LinuxNamespace {
|
||||||
|
string type = 1;
|
||||||
|
string path = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A container (linux) device.
|
||||||
|
message LinuxDevice {
|
||||||
|
string path = 1;
|
||||||
|
string type = 2;
|
||||||
|
int64 major = 3;
|
||||||
|
int64 minor = 4;
|
||||||
|
OptionalFileMode file_mode = 5;
|
||||||
|
OptionalUInt32 uid = 6;
|
||||||
|
OptionalUInt32 gid = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A linux device cgroup controller rule.
|
||||||
|
message LinuxDeviceCgroup {
|
||||||
|
bool allow = 1;
|
||||||
|
string type = 2;
|
||||||
|
OptionalInt64 major = 3;
|
||||||
|
OptionalInt64 minor = 4;
|
||||||
|
string access = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container (linux) resources.
|
||||||
|
message LinuxResources {
|
||||||
|
LinuxMemory memory = 1;
|
||||||
|
LinuxCPU cpu = 2;
|
||||||
|
repeated HugepageLimit hugepage_limits = 3;
|
||||||
|
OptionalString blockio_class = 4;
|
||||||
|
OptionalString rdt_class = 5;
|
||||||
|
map<string, string> unified = 6;
|
||||||
|
repeated LinuxDeviceCgroup devices = 7; // for NRI v1 emulation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory-related parts of (linux) resources.
|
||||||
|
message LinuxMemory {
|
||||||
|
OptionalInt64 limit = 1;
|
||||||
|
OptionalInt64 reservation = 2;
|
||||||
|
OptionalInt64 swap = 3;
|
||||||
|
OptionalInt64 kernel = 4;
|
||||||
|
OptionalInt64 kernel_tcp = 5;
|
||||||
|
OptionalUInt64 swappiness = 6;
|
||||||
|
OptionalBool disable_oom_killer = 7;
|
||||||
|
OptionalBool use_hierarchy = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CPU-related parts of (linux) resources.
|
||||||
|
message LinuxCPU {
|
||||||
|
OptionalUInt64 shares = 1;
|
||||||
|
OptionalInt64 quota = 2;
|
||||||
|
OptionalUInt64 period = 3;
|
||||||
|
OptionalInt64 realtime_runtime = 4;
|
||||||
|
OptionalUInt64 realtime_period = 5;
|
||||||
|
string cpus = 6;
|
||||||
|
string mems = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container huge page limit.
|
||||||
|
message HugepageLimit {
|
||||||
|
string page_size = 1;
|
||||||
|
uint64 limit = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requested adjustments to a container being created.
|
||||||
|
message ContainerAdjustment {
|
||||||
|
map<string, string> annotations = 2;
|
||||||
|
repeated Mount mounts = 3;
|
||||||
|
repeated KeyValue env = 4;
|
||||||
|
Hooks hooks = 5;
|
||||||
|
LinuxContainerAdjustment linux = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjustments to (linux) resources.
|
||||||
|
message LinuxContainerAdjustment {
|
||||||
|
repeated LinuxDevice devices = 1;
|
||||||
|
LinuxResources resources = 2;
|
||||||
|
string cgroups_path = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requested update to an already created container.
|
||||||
|
message ContainerUpdate {
|
||||||
|
string container_id = 1;
|
||||||
|
LinuxContainerUpdate linux = 2;
|
||||||
|
bool ignore_failure = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates to (linux) resources.
|
||||||
|
message LinuxContainerUpdate {
|
||||||
|
LinuxResources resources = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request to evict (IOW unsolicitedly stop) a container.
|
||||||
|
message ContainerEviction {
|
||||||
|
// Container to evict.
|
||||||
|
string container_id = 1;
|
||||||
|
// Human-readable reason for eviction.
|
||||||
|
string reason = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyValue represents an environment variable.
|
||||||
|
message KeyValue {
|
||||||
|
string key = 1;
|
||||||
|
string value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional string value.
|
||||||
|
message OptionalString {
|
||||||
|
string value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional signed integer value.
|
||||||
|
message OptionalInt {
|
||||||
|
int64 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional 32-bit signed integer value.
|
||||||
|
message OptionalInt32 {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional 32-bit unsigned integer value.
|
||||||
|
message OptionalUInt32 {
|
||||||
|
uint32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional 64-bit signed integer value.
|
||||||
|
message OptionalInt64 {
|
||||||
|
int64 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional 64-bit unsigned integer value.
|
||||||
|
message OptionalUInt64 {
|
||||||
|
uint64 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional boolean value.
|
||||||
|
message OptionalBool {
|
||||||
|
bool value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional value of file permissions.
|
||||||
|
message OptionalFileMode {
|
||||||
|
uint32 value = 1;
|
||||||
|
}
|
179
vendor/github.com/containerd/nri/pkg/api/api_ttrpc.pb.go
generated
vendored
Normal file
179
vendor/github.com/containerd/nri/pkg/api/api_ttrpc.pb.go
generated
vendored
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
// Code generated by protoc-gen-go-ttrpc. DO NOT EDIT.
|
||||||
|
// source: pkg/api/api.proto
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
ttrpc "github.com/containerd/ttrpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RuntimeService interface {
|
||||||
|
RegisterPlugin(ctx context.Context, req *RegisterPluginRequest) (*Empty, error)
|
||||||
|
UpdateContainers(ctx context.Context, req *UpdateContainersRequest) (*UpdateContainersResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterRuntimeService(srv *ttrpc.Server, svc RuntimeService) {
|
||||||
|
srv.Register("nri.pkg.api.v1alpha1.Runtime", map[string]ttrpc.Method{
|
||||||
|
"RegisterPlugin": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req RegisterPluginRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.RegisterPlugin(ctx, &req)
|
||||||
|
},
|
||||||
|
"UpdateContainers": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req UpdateContainersRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.UpdateContainers(ctx, &req)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type runtimeClient struct {
|
||||||
|
client *ttrpc.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRuntimeClient(client *ttrpc.Client) RuntimeService {
|
||||||
|
return &runtimeClient{
|
||||||
|
client: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (c *runtimeClient) RegisterPlugin(ctx context.Context, req *RegisterPluginRequest) (*Empty, error) {
|
||||||
|
var resp Empty
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Runtime", "RegisterPlugin", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *runtimeClient) UpdateContainers(ctx context.Context, req *UpdateContainersRequest) (*UpdateContainersResponse, error) {
|
||||||
|
var resp UpdateContainersResponse
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Runtime", "UpdateContainers", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type PluginService interface {
|
||||||
|
Configure(ctx context.Context, req *ConfigureRequest) (*ConfigureResponse, error)
|
||||||
|
Synchronize(ctx context.Context, req *SynchronizeRequest) (*SynchronizeResponse, error)
|
||||||
|
Shutdown(ctx context.Context, req *Empty) (*Empty, error)
|
||||||
|
CreateContainer(ctx context.Context, req *CreateContainerRequest) (*CreateContainerResponse, error)
|
||||||
|
UpdateContainer(ctx context.Context, req *UpdateContainerRequest) (*UpdateContainerResponse, error)
|
||||||
|
StopContainer(ctx context.Context, req *StopContainerRequest) (*StopContainerResponse, error)
|
||||||
|
StateChange(ctx context.Context, req *StateChangeEvent) (*Empty, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterPluginService(srv *ttrpc.Server, svc PluginService) {
|
||||||
|
srv.Register("nri.pkg.api.v1alpha1.Plugin", map[string]ttrpc.Method{
|
||||||
|
"Configure": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req ConfigureRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.Configure(ctx, &req)
|
||||||
|
},
|
||||||
|
"Synchronize": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req SynchronizeRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.Synchronize(ctx, &req)
|
||||||
|
},
|
||||||
|
"Shutdown": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req Empty
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.Shutdown(ctx, &req)
|
||||||
|
},
|
||||||
|
"CreateContainer": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req CreateContainerRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.CreateContainer(ctx, &req)
|
||||||
|
},
|
||||||
|
"UpdateContainer": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req UpdateContainerRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.UpdateContainer(ctx, &req)
|
||||||
|
},
|
||||||
|
"StopContainer": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req StopContainerRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.StopContainer(ctx, &req)
|
||||||
|
},
|
||||||
|
"StateChange": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req StateChangeEvent
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.StateChange(ctx, &req)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type pluginClient struct {
|
||||||
|
client *ttrpc.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPluginClient(client *ttrpc.Client) PluginService {
|
||||||
|
return &pluginClient{
|
||||||
|
client: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (c *pluginClient) Configure(ctx context.Context, req *ConfigureRequest) (*ConfigureResponse, error) {
|
||||||
|
var resp ConfigureResponse
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "Configure", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *pluginClient) Synchronize(ctx context.Context, req *SynchronizeRequest) (*SynchronizeResponse, error) {
|
||||||
|
var resp SynchronizeResponse
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "Synchronize", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *pluginClient) Shutdown(ctx context.Context, req *Empty) (*Empty, error) {
|
||||||
|
var resp Empty
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "Shutdown", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *pluginClient) CreateContainer(ctx context.Context, req *CreateContainerRequest) (*CreateContainerResponse, error) {
|
||||||
|
var resp CreateContainerResponse
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "CreateContainer", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *pluginClient) UpdateContainer(ctx context.Context, req *UpdateContainerRequest) (*UpdateContainerResponse, error) {
|
||||||
|
var resp UpdateContainerResponse
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "UpdateContainer", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *pluginClient) StopContainer(ctx context.Context, req *StopContainerRequest) (*StopContainerResponse, error) {
|
||||||
|
var resp StopContainerResponse
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "StopContainer", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *pluginClient) StateChange(ctx context.Context, req *StateChangeEvent) (*Empty, error) {
|
||||||
|
var resp Empty
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "StateChange", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
89
vendor/github.com/containerd/nri/pkg/api/device.go
generated
vendored
Normal file
89
vendor/github.com/containerd/nri/pkg/api/device.go
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
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 api
|
||||||
|
|
||||||
|
import (
|
||||||
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FromOCILinuxDevices returns a device slice from an OCI runtime Spec.
|
||||||
|
func FromOCILinuxDevices(o []rspec.LinuxDevice) []*LinuxDevice {
|
||||||
|
var devices []*LinuxDevice
|
||||||
|
for _, d := range o {
|
||||||
|
devices = append(devices, &LinuxDevice{
|
||||||
|
Path: d.Path,
|
||||||
|
Type: d.Type,
|
||||||
|
Major: d.Major,
|
||||||
|
Minor: d.Minor,
|
||||||
|
FileMode: FileMode(d.FileMode),
|
||||||
|
Uid: UInt32(d.UID),
|
||||||
|
Gid: UInt32(d.GID),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return devices
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToOCI returns the linux devices for an OCI runtime Spec.
|
||||||
|
func (d *LinuxDevice) ToOCI() rspec.LinuxDevice {
|
||||||
|
if d == nil {
|
||||||
|
return rspec.LinuxDevice{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rspec.LinuxDevice{
|
||||||
|
Path: d.Path,
|
||||||
|
Type: d.Type,
|
||||||
|
Major: d.Major,
|
||||||
|
Minor: d.Minor,
|
||||||
|
FileMode: d.FileMode.Get(),
|
||||||
|
UID: d.Uid.Get(),
|
||||||
|
GID: d.Gid.Get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccessString returns an OCI access string for the device.
|
||||||
|
func (d *LinuxDevice) AccessString() string {
|
||||||
|
r, w, m := "r", "w", ""
|
||||||
|
|
||||||
|
if mode := d.FileMode.Get(); mode != nil {
|
||||||
|
perm := mode.Perm()
|
||||||
|
if (perm & 0444) != 0 {
|
||||||
|
r = "r"
|
||||||
|
}
|
||||||
|
if (perm & 0222) != 0 {
|
||||||
|
w = "w"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if d.Type == "b" {
|
||||||
|
m = "m"
|
||||||
|
}
|
||||||
|
|
||||||
|
return r + w + m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cmp returns true if the devices are equal.
|
||||||
|
func (d *LinuxDevice) Cmp(v *LinuxDevice) bool {
|
||||||
|
if v == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return d.Major != v.Major || d.Minor != v.Minor
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMarkedForRemoval checks if a LinuxDevice is marked for removal.
|
||||||
|
func (d *LinuxDevice) IsMarkedForRemoval() (string, bool) {
|
||||||
|
key, marked := IsMarkedForRemoval(d.Path)
|
||||||
|
return key, marked
|
||||||
|
}
|
17
vendor/github.com/containerd/nri/pkg/api/doc.go
generated
vendored
Normal file
17
vendor/github.com/containerd/nri/pkg/api/doc.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
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 api
|
60
vendor/github.com/containerd/nri/pkg/api/env.go
generated
vendored
Normal file
60
vendor/github.com/containerd/nri/pkg/api/env.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
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 api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ToOCI returns an OCI Env entry for the KeyValue.
|
||||||
|
func (e *KeyValue) ToOCI() string {
|
||||||
|
return e.Key + "=" + e.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromOCIEnv returns KeyValues from an OCI runtime Spec environment.
|
||||||
|
func FromOCIEnv(in []string) []*KeyValue {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := []*KeyValue{}
|
||||||
|
for _, keyval := range in {
|
||||||
|
var key, val string
|
||||||
|
split := strings.SplitN(keyval, "=", 2)
|
||||||
|
switch len(split) {
|
||||||
|
case 0:
|
||||||
|
continue
|
||||||
|
case 1:
|
||||||
|
key = split[0]
|
||||||
|
case 2:
|
||||||
|
key = split[0]
|
||||||
|
val = split[1]
|
||||||
|
default:
|
||||||
|
val = strings.Join(split[1:], "=")
|
||||||
|
}
|
||||||
|
out = append(out, &KeyValue{
|
||||||
|
Key: key,
|
||||||
|
Value: val,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMarkedForRemoval checks if an environment variable is marked for removal.
|
||||||
|
func (e *KeyValue) IsMarkedForRemoval() (string, bool) {
|
||||||
|
key, marked := IsMarkedForRemoval(e.Key)
|
||||||
|
return key, marked
|
||||||
|
}
|
172
vendor/github.com/containerd/nri/pkg/api/event.go
generated
vendored
Normal file
172
vendor/github.com/containerd/nri/pkg/api/event.go
generated
vendored
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
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 api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ValidEvents is the event mask of all valid events.
|
||||||
|
ValidEvents = EventMask((1 << (Event_LAST - 1)) - 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
// nolint
|
||||||
|
type (
|
||||||
|
// Define *Request/*Response type aliases for *Event/Empty pairs.
|
||||||
|
|
||||||
|
StateChangeResponse = Empty
|
||||||
|
RunPodSandboxRequest = StateChangeEvent
|
||||||
|
RunPodSandboxResponse = Empty
|
||||||
|
StopPodSandboxRequest = StateChangeEvent
|
||||||
|
StopPodSandboxResponse = Empty
|
||||||
|
RemovePodSandboxRequest = StateChangeEvent
|
||||||
|
RemovePodSandboxResponse = Empty
|
||||||
|
StartContainerRequest = StateChangeEvent
|
||||||
|
StartContainerResponse = Empty
|
||||||
|
RemoveContainerRequest = StateChangeEvent
|
||||||
|
RemoveContainerResponse = Empty
|
||||||
|
PostCreateContainerRequest = StateChangeEvent
|
||||||
|
PostCreateContainerResponse = Empty
|
||||||
|
PostStartContainerRequest = StateChangeEvent
|
||||||
|
PostStartContainerResponse = Empty
|
||||||
|
PostUpdateContainerRequest = StateChangeEvent
|
||||||
|
PostUpdateContainerResponse = Empty
|
||||||
|
|
||||||
|
ShutdownRequest = Empty
|
||||||
|
ShutdownResponse = Empty
|
||||||
|
)
|
||||||
|
|
||||||
|
// EventMask corresponds to a set of enumerated Events.
|
||||||
|
type EventMask int32
|
||||||
|
|
||||||
|
// ParseEventMask parses a string representation into an EventMask.
|
||||||
|
func ParseEventMask(events ...string) (EventMask, error) {
|
||||||
|
var mask EventMask
|
||||||
|
|
||||||
|
bits := map[string]Event{
|
||||||
|
"runpodsandbox": Event_RUN_POD_SANDBOX,
|
||||||
|
"stoppodsandbox": Event_STOP_POD_SANDBOX,
|
||||||
|
"removepodsandbox": Event_REMOVE_POD_SANDBOX,
|
||||||
|
"createcontainer": Event_CREATE_CONTAINER,
|
||||||
|
"postcreatecontainer": Event_POST_CREATE_CONTAINER,
|
||||||
|
"startcontainer": Event_START_CONTAINER,
|
||||||
|
"poststartcontainer": Event_POST_START_CONTAINER,
|
||||||
|
"updatecontainer": Event_UPDATE_CONTAINER,
|
||||||
|
"postupdatecontainer": Event_POST_UPDATE_CONTAINER,
|
||||||
|
"stopcontainer": Event_STOP_CONTAINER,
|
||||||
|
"removecontainer": Event_REMOVE_CONTAINER,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, event := range events {
|
||||||
|
lcEvents := strings.ToLower(event)
|
||||||
|
for _, name := range strings.Split(lcEvents, ",") {
|
||||||
|
switch name {
|
||||||
|
case "all":
|
||||||
|
mask |= ValidEvents
|
||||||
|
continue
|
||||||
|
case "pod", "podsandbox":
|
||||||
|
for name, bit := range bits {
|
||||||
|
if strings.Contains(name, "Pod") {
|
||||||
|
mask.Set(bit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
case "container":
|
||||||
|
for name, bit := range bits {
|
||||||
|
if strings.Contains(name, "Container") {
|
||||||
|
mask.Set(bit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
bit, ok := bits[strings.TrimSpace(name)]
|
||||||
|
if !ok {
|
||||||
|
return 0, fmt.Errorf("unknown event %q", name)
|
||||||
|
}
|
||||||
|
mask.Set(bit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mask, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustParseEventMask parses the given events, panic()ing on errors.
|
||||||
|
func MustParseEventMask(events ...string) EventMask {
|
||||||
|
mask, err := ParseEventMask(events...)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to parse events %s", strings.Join(events, " ")))
|
||||||
|
}
|
||||||
|
return mask
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrettyString returns a human-readable string representation of an EventMask.
|
||||||
|
func (m *EventMask) PrettyString() string {
|
||||||
|
names := map[Event]string{
|
||||||
|
Event_RUN_POD_SANDBOX: "RunPodSandbox",
|
||||||
|
Event_STOP_POD_SANDBOX: "StopPodSandbox",
|
||||||
|
Event_REMOVE_POD_SANDBOX: "RemovePodSandbox",
|
||||||
|
Event_CREATE_CONTAINER: "CreateContainer",
|
||||||
|
Event_POST_CREATE_CONTAINER: "PostCreateContainer",
|
||||||
|
Event_START_CONTAINER: "StartContainer",
|
||||||
|
Event_POST_START_CONTAINER: "PostStartContainer",
|
||||||
|
Event_UPDATE_CONTAINER: "UpdateContainer",
|
||||||
|
Event_POST_UPDATE_CONTAINER: "PostUpdateContainer",
|
||||||
|
Event_STOP_CONTAINER: "StopContainer",
|
||||||
|
Event_REMOVE_CONTAINER: "RemoveContainer",
|
||||||
|
}
|
||||||
|
|
||||||
|
mask := *m
|
||||||
|
events, sep := "", ""
|
||||||
|
|
||||||
|
for bit := Event_UNKNOWN + 1; bit <= Event_LAST; bit++ {
|
||||||
|
if mask.IsSet(bit) {
|
||||||
|
events += sep + names[bit]
|
||||||
|
sep = ","
|
||||||
|
mask.Clear(bit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if mask != 0 {
|
||||||
|
events += sep + fmt.Sprintf("unknown(0x%x)", mask)
|
||||||
|
}
|
||||||
|
|
||||||
|
return events
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the given Events in the mask.
|
||||||
|
func (m *EventMask) Set(events ...Event) *EventMask {
|
||||||
|
for _, e := range events {
|
||||||
|
*m |= (1 << (e - 1))
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear clears the given Events in the mask.
|
||||||
|
func (m *EventMask) Clear(events ...Event) *EventMask {
|
||||||
|
for _, e := range events {
|
||||||
|
*m &^= (1 << (e - 1))
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet check if the given Event is set in the mask.
|
||||||
|
func (m *EventMask) IsSet(e Event) bool {
|
||||||
|
return *m&(1<<(e-1)) != 0
|
||||||
|
}
|
59
vendor/github.com/containerd/nri/pkg/api/helpers.go
generated
vendored
Normal file
59
vendor/github.com/containerd/nri/pkg/api/helpers.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
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 api
|
||||||
|
|
||||||
|
// DupStringSlice creates a copy of a string slice.
|
||||||
|
func DupStringSlice(in []string) []string {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := make([]string, len(in))
|
||||||
|
copy(out, in)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DupStringMap creates a copy of a map with string keys and values.
|
||||||
|
func DupStringMap(in map[string]string) map[string]string {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := map[string]string{}
|
||||||
|
for k, v := range in {
|
||||||
|
out[k] = v
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMarkedForRemoval checks if a key is marked for removal.
|
||||||
|
//
|
||||||
|
// The key can be an annotation name, a mount container path, a device path,
|
||||||
|
// or an environment variable name. These are all marked for removal in
|
||||||
|
// adjustments by preceding their corresponding key with a '-'.
|
||||||
|
func IsMarkedForRemoval(key string) (string, bool) {
|
||||||
|
if key == "" {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
if key[0] != '-' {
|
||||||
|
return key, false
|
||||||
|
}
|
||||||
|
return key[1:], true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkForRemoval returns a key marked for removal.
|
||||||
|
func MarkForRemoval(key string) string {
|
||||||
|
return "-" + key
|
||||||
|
}
|
103
vendor/github.com/containerd/nri/pkg/api/hooks.go
generated
vendored
Normal file
103
vendor/github.com/containerd/nri/pkg/api/hooks.go
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
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 api
|
||||||
|
|
||||||
|
import (
|
||||||
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Append appends the given hooks to the existing ones.
|
||||||
|
func (hooks *Hooks) Append(h *Hooks) *Hooks {
|
||||||
|
if h == nil {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
hooks.Prestart = append(hooks.Prestart, h.Prestart...)
|
||||||
|
hooks.CreateRuntime = append(hooks.CreateRuntime, h.CreateRuntime...)
|
||||||
|
hooks.CreateContainer = append(hooks.CreateContainer, h.CreateContainer...)
|
||||||
|
hooks.StartContainer = append(hooks.StartContainer, h.StartContainer...)
|
||||||
|
hooks.Poststart = append(hooks.Poststart, h.Poststart...)
|
||||||
|
hooks.Poststop = append(hooks.Poststop, h.Poststop...)
|
||||||
|
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hooks returns itself it any of its hooks is set. Otherwise it returns nil.
|
||||||
|
func (hooks *Hooks) Hooks() *Hooks {
|
||||||
|
if hooks == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(hooks.Prestart) > 0 {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
if len(hooks.CreateRuntime) > 0 {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
if len(hooks.CreateContainer) > 0 {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
if len(hooks.StartContainer) > 0 {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
if len(hooks.Poststart) > 0 {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
if len(hooks.Poststop) > 0 {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToOCI returns the hook for an OCI runtime Spec.
|
||||||
|
func (h *Hook) ToOCI() rspec.Hook {
|
||||||
|
return rspec.Hook{
|
||||||
|
Path: h.Path,
|
||||||
|
Args: DupStringSlice(h.Args),
|
||||||
|
Env: DupStringSlice(h.Env),
|
||||||
|
Timeout: h.Timeout.Get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromOCIHooks returns hooks from an OCI runtime Spec.
|
||||||
|
func FromOCIHooks(o *rspec.Hooks) *Hooks {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &Hooks{
|
||||||
|
Prestart: FromOCIHookSlice(o.Prestart),
|
||||||
|
CreateRuntime: FromOCIHookSlice(o.CreateRuntime),
|
||||||
|
CreateContainer: FromOCIHookSlice(o.CreateContainer),
|
||||||
|
StartContainer: FromOCIHookSlice(o.StartContainer),
|
||||||
|
Poststart: FromOCIHookSlice(o.Poststart),
|
||||||
|
Poststop: FromOCIHookSlice(o.Poststop),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromOCIHookSlice returns a hook slice from an OCI runtime Spec.
|
||||||
|
func FromOCIHookSlice(o []rspec.Hook) []*Hook {
|
||||||
|
var hooks []*Hook
|
||||||
|
for _, h := range o {
|
||||||
|
hooks = append(hooks, &Hook{
|
||||||
|
Path: h.Path,
|
||||||
|
Args: DupStringSlice(h.Args),
|
||||||
|
Env: DupStringSlice(h.Env),
|
||||||
|
Timeout: Int(h.Timeout),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return hooks
|
||||||
|
}
|
89
vendor/github.com/containerd/nri/pkg/api/mount.go
generated
vendored
Normal file
89
vendor/github.com/containerd/nri/pkg/api/mount.go
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
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 api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SELinuxRelabel is a Mount pseudo-option to request relabeling.
|
||||||
|
SELinuxRelabel = "relabel"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FromOCIMounts returns a Mount slice for an OCI runtime Spec.
|
||||||
|
func FromOCIMounts(o []rspec.Mount) []*Mount {
|
||||||
|
var mounts []*Mount
|
||||||
|
for _, m := range o {
|
||||||
|
mounts = append(mounts, &Mount{
|
||||||
|
Destination: m.Destination,
|
||||||
|
Type: m.Type,
|
||||||
|
Source: m.Source,
|
||||||
|
Options: DupStringSlice(m.Options),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return mounts
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToOCI returns a Mount for an OCI runtime Spec.
|
||||||
|
func (m *Mount) ToOCI(propagationQuery *string) rspec.Mount {
|
||||||
|
o := rspec.Mount{
|
||||||
|
Destination: m.Destination,
|
||||||
|
Type: m.Type,
|
||||||
|
Source: m.Source,
|
||||||
|
Options: []string{},
|
||||||
|
}
|
||||||
|
for _, opt := range m.Options {
|
||||||
|
o.Options = append(o.Options, opt)
|
||||||
|
if propagationQuery != nil && (opt == "rprivate" || opt == "rshared" || opt == "rslave") {
|
||||||
|
*propagationQuery = opt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cmp returns true if the mounts are equal.
|
||||||
|
func (m *Mount) Cmp(v *Mount) bool {
|
||||||
|
if v == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if m.Destination != v.Destination || m.Type != v.Type || m.Source != v.Source ||
|
||||||
|
len(m.Options) != len(v.Options) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
mOpts := make([]string, len(m.Options))
|
||||||
|
vOpts := make([]string, len(m.Options))
|
||||||
|
sort.Strings(mOpts)
|
||||||
|
sort.Strings(vOpts)
|
||||||
|
|
||||||
|
for i, o := range mOpts {
|
||||||
|
if vOpts[i] != o {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMarkedForRemoval checks if a Mount is marked for removal.
|
||||||
|
func (m *Mount) IsMarkedForRemoval() (string, bool) {
|
||||||
|
key, marked := IsMarkedForRemoval(m.Destination)
|
||||||
|
return key, marked
|
||||||
|
}
|
33
vendor/github.com/containerd/nri/pkg/api/namespace.go
generated
vendored
Normal file
33
vendor/github.com/containerd/nri/pkg/api/namespace.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
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 api
|
||||||
|
|
||||||
|
import (
|
||||||
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FromOCILinuxNamespaces returns a namespace slice from an OCI runtime Spec.
|
||||||
|
func FromOCILinuxNamespaces(o []rspec.LinuxNamespace) []*LinuxNamespace {
|
||||||
|
var namespaces []*LinuxNamespace
|
||||||
|
for _, ns := range o {
|
||||||
|
namespaces = append(namespaces, &LinuxNamespace{
|
||||||
|
Type: string(ns.Type),
|
||||||
|
Path: ns.Path,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return namespaces
|
||||||
|
}
|
341
vendor/github.com/containerd/nri/pkg/api/optional.go
generated
vendored
Normal file
341
vendor/github.com/containerd/nri/pkg/api/optional.go
generated
vendored
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
/*
|
||||||
|
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 api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
// XXX FIXME:
|
||||||
|
//
|
||||||
|
// The optional interface constructor should be updated/split up
|
||||||
|
// to avoid having to take an interface{} argument. Instead The
|
||||||
|
// optional types should have a
|
||||||
|
// - constructor taking the underlying native type
|
||||||
|
// - a Copy() function for copying them
|
||||||
|
// - a FromPointer constructor to create them from an optionally nil
|
||||||
|
// pointer to the underlying native type (to help constructing from
|
||||||
|
// structures that use a pointer to the native underlying type to
|
||||||
|
// denote optionality (OCI Spec mostly))
|
||||||
|
// Creating from any other type should use one of these with any explicit
|
||||||
|
// cast for the argument as necessary.
|
||||||
|
//
|
||||||
|
|
||||||
|
// String creates an Optional wrapper from its argument.
|
||||||
|
func String(v interface{}) *OptionalString {
|
||||||
|
var value string
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case string:
|
||||||
|
value = o
|
||||||
|
case *string:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case *OptionalString:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalString{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalString) Get() *string {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := o.Value
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int creates an Optional wrapper from its argument.
|
||||||
|
func Int(v interface{}) *OptionalInt {
|
||||||
|
var value int64
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case int:
|
||||||
|
value = int64(o)
|
||||||
|
case *int:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = int64(*o)
|
||||||
|
case *OptionalInt:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalInt{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalInt) Get() *int {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := int(o.Value)
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int32 creates an Optional wrapper from its argument.
|
||||||
|
func Int32(v interface{}) *OptionalInt32 {
|
||||||
|
var value int32
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case int32:
|
||||||
|
value = o
|
||||||
|
case *int32:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case *OptionalInt32:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalInt32{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalInt32) Get() *int32 {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := o.Value
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// UInt32 creates an Optional wrapper from its argument.
|
||||||
|
func UInt32(v interface{}) *OptionalUInt32 {
|
||||||
|
var value uint32
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case uint32:
|
||||||
|
value = o
|
||||||
|
case *uint32:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case *OptionalUInt32:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalUInt32{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalUInt32) Get() *uint32 {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := o.Value
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 creates an Optional wrapper from its argument.
|
||||||
|
func Int64(v interface{}) *OptionalInt64 {
|
||||||
|
var value int64
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case int:
|
||||||
|
value = int64(o)
|
||||||
|
case uint:
|
||||||
|
value = int64(o)
|
||||||
|
case uint64:
|
||||||
|
value = int64(o)
|
||||||
|
case int64:
|
||||||
|
value = o
|
||||||
|
case *int64:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case *uint64:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = int64(*o)
|
||||||
|
case *OptionalInt64:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalInt64{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalInt64) Get() *int64 {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := o.Value
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// UInt64 creates an Optional wrapper from its argument.
|
||||||
|
func UInt64(v interface{}) *OptionalUInt64 {
|
||||||
|
var value uint64
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case int:
|
||||||
|
value = uint64(o)
|
||||||
|
case uint:
|
||||||
|
value = uint64(o)
|
||||||
|
case int64:
|
||||||
|
value = uint64(o)
|
||||||
|
case uint64:
|
||||||
|
value = o
|
||||||
|
case *int64:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = uint64(*o)
|
||||||
|
case *uint64:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case *OptionalUInt64:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalUInt64{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalUInt64) Get() *uint64 {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := o.Value
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool creates an Optional wrapper from its argument.
|
||||||
|
func Bool(v interface{}) *OptionalBool {
|
||||||
|
var value bool
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case bool:
|
||||||
|
value = o
|
||||||
|
case *bool:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case *OptionalBool:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalBool{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalBool) Get() *bool {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := o.Value
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileMode creates an Optional wrapper from its argument.
|
||||||
|
func FileMode(v interface{}) *OptionalFileMode {
|
||||||
|
var value os.FileMode
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case *os.FileMode:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case os.FileMode:
|
||||||
|
value = o
|
||||||
|
case *OptionalFileMode:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = os.FileMode(o.Value)
|
||||||
|
case uint32:
|
||||||
|
value = os.FileMode(o)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalFileMode{
|
||||||
|
Value: uint32(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalFileMode) Get() *os.FileMode {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := os.FileMode(o.Value)
|
||||||
|
return &v
|
||||||
|
}
|
58
vendor/github.com/containerd/nri/pkg/api/plugin.go
generated
vendored
Normal file
58
vendor/github.com/containerd/nri/pkg/api/plugin.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
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 api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultSocketPath is the default socket path for external plugins.
|
||||||
|
DefaultSocketPath = "/var/run/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.
|
||||||
|
PluginNameEnvVar = "NRI_PLUGIN_NAME"
|
||||||
|
// PluginIdxEnvVar is used to inform NRI-launched plugins about their ID.
|
||||||
|
PluginIdxEnvVar = "NRI_PLUGIN_IDX"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParsePluginName parses the (file)name of a plugin into an index and a base.
|
||||||
|
func ParsePluginName(name string) (string, string, error) {
|
||||||
|
split := strings.SplitN(name, "-", 2)
|
||||||
|
if len(split) < 2 {
|
||||||
|
return "", "", fmt.Errorf("invalid plugin name %q, idx-pluginname expected", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := CheckPluginIndex(split[0]); err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return split[0], split[1], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckPluginIndex checks the validity of a plugin index.
|
||||||
|
func CheckPluginIndex(idx string) error {
|
||||||
|
if len(idx) != 2 {
|
||||||
|
return fmt.Errorf("invalid plugin index %q, must be 2 digits", idx)
|
||||||
|
}
|
||||||
|
if !('0' <= idx[0] && idx[0] <= '9') || !('0' <= idx[1] && idx[1] <= '9') {
|
||||||
|
return fmt.Errorf("invalid plugin index %q (not [0-9][0-9])", idx)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
230
vendor/github.com/containerd/nri/pkg/api/resources.go
generated
vendored
Normal file
230
vendor/github.com/containerd/nri/pkg/api/resources.go
generated
vendored
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
/*
|
||||||
|
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 api
|
||||||
|
|
||||||
|
import (
|
||||||
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
cri "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FromOCILinuxResources returns resources from an OCI runtime Spec.
|
||||||
|
func FromOCILinuxResources(o *rspec.LinuxResources, ann map[string]string) *LinuxResources {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
l := &LinuxResources{}
|
||||||
|
if m := o.Memory; m != nil {
|
||||||
|
l.Memory = &LinuxMemory{
|
||||||
|
Limit: Int64(m.Limit),
|
||||||
|
Reservation: Int64(m.Reservation),
|
||||||
|
Swap: Int64(m.Swap),
|
||||||
|
Kernel: Int64(m.Kernel),
|
||||||
|
KernelTcp: Int64(m.KernelTCP),
|
||||||
|
Swappiness: UInt64(m.Swappiness),
|
||||||
|
DisableOomKiller: Bool(m.DisableOOMKiller),
|
||||||
|
UseHierarchy: Bool(m.UseHierarchy),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c := o.CPU; c != nil {
|
||||||
|
l.Cpu = &LinuxCPU{
|
||||||
|
Shares: UInt64(c.Shares),
|
||||||
|
Quota: Int64(c.Quota),
|
||||||
|
Period: UInt64(c.Period),
|
||||||
|
RealtimeRuntime: Int64(c.RealtimeRuntime),
|
||||||
|
RealtimePeriod: UInt64(c.RealtimePeriod),
|
||||||
|
Cpus: c.Cpus,
|
||||||
|
Mems: c.Mems,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, h := range o.HugepageLimits {
|
||||||
|
l.HugepageLimits = append(l.HugepageLimits, &HugepageLimit{
|
||||||
|
PageSize: h.Pagesize,
|
||||||
|
Limit: h.Limit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for _, d := range o.Devices {
|
||||||
|
l.Devices = append(l.Devices, &LinuxDeviceCgroup{
|
||||||
|
Allow: d.Allow,
|
||||||
|
Type: d.Type,
|
||||||
|
Major: Int64(d.Major),
|
||||||
|
Minor: Int64(d.Minor),
|
||||||
|
Access: d.Access,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromCRILinuxResources(c *cri.LinuxContainerResources) *LinuxResources {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
shares, quota, period := uint64(c.CpuShares), c.CpuQuota, uint64(c.CpuPeriod)
|
||||||
|
r := &LinuxResources{
|
||||||
|
Cpu: &LinuxCPU{
|
||||||
|
Shares: UInt64(&shares),
|
||||||
|
Quota: Int64("a),
|
||||||
|
Period: UInt64(&period),
|
||||||
|
Cpus: c.CpusetCpus,
|
||||||
|
Mems: c.CpusetMems,
|
||||||
|
},
|
||||||
|
Memory: &LinuxMemory{
|
||||||
|
Limit: Int64(&c.MemoryLimitInBytes),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, l := range c.HugepageLimits {
|
||||||
|
r.HugepageLimits = append(r.HugepageLimits,
|
||||||
|
&HugepageLimit{
|
||||||
|
PageSize: l.PageSize,
|
||||||
|
Limit: l.Limit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToOCI returns resources for an OCI runtime Spec.
|
||||||
|
func (r *LinuxResources) ToOCI() *rspec.LinuxResources {
|
||||||
|
if r == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
o := &rspec.LinuxResources{}
|
||||||
|
if r.Memory != nil {
|
||||||
|
o.Memory = &rspec.LinuxMemory{
|
||||||
|
Limit: r.Memory.Limit.Get(),
|
||||||
|
Reservation: r.Memory.Reservation.Get(),
|
||||||
|
Swap: r.Memory.Swap.Get(),
|
||||||
|
Kernel: r.Memory.Kernel.Get(),
|
||||||
|
KernelTCP: r.Memory.KernelTcp.Get(),
|
||||||
|
Swappiness: r.Memory.Swappiness.Get(),
|
||||||
|
DisableOOMKiller: r.Memory.DisableOomKiller.Get(),
|
||||||
|
UseHierarchy: r.Memory.UseHierarchy.Get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if r.Cpu != nil {
|
||||||
|
o.CPU = &rspec.LinuxCPU{
|
||||||
|
Shares: r.Cpu.Shares.Get(),
|
||||||
|
Quota: r.Cpu.Quota.Get(),
|
||||||
|
Period: r.Cpu.Period.Get(),
|
||||||
|
RealtimeRuntime: r.Cpu.RealtimeRuntime.Get(),
|
||||||
|
RealtimePeriod: r.Cpu.RealtimePeriod.Get(),
|
||||||
|
Cpus: r.Cpu.Cpus,
|
||||||
|
Mems: r.Cpu.Mems,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, l := range r.HugepageLimits {
|
||||||
|
o.HugepageLimits = append(o.HugepageLimits, rspec.LinuxHugepageLimit{
|
||||||
|
Pagesize: l.PageSize,
|
||||||
|
Limit: l.Limit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(r.Unified) != 0 {
|
||||||
|
o.Unified = make(map[string]string)
|
||||||
|
for k, v := range r.Unified {
|
||||||
|
o.Unified[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, d := range r.Devices {
|
||||||
|
o.Devices = append(o.Devices, rspec.LinuxDeviceCgroup{
|
||||||
|
Allow: d.Allow,
|
||||||
|
Type: d.Type,
|
||||||
|
Major: d.Major.Get(),
|
||||||
|
Minor: d.Minor.Get(),
|
||||||
|
Access: d.Access,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToCRI returns resources for CRI.
|
||||||
|
func (r *LinuxResources) ToCRI(oomScoreAdj int64) *cri.LinuxContainerResources {
|
||||||
|
if r == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
o := &cri.LinuxContainerResources{}
|
||||||
|
if r.Memory != nil {
|
||||||
|
o.MemoryLimitInBytes = r.Memory.GetLimit().GetValue()
|
||||||
|
o.OomScoreAdj = oomScoreAdj
|
||||||
|
}
|
||||||
|
if r.Cpu != nil {
|
||||||
|
o.CpuShares = int64(r.Cpu.GetShares().GetValue())
|
||||||
|
o.CpuPeriod = int64(r.Cpu.GetPeriod().GetValue())
|
||||||
|
o.CpuQuota = r.Cpu.GetQuota().GetValue()
|
||||||
|
o.CpusetCpus = r.Cpu.Cpus
|
||||||
|
o.CpusetMems = r.Cpu.Mems
|
||||||
|
}
|
||||||
|
for _, l := range r.HugepageLimits {
|
||||||
|
o.HugepageLimits = append(o.HugepageLimits, &cri.HugepageLimit{
|
||||||
|
PageSize: l.PageSize,
|
||||||
|
Limit: l.Limit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(r.Unified) != 0 {
|
||||||
|
o.Unified = make(map[string]string)
|
||||||
|
for k, v := range r.Unified {
|
||||||
|
o.Unified[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy creates a copy of the resources.
|
||||||
|
func (r *LinuxResources) Copy() *LinuxResources {
|
||||||
|
if r == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
o := &LinuxResources{}
|
||||||
|
if r.Memory != nil {
|
||||||
|
o.Memory = &LinuxMemory{
|
||||||
|
Limit: Int64(r.Memory.GetLimit()),
|
||||||
|
Reservation: Int64(r.Memory.GetReservation()),
|
||||||
|
Swap: Int64(r.Memory.GetSwap()),
|
||||||
|
Kernel: Int64(r.Memory.GetKernel()),
|
||||||
|
KernelTcp: Int64(r.Memory.GetKernelTcp()),
|
||||||
|
Swappiness: UInt64(r.Memory.GetSwappiness()),
|
||||||
|
DisableOomKiller: Bool(r.Memory.GetDisableOomKiller()),
|
||||||
|
UseHierarchy: Bool(r.Memory.GetUseHierarchy()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if r.Cpu != nil {
|
||||||
|
o.Cpu = &LinuxCPU{
|
||||||
|
Shares: UInt64(r.Cpu.GetShares()),
|
||||||
|
Quota: Int64(r.Cpu.GetQuota()),
|
||||||
|
Period: UInt64(r.Cpu.GetPeriod()),
|
||||||
|
RealtimeRuntime: Int64(r.Cpu.GetRealtimeRuntime()),
|
||||||
|
RealtimePeriod: UInt64(r.Cpu.GetRealtimePeriod()),
|
||||||
|
Cpus: r.Cpu.GetCpus(),
|
||||||
|
Mems: r.Cpu.GetMems(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, l := range r.HugepageLimits {
|
||||||
|
o.HugepageLimits = append(o.HugepageLimits, &HugepageLimit{
|
||||||
|
PageSize: l.PageSize,
|
||||||
|
Limit: l.Limit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(r.Unified) != 0 {
|
||||||
|
o.Unified = make(map[string]string)
|
||||||
|
for k, v := range r.Unified {
|
||||||
|
o.Unified[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
o.BlockioClass = String(r.BlockioClass)
|
||||||
|
o.RdtClass = String(r.RdtClass)
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
186
vendor/github.com/containerd/nri/pkg/api/update.go
generated
vendored
Normal file
186
vendor/github.com/containerd/nri/pkg/api/update.go
generated
vendored
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
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 api
|
||||||
|
|
||||||
|
//nolint
|
||||||
|
// SetContainerId sets the id of the container to update.
|
||||||
|
func (u *ContainerUpdate) SetContainerId(id string) {
|
||||||
|
u.ContainerId = id
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryLimit records setting the memory limit for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemoryLimit(value int64) {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.Limit = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryReservation records setting the memory reservation for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemoryReservation(value int64) {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.Reservation = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemorySwap records records setting the memory swap limit for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemorySwap(value int64) {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.Swap = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryKernel records setting the memory kernel limit for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemoryKernel(value int64) {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.Kernel = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryKernelTCP records setting the memory kernel TCP limit for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemoryKernelTCP(value int64) {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.KernelTcp = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemorySwappiness records setting the memory swappiness for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemorySwappiness(value uint64) {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.Swappiness = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryDisableOomKiller records disabling the OOM killer for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemoryDisableOomKiller() {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.DisableOomKiller = Bool(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryUseHierarchy records enabling hierarchical memory accounting for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemoryUseHierarchy() {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.UseHierarchy = Bool(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUShares records setting the scheduler's CPU shares for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPUShares(value uint64) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.Shares = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUQuota records setting the scheduler's CPU quota for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPUQuota(value int64) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.Quota = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUPeriod records setting the scheduler's CPU period for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPUPeriod(value int64) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.Period = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPURealtimeRuntime records setting the scheduler's realtime runtime for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPURealtimeRuntime(value int64) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.RealtimeRuntime = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPURealtimePeriod records setting the scheduler's realtime period for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPURealtimePeriod(value uint64) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.RealtimePeriod = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUSetCPUs records setting the cpuset CPUs for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPUSetCPUs(value string) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.Cpus = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUSetMems records setting the cpuset memory for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPUSetMems(value string) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.Mems = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLinuxHugepageLimit records adding a hugepage limit for a container.
|
||||||
|
func (u *ContainerUpdate) AddLinuxHugepageLimit(pageSize string, value uint64) {
|
||||||
|
u.initLinuxResources()
|
||||||
|
u.Linux.Resources.HugepageLimits = append(u.Linux.Resources.HugepageLimits,
|
||||||
|
&HugepageLimit{
|
||||||
|
PageSize: pageSize,
|
||||||
|
Limit: value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxBlockIOClass records setting the Block I/O class for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxBlockIOClass(value string) {
|
||||||
|
u.initLinuxResources()
|
||||||
|
u.Linux.Resources.BlockioClass = String(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxRDTClass records setting the RDT class for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxRDTClass(value string) {
|
||||||
|
u.initLinuxResources()
|
||||||
|
u.Linux.Resources.RdtClass = String(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLinuxUnified sets a cgroupv2 unified resource.
|
||||||
|
func (u *ContainerUpdate) AddLinuxUnified(key, value string) {
|
||||||
|
u.initLinuxResourcesUnified()
|
||||||
|
u.Linux.Resources.Unified[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIgnoreFailure marks an Update as ignored for failures.
|
||||||
|
// Such updates will not prevent the related container operation
|
||||||
|
// from succeeding if the update fails.
|
||||||
|
func (u *ContainerUpdate) SetIgnoreFailure() {
|
||||||
|
u.IgnoreFailure = true
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initializing a container update.
|
||||||
|
//
|
||||||
|
|
||||||
|
func (u *ContainerUpdate) initLinux() {
|
||||||
|
if u.Linux == nil {
|
||||||
|
u.Linux = &LinuxContainerUpdate{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *ContainerUpdate) initLinuxResources() {
|
||||||
|
u.initLinux()
|
||||||
|
if u.Linux.Resources == nil {
|
||||||
|
u.Linux.Resources = &LinuxResources{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *ContainerUpdate) initLinuxResourcesMemory() {
|
||||||
|
u.initLinuxResources()
|
||||||
|
if u.Linux.Resources.Memory == nil {
|
||||||
|
u.Linux.Resources.Memory = &LinuxMemory{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *ContainerUpdate) initLinuxResourcesCPU() {
|
||||||
|
u.initLinuxResources()
|
||||||
|
if u.Linux.Resources.Cpu == nil {
|
||||||
|
u.Linux.Resources.Cpu = &LinuxCPU{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *ContainerUpdate) initLinuxResourcesUnified() {
|
||||||
|
u.initLinuxResources()
|
||||||
|
if u.Linux.Resources.Unified == nil {
|
||||||
|
u.Linux.Resources.Unified = make(map[string]string)
|
||||||
|
}
|
||||||
|
}
|
87
vendor/github.com/containerd/nri/pkg/log/log.go
generated
vendored
Normal file
87
vendor/github.com/containerd/nri/pkg/log/log.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
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 log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
log Logger = &fallbackLogger{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Logger is the interface NRI uses for logging.
|
||||||
|
type Logger interface {
|
||||||
|
Debugf(ctx context.Context, format string, args ...interface{})
|
||||||
|
Infof(ctx context.Context, format string, args ...interface{})
|
||||||
|
Warnf(ctx context.Context, format string, args ...interface{})
|
||||||
|
Errorf(ctx context.Context, format string, args ...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the logger used by NRI.
|
||||||
|
func Set(l Logger) {
|
||||||
|
log = l
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the logger used by NRI.
|
||||||
|
func Get() Logger {
|
||||||
|
return log
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf logs a formatted debug message.
|
||||||
|
func Debugf(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
log.Debugf(ctx, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof logs a formatted informational message.
|
||||||
|
func Infof(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
log.Infof(ctx, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warnf logs a formatted warning message.
|
||||||
|
func Warnf(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
log.Warnf(ctx, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf logs a formatted error message.
|
||||||
|
func Errorf(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
log.Errorf(ctx, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
type fallbackLogger struct{}
|
||||||
|
|
||||||
|
// Debugf logs a formatted debug message.
|
||||||
|
func (f *fallbackLogger) Debugf(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
logrus.WithContext(ctx).Debugf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof logs a formatted informational message.
|
||||||
|
func (f *fallbackLogger) Infof(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
logrus.WithContext(ctx).Infof(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warnf logs a formatted warning message.
|
||||||
|
func (f *fallbackLogger) Warnf(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
logrus.WithContext(ctx).Warnf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf logs a formatted error message.
|
||||||
|
func (f *fallbackLogger) Errorf(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
logrus.WithContext(ctx).Errorf(format, args...)
|
||||||
|
}
|
93
vendor/github.com/containerd/nri/pkg/net/conn.go
generated
vendored
Normal file
93
vendor/github.com/containerd/nri/pkg/net/conn.go
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
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 net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewFdConn creates a net.Conn for the given (socket) fd.
|
||||||
|
func NewFdConn(fd int) (net.Conn, error) {
|
||||||
|
f := os.NewFile(uintptr(fd), "fd #"+strconv.Itoa(fd))
|
||||||
|
|
||||||
|
conn, err := net.FileConn(f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create net.Conn for fd #%d: %w", fd, err)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// connListener wraps a pre-connected socket in a net.Listener.
|
||||||
|
type connListener struct {
|
||||||
|
next chan net.Conn
|
||||||
|
conn net.Conn
|
||||||
|
addr net.Addr
|
||||||
|
lock sync.RWMutex // for Close()
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConnListener wraps an existing net.Conn in a net.Listener.
|
||||||
|
//
|
||||||
|
// The first call to Accept() on the listener will return the wrapped
|
||||||
|
// connection. Subsequent calls to Accept() block until the listener
|
||||||
|
// is closed, then return io.EOF. Close() closes the listener and the
|
||||||
|
// wrapped connection.
|
||||||
|
func NewConnListener(conn net.Conn) net.Listener {
|
||||||
|
next := make(chan net.Conn, 1)
|
||||||
|
next <- conn
|
||||||
|
|
||||||
|
return &connListener{
|
||||||
|
next: next,
|
||||||
|
conn: conn,
|
||||||
|
addr: conn.LocalAddr(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept returns the wrapped connection when it is called the first
|
||||||
|
// time. Later calls to Accept block until the listener is closed, then
|
||||||
|
// return io.EOF.
|
||||||
|
func (l *connListener) Accept() (net.Conn, error) {
|
||||||
|
conn := <-l.next
|
||||||
|
if conn == nil {
|
||||||
|
return nil, io.EOF
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the listener and the wrapped connection.
|
||||||
|
func (l *connListener) Close() error {
|
||||||
|
l.lock.Lock()
|
||||||
|
defer l.lock.Unlock()
|
||||||
|
if l.closed {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
close(l.next)
|
||||||
|
l.closed = true
|
||||||
|
return l.conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Addr returns the local address of the wrapped connection.
|
||||||
|
func (l *connListener) Addr() net.Addr {
|
||||||
|
return l.addr
|
||||||
|
}
|
444
vendor/github.com/containerd/nri/pkg/net/multiplex/mux.go
generated
vendored
Normal file
444
vendor/github.com/containerd/nri/pkg/net/multiplex/mux.go
generated
vendored
Normal file
@ -0,0 +1,444 @@
|
|||||||
|
/*
|
||||||
|
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 multiplex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
nrinet "github.com/containerd/nri/pkg/net"
|
||||||
|
"github.com/containerd/ttrpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Mux multiplexes several logical connections over a single net.Conn.
|
||||||
|
//
|
||||||
|
// Connections are identified within a Mux by ConnIDs which are simple
|
||||||
|
// 32-bit unsigned integers. Opening a connection returns a net.Conn
|
||||||
|
// corrponding to the ConnID. This can then be used to write and read
|
||||||
|
// data through the connection with the Mux performing multiplexing
|
||||||
|
// and demultiplexing of data.
|
||||||
|
//
|
||||||
|
// Writing to a connection is fully synchronous. The caller can safely
|
||||||
|
// reuse the buffer once the call returns. Reading from a connection
|
||||||
|
// returns the oldest demultiplexed buffer for the connection, blocking
|
||||||
|
// if the connections incoming queue is empty. If any incoming queue is
|
||||||
|
// ever overflown the underlying trunk and all multiplexed connections
|
||||||
|
// are closed and an error is recorded. This error is later returned by
|
||||||
|
// any subsequent read from any connection. All connections of the Mux
|
||||||
|
// have the same fixed incoming queue length which can be configured
|
||||||
|
// using the WithReadQueueLength Option during Mux creation.
|
||||||
|
//
|
||||||
|
// The Mux interface also provides functions that emulate net.Dial and
|
||||||
|
// net.Listen for a connection. Usually these can be used for passing
|
||||||
|
// multiplexed connections to packages that insist to Dial or Accept
|
||||||
|
// themselves for connection establishment.
|
||||||
|
//
|
||||||
|
// Note that opening a connection is a virtual operation in the sense
|
||||||
|
// that it has no effects outside the Mux. It is performed without any
|
||||||
|
// signalling or other communication. It merely acquires the net.Conn
|
||||||
|
// corresponding to the connection and blindly assumes that the same
|
||||||
|
// ConnID is or will be opened at the other end of the Mux.
|
||||||
|
type Mux interface {
|
||||||
|
// Open the connection for the given ConnID.
|
||||||
|
Open(ConnID) (net.Conn, error)
|
||||||
|
|
||||||
|
// Close the Mux and all connections associated with it.
|
||||||
|
Close() error
|
||||||
|
|
||||||
|
// Dialer returns a net.Dial-like function for the connection.
|
||||||
|
//
|
||||||
|
// Calling the returned function (with arguments) will return a
|
||||||
|
// net.Conn for the connection.
|
||||||
|
Dialer(ConnID) func(string, string) (net.Conn, error)
|
||||||
|
|
||||||
|
// Listener returns a net.Listener for the connection. The first
|
||||||
|
// call to Accept() on the listener will return a net.Conn for the
|
||||||
|
// connection. Subsequent calls to Accept() will block until the
|
||||||
|
// connection is closed then return io.EOF.
|
||||||
|
Listen(ConnID) (net.Listener, error)
|
||||||
|
|
||||||
|
// Trunk returns the trunk connection for the Mux.
|
||||||
|
Trunk() net.Conn
|
||||||
|
|
||||||
|
// Unblock unblocks the Mux reader.
|
||||||
|
Unblock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnID uniquely identifies a logical connection within a Mux.
|
||||||
|
type ConnID uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ConnID 0 is reserved for future use.
|
||||||
|
reservedConnID ConnID = iota
|
||||||
|
// LowestConnID is the lowest externally usable ConnID.
|
||||||
|
LowestConnID
|
||||||
|
)
|
||||||
|
|
||||||
|
// Option to apply to a Mux.
|
||||||
|
type Option func(*mux)
|
||||||
|
|
||||||
|
// WithBlockedRead causes the Mux to be blocked for reading until gets Unblock()'ed.
|
||||||
|
func WithBlockedRead() Option {
|
||||||
|
return func(m *mux) {
|
||||||
|
if m.blockC == nil {
|
||||||
|
m.blockC = make(chan struct{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithReadQueueLength overrides the default read queue size.
|
||||||
|
func WithReadQueueLength(length int) Option {
|
||||||
|
return func(m *mux) {
|
||||||
|
m.qlen = length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiplex returns a multiplexer for the given connection.
|
||||||
|
func Multiplex(trunk net.Conn, options ...Option) Mux {
|
||||||
|
return newMux(trunk, options...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mux is our implementation of Mux.
|
||||||
|
type mux struct {
|
||||||
|
trunk net.Conn
|
||||||
|
writeLock sync.Mutex
|
||||||
|
conns map[ConnID]*conn
|
||||||
|
connLock sync.RWMutex
|
||||||
|
qlen int
|
||||||
|
errOnce sync.Once
|
||||||
|
err error
|
||||||
|
unblkOnce sync.Once
|
||||||
|
blockC chan struct{}
|
||||||
|
closeOnce sync.Once
|
||||||
|
doneC chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// default read queue length for a single connection
|
||||||
|
readQueueLen = 256
|
||||||
|
// length of frame header: 4-byte ConnID, 4-byte payload length
|
||||||
|
headerLen = 8
|
||||||
|
// max. allowed payload size
|
||||||
|
maxPayloadSize = 1 << 24
|
||||||
|
)
|
||||||
|
|
||||||
|
// conn represents a single multiplexed connection.
|
||||||
|
type conn struct {
|
||||||
|
id ConnID
|
||||||
|
mux *mux
|
||||||
|
readC chan []byte
|
||||||
|
closeOnce sync.Once
|
||||||
|
doneC chan error
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMux(trunk net.Conn, options ...Option) *mux {
|
||||||
|
m := &mux{
|
||||||
|
trunk: trunk,
|
||||||
|
conns: make(map[ConnID]*conn),
|
||||||
|
qlen: readQueueLen,
|
||||||
|
doneC: make(chan struct{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o := range options {
|
||||||
|
o(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.blockC == nil {
|
||||||
|
WithBlockedRead()(m)
|
||||||
|
m.Unblock()
|
||||||
|
}
|
||||||
|
|
||||||
|
go m.reader()
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) Trunk() net.Conn {
|
||||||
|
return m.trunk
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) Unblock() {
|
||||||
|
m.unblkOnce.Do(func() {
|
||||||
|
close(m.blockC)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) Open(id ConnID) (net.Conn, error) {
|
||||||
|
if id == reservedConnID {
|
||||||
|
return nil, fmt.Errorf("ConnID %d is reserved", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.connLock.Lock()
|
||||||
|
defer m.connLock.Unlock()
|
||||||
|
|
||||||
|
c, ok := m.conns[id]
|
||||||
|
if !ok {
|
||||||
|
c = &conn{
|
||||||
|
id: id,
|
||||||
|
mux: m,
|
||||||
|
doneC: make(chan error, 1),
|
||||||
|
readC: make(chan []byte, m.qlen),
|
||||||
|
}
|
||||||
|
m.conns[id] = c
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) Close() error {
|
||||||
|
m.closeOnce.Do(func() {
|
||||||
|
m.connLock.Lock()
|
||||||
|
defer m.connLock.Unlock()
|
||||||
|
for _, conn := range m.conns {
|
||||||
|
conn.close()
|
||||||
|
}
|
||||||
|
close(m.doneC)
|
||||||
|
m.trunk.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) Dialer(id ConnID) func(string, string) (net.Conn, error) {
|
||||||
|
return func(string, string) (net.Conn, error) {
|
||||||
|
return m.Open(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) Listen(id ConnID) (net.Listener, error) {
|
||||||
|
conn, err := m.Open(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nrinet.NewConnListener(conn), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) write(id ConnID, buf []byte) (int, error) {
|
||||||
|
var hdr [headerLen]byte
|
||||||
|
|
||||||
|
if len(buf) > maxPayloadSize {
|
||||||
|
return 0, syscall.EMSGSIZE
|
||||||
|
}
|
||||||
|
|
||||||
|
binary.BigEndian.PutUint32(hdr[0:4], uint32(id))
|
||||||
|
binary.BigEndian.PutUint32(hdr[4:8], uint32(len(buf)))
|
||||||
|
|
||||||
|
m.writeLock.Lock()
|
||||||
|
defer m.writeLock.Unlock()
|
||||||
|
|
||||||
|
n, err := m.trunk.Write(hdr[:])
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("failed to write header to trunk: %w", err)
|
||||||
|
if n != 0 {
|
||||||
|
m.setError(err)
|
||||||
|
m.Close()
|
||||||
|
}
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err = m.trunk.Write(buf)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("failed to write payload to trunk: %w", err)
|
||||||
|
if n != 0 {
|
||||||
|
m.setError(err)
|
||||||
|
m.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) reader() {
|
||||||
|
var (
|
||||||
|
hdr [headerLen]byte
|
||||||
|
cid uint32
|
||||||
|
cnt uint32
|
||||||
|
buf []byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
<-m.blockC
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-m.doneC:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.ReadFull(m.trunk, hdr[:])
|
||||||
|
if err != nil {
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, io.EOF):
|
||||||
|
case errors.Is(err, ttrpc.ErrClosed):
|
||||||
|
err = io.EOF
|
||||||
|
case errors.Is(err, ttrpc.ErrServerClosed):
|
||||||
|
err = io.EOF
|
||||||
|
case errors.Is(err, net.ErrClosed):
|
||||||
|
err = io.EOF
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("failed to read header from trunk: %w", err)
|
||||||
|
}
|
||||||
|
m.setError(err)
|
||||||
|
m.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cid = binary.BigEndian.Uint32(hdr[0:4])
|
||||||
|
cnt = binary.BigEndian.Uint32(hdr[4:8])
|
||||||
|
buf = make([]byte, int(cnt))
|
||||||
|
|
||||||
|
_, err = io.ReadFull(m.trunk, buf)
|
||||||
|
if err != nil {
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, io.EOF):
|
||||||
|
case errors.Is(err, ttrpc.ErrClosed):
|
||||||
|
err = io.EOF
|
||||||
|
case errors.Is(err, ttrpc.ErrServerClosed):
|
||||||
|
err = io.EOF
|
||||||
|
case errors.Is(err, net.ErrClosed):
|
||||||
|
err = io.EOF
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("failed to read payload from trunk: %w", err)
|
||||||
|
}
|
||||||
|
m.setError(err)
|
||||||
|
m.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.connLock.RLock()
|
||||||
|
conn, ok := m.conns[ConnID(cid)]
|
||||||
|
m.connLock.RUnlock()
|
||||||
|
if ok {
|
||||||
|
select {
|
||||||
|
case conn.readC <- buf:
|
||||||
|
default:
|
||||||
|
m.setError(errors.New("failed to queue payload for reading"))
|
||||||
|
m.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) setError(err error) {
|
||||||
|
m.errOnce.Do(func() {
|
||||||
|
m.err = err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// nolint
|
||||||
|
func (m *mux) error() error {
|
||||||
|
m.errOnce.Do(func() {
|
||||||
|
if m.err == nil {
|
||||||
|
m.err = io.EOF
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return m.err
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// multiplexed connections
|
||||||
|
//
|
||||||
|
|
||||||
|
// Reads reads the next message from the multiplexed connection.
|
||||||
|
func (c *conn) Read(buf []byte) (int, error) {
|
||||||
|
var (
|
||||||
|
msg []byte
|
||||||
|
err error
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case err, ok = <-c.doneC:
|
||||||
|
if !ok || err == nil {
|
||||||
|
err = c.mux.error()
|
||||||
|
}
|
||||||
|
return 0, err
|
||||||
|
case msg, ok = <-c.readC:
|
||||||
|
if !ok {
|
||||||
|
return 0, c.mux.error()
|
||||||
|
}
|
||||||
|
if cap(buf) < len(msg) {
|
||||||
|
return 0, syscall.ENOMEM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(buf, msg)
|
||||||
|
return len(msg), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write writes the given data to the multiplexed connection.
|
||||||
|
func (c *conn) Write(b []byte) (int, error) {
|
||||||
|
select {
|
||||||
|
case err := <-c.doneC:
|
||||||
|
if err == nil {
|
||||||
|
err = io.EOF
|
||||||
|
}
|
||||||
|
return 0, err
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return c.mux.write(c.id, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the multiplexed connection.
|
||||||
|
func (c *conn) Close() error {
|
||||||
|
c.mux.connLock.Lock()
|
||||||
|
defer c.mux.connLock.Unlock()
|
||||||
|
if c.mux.conns[c.id] == c {
|
||||||
|
delete(c.mux.conns, c.id)
|
||||||
|
}
|
||||||
|
return c.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) close() error {
|
||||||
|
c.closeOnce.Do(func() {
|
||||||
|
close(c.doneC)
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalAddr is the unimplemented stub for the corresponding net.Conn function.
|
||||||
|
func (c *conn) LocalAddr() net.Addr {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoteAddr is the unimplemented stub for the corresponding net.Conn function.
|
||||||
|
func (c *conn) RemoteAddr() net.Addr {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDeadline is the unimplemented stub for the corresponding net.Conn function.
|
||||||
|
func (c *conn) SetDeadline(t time.Time) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetReadDeadline is the unimplemented stub for the corresponding net.Conn function.
|
||||||
|
func (c *conn) SetReadDeadline(t time.Time) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWriteDeadline is the unimplemented stub for the corresponding net.Conn function.
|
||||||
|
func (c *conn) SetWriteDeadline(t time.Time) error {
|
||||||
|
return nil
|
||||||
|
}
|
24
vendor/github.com/containerd/nri/pkg/net/multiplex/ttrpc.go
generated
vendored
Normal file
24
vendor/github.com/containerd/nri/pkg/net/multiplex/ttrpc.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
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 multiplex
|
||||||
|
|
||||||
|
const (
|
||||||
|
// PluginServiceConn is the mux connection ID for NRI plugin services.
|
||||||
|
PluginServiceConn ConnID = iota + 1
|
||||||
|
// RuntimeServiceConn is the mux connection ID for NRI runtime services.
|
||||||
|
RuntimeServiceConn
|
||||||
|
)
|
98
vendor/github.com/containerd/nri/pkg/net/socketpair_unix.go
generated
vendored
Normal file
98
vendor/github.com/containerd/nri/pkg/net/socketpair_unix.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
//go:build !windows
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
syscall "golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
local = 0
|
||||||
|
peer = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// SocketPair contains the file descriptors of a connected pair of sockets.
|
||||||
|
type SocketPair [2]int
|
||||||
|
|
||||||
|
// NewSocketPair returns a connected pair of sockets.
|
||||||
|
func NewSocketPair() (SocketPair, error) {
|
||||||
|
fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
|
||||||
|
if err != nil {
|
||||||
|
return [2]int{-1, -1}, fmt.Errorf("failed to create socketpair: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalFile returns the socketpair fd for local usage as an *os.File.
|
||||||
|
func (fds SocketPair) LocalFile() *os.File {
|
||||||
|
return os.NewFile(uintptr(fds[local]), fds.fileName()+"[0]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerFile returns the socketpair fd for peer usage as an *os.File.
|
||||||
|
func (fds SocketPair) PeerFile() *os.File {
|
||||||
|
return os.NewFile(uintptr(fds[peer]), fds.fileName()+"[1]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalConn returns a net.Conn for the local end of the socketpair.
|
||||||
|
func (fds SocketPair) LocalConn() (net.Conn, error) {
|
||||||
|
file := fds.LocalFile()
|
||||||
|
defer file.Close()
|
||||||
|
conn, err := net.FileConn(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create net.Conn for %s[0]: %w", fds.fileName(), err)
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerConn returns a net.Conn for the peer end of the socketpair.
|
||||||
|
func (fds SocketPair) PeerConn() (net.Conn, error) {
|
||||||
|
file := fds.PeerFile()
|
||||||
|
defer file.Close()
|
||||||
|
conn, err := net.FileConn(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create net.Conn for %s[1]: %w", fds.fileName(), err)
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes both ends of the socketpair.
|
||||||
|
func (fds SocketPair) Close() {
|
||||||
|
fds.LocalClose()
|
||||||
|
fds.PeerClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalClose closes the local end of the socketpair.
|
||||||
|
func (fds SocketPair) LocalClose() {
|
||||||
|
syscall.Close(fds[local])
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerClose closes the peer end of the socketpair.
|
||||||
|
func (fds SocketPair) PeerClose() {
|
||||||
|
syscall.Close(fds[peer])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fds SocketPair) fileName() string {
|
||||||
|
return fmt.Sprintf("socketpair-#%d:%d[0]", fds[local], fds[peer])
|
||||||
|
}
|
198
vendor/github.com/containerd/nri/pkg/net/socketpair_windows.go
generated
vendored
Normal file
198
vendor/github.com/containerd/nri/pkg/net/socketpair_windows.go
generated
vendored
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
sys "golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SocketPair contains a connected pair of sockets.
|
||||||
|
type SocketPair [2]sys.Handle
|
||||||
|
|
||||||
|
const (
|
||||||
|
local = 0
|
||||||
|
peer = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewSocketPair returns a connected pair of sockets.
|
||||||
|
func NewSocketPair() (SocketPair, error) {
|
||||||
|
/* return [2]sys.Handle{sys.InvalidHandle, sys.InvalidHandle},
|
||||||
|
errors.New("failed to emulatesocketpair, unimplemented for windows")*/
|
||||||
|
|
||||||
|
// untested: return emulateWithPreConnect()
|
||||||
|
return emulateWithPreConnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
func emulateWithPreConnect() (SocketPair, error) {
|
||||||
|
var (
|
||||||
|
invalid = SocketPair{sys.InvalidHandle, sys.InvalidHandle}
|
||||||
|
sa sys.SockaddrInet4
|
||||||
|
//sn sys.Sockaddr
|
||||||
|
l sys.Handle
|
||||||
|
a sys.Handle
|
||||||
|
p sys.Handle
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
l, err = socket(sys.AF_INET, sys.SOCK_STREAM, 0)
|
||||||
|
if err != nil {
|
||||||
|
return invalid, fmt.Errorf("failed to emulate socketpair (local Socket()): %w", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
sys.CloseHandle(l)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
sa.Addr[0] = 127
|
||||||
|
sa.Addr[3] = 1
|
||||||
|
sa.Port = 9999
|
||||||
|
|
||||||
|
err = sys.Bind(l, &sa)
|
||||||
|
if err != nil {
|
||||||
|
return invalid, fmt.Errorf("failed to emulate socketpair (Bind()): %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*sn, err = sys.Getsockname(l)
|
||||||
|
if err != nil {
|
||||||
|
return invalid, fmt.Errorf("failed to emulate socketpair (Getsockname()): %w", err)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
p, err = socket(sys.AF_INET, sys.SOCK_STREAM, 0)
|
||||||
|
if err != nil {
|
||||||
|
return invalid, fmt.Errorf("failed to emulate socketpair (peer Socket()): %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
sys.CloseHandle(p)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = sys.Listen(l, 0)
|
||||||
|
if err != nil {
|
||||||
|
return invalid, fmt.Errorf("failed to emulate socketpair (Listen()): %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err = connect(p, &sa)
|
||||||
|
}()
|
||||||
|
|
||||||
|
a, err = accept(l, sys.AF_INET, sys.SOCK_STREAM, 0)
|
||||||
|
if err != nil {
|
||||||
|
return invalid, fmt.Errorf("failed to emualte socketpair (Accept()): %w", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
sys.CloseHandle(a)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
sys.CloseHandle(l)
|
||||||
|
return SocketPair{a, p}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes both ends of the socketpair.
|
||||||
|
func (sp SocketPair) Close() {
|
||||||
|
sp.LocalClose()
|
||||||
|
sp.PeerClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalFile returns the socketpair fd for local usage as an *os.File.
|
||||||
|
func (sp SocketPair) LocalFile() *os.File {
|
||||||
|
return os.NewFile(uintptr(sp[local]), sp.fileName()+"[0]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerFile returns the socketpair fd for peer usage as an *os.File.
|
||||||
|
func (sp SocketPair) PeerFile() *os.File {
|
||||||
|
return os.NewFile(uintptr(sp[peer]), sp.fileName()+"[1]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalConn returns a net.Conn for the local end of the socketpair.
|
||||||
|
func (sp SocketPair) LocalConn() (net.Conn, error) {
|
||||||
|
file := sp.LocalFile()
|
||||||
|
defer file.Close()
|
||||||
|
conn, err := net.FileConn(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create net.Conn for %s[0]: %w", sp.fileName(), err)
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerConn returns a net.Conn for the peer end of the socketpair.
|
||||||
|
func (sp SocketPair) PeerConn() (net.Conn, error) {
|
||||||
|
file := sp.PeerFile()
|
||||||
|
defer file.Close()
|
||||||
|
conn, err := net.FileConn(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create net.Conn for %s[1]: %w", sp.fileName(), err)
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalClose closes the local end of the socketpair.
|
||||||
|
func (sp SocketPair) LocalClose() {
|
||||||
|
sys.CloseHandle(sp[local])
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerClose closes the peer end of the socketpair.
|
||||||
|
func (sp SocketPair) PeerClose() {
|
||||||
|
sys.CloseHandle(sp[peer])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sp SocketPair) fileName() string {
|
||||||
|
return fmt.Sprintf("socketpair-#%d:%d[0]", sp[local], sp[peer])
|
||||||
|
}
|
||||||
|
|
||||||
|
func socket(domain, typ, proto int) (sys.Handle, error) {
|
||||||
|
return sys.WSASocket(int32(domain), int32(typ), int32(proto), nil, 0, sys.WSA_FLAG_OVERLAPPED)
|
||||||
|
}
|
||||||
|
|
||||||
|
func connect(s sys.Handle, sa sys.Sockaddr) error {
|
||||||
|
o := &sys.Overlapped{}
|
||||||
|
return sys.ConnectEx(s, sa, nil, 0, nil, o)
|
||||||
|
}
|
||||||
|
|
||||||
|
func accept(l sys.Handle, domain, typ, proto int) (sys.Handle, error) {
|
||||||
|
var (
|
||||||
|
a sys.Handle
|
||||||
|
err error
|
||||||
|
buf = [1024]byte{}
|
||||||
|
overlap = sys.Overlapped{}
|
||||||
|
cnt = uint32(16 + 256)
|
||||||
|
)
|
||||||
|
|
||||||
|
a, err = socket(sys.AF_INET, sys.SOCK_STREAM, 0)
|
||||||
|
if err != nil {
|
||||||
|
return sys.InvalidHandle, fmt.Errorf("failed to emulate socketpair (accept): %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sys.AcceptEx(l, a, (*byte)(unsafe.Pointer(&buf)), 0, cnt, cnt, &cnt, &overlap)
|
||||||
|
if err != nil {
|
||||||
|
return sys.InvalidHandle, fmt.Errorf("failed to emulate socketpair (AcceptEx()): %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return a, nil
|
||||||
|
}
|
422
vendor/github.com/containerd/nri/pkg/runtime-tools/generate/generate.go
generated
vendored
Normal file
422
vendor/github.com/containerd/nri/pkg/runtime-tools/generate/generate.go
generated
vendored
Normal file
@ -0,0 +1,422 @@
|
|||||||
|
/*
|
||||||
|
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 generate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/opencontainers/runtime-tools/generate"
|
||||||
|
|
||||||
|
nri "github.com/containerd/nri/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GeneratorOption is an option for Generator().
|
||||||
|
type GeneratorOption func(*Generator)
|
||||||
|
|
||||||
|
// Generator extends a stock runtime-tools Generator and extends it with
|
||||||
|
// a few functions for handling NRI container adjustment.
|
||||||
|
type Generator struct {
|
||||||
|
*generate.Generator
|
||||||
|
filterLabels func(map[string]string) (map[string]string, error)
|
||||||
|
filterAnnotations func(map[string]string) (map[string]string, error)
|
||||||
|
resolveBlockIO func(string) (*rspec.LinuxBlockIO, error)
|
||||||
|
resolveRdt func(string) (*rspec.LinuxIntelRdt, error)
|
||||||
|
checkResources func(*rspec.LinuxResources) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// SpecGenerator returns a wrapped OCI Spec Generator.
|
||||||
|
func SpecGenerator(gg *generate.Generator, opts ...GeneratorOption) *Generator {
|
||||||
|
g := &Generator{
|
||||||
|
Generator: gg,
|
||||||
|
}
|
||||||
|
g.filterLabels = nopFilter
|
||||||
|
g.filterAnnotations = nopFilter
|
||||||
|
for _, o := range opts {
|
||||||
|
o(g)
|
||||||
|
}
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithLabelFilter provides an option for filtering or rejecting labels.
|
||||||
|
func WithLabelFilter(fn func(map[string]string) (map[string]string, error)) GeneratorOption {
|
||||||
|
return func(g *Generator) {
|
||||||
|
g.filterLabels = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithAnnotationFilter provides an option for filtering or rejecting annotations.
|
||||||
|
func WithAnnotationFilter(fn func(map[string]string) (map[string]string, error)) GeneratorOption {
|
||||||
|
return func(g *Generator) {
|
||||||
|
g.filterAnnotations = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithBlockIOResolver specifies a function for resolving Block I/O classes by name.
|
||||||
|
func WithBlockIOResolver(fn func(string) (*rspec.LinuxBlockIO, error)) GeneratorOption {
|
||||||
|
return func(g *Generator) {
|
||||||
|
g.resolveBlockIO = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithRdtResolver specifies a function for resolving RDT classes by name.
|
||||||
|
func WithRdtResolver(fn func(string) (*rspec.LinuxIntelRdt, error)) GeneratorOption {
|
||||||
|
return func(g *Generator) {
|
||||||
|
g.resolveRdt = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithResourceChecker specifies a function to perform final resource adjustment.
|
||||||
|
func WithResourceChecker(fn func(*rspec.LinuxResources) error) GeneratorOption {
|
||||||
|
return func(g *Generator) {
|
||||||
|
g.checkResources = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust adjusts all aspects of the OCI Spec that NRI knows/cares about.
|
||||||
|
func (g *Generator) Adjust(adjust *nri.ContainerAdjustment) error {
|
||||||
|
if adjust == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := g.AdjustAnnotations(adjust.GetAnnotations()); err != nil {
|
||||||
|
return fmt.Errorf("failed to adjust annotations in OCI Spec: %w", err)
|
||||||
|
}
|
||||||
|
g.AdjustEnv(adjust.GetEnv())
|
||||||
|
g.AdjustHooks(adjust.GetHooks())
|
||||||
|
g.AdjustDevices(adjust.GetLinux().GetDevices())
|
||||||
|
g.AdjustCgroupsPath(adjust.GetLinux().GetCgroupsPath())
|
||||||
|
|
||||||
|
resources := adjust.GetLinux().GetResources()
|
||||||
|
if err := g.AdjustResources(resources); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := g.AdjustBlockIOClass(resources.GetBlockioClass().Get()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := g.AdjustRdtClass(resources.GetRdtClass().Get()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := g.AdjustMounts(adjust.GetMounts()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdjustEnv adjusts the environment of the OCI Spec.
|
||||||
|
func (g *Generator) AdjustEnv(env []*nri.KeyValue) {
|
||||||
|
mod := map[string]*nri.KeyValue{}
|
||||||
|
|
||||||
|
for _, e := range env {
|
||||||
|
key, _ := nri.IsMarkedForRemoval(e.Key)
|
||||||
|
mod[key] = e
|
||||||
|
}
|
||||||
|
|
||||||
|
// first modify existing environment
|
||||||
|
if len(mod) > 0 && g.Config != nil && g.Config.Process != nil {
|
||||||
|
old := g.Config.Process.Env
|
||||||
|
g.ClearProcessEnv()
|
||||||
|
for _, e := range old {
|
||||||
|
keyval := strings.SplitN(e, "=", 2)
|
||||||
|
if len(keyval) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if m, ok := mod[keyval[0]]; ok {
|
||||||
|
delete(mod, keyval[0])
|
||||||
|
if _, marked := m.IsMarkedForRemoval(); !marked {
|
||||||
|
g.AddProcessEnv(m.Key, m.Value)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
g.AddProcessEnv(keyval[0], keyval[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// then append remaining unprocessed adjustments (new variables)
|
||||||
|
for _, e := range env {
|
||||||
|
if _, marked := e.IsMarkedForRemoval(); marked {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := mod[e.Key]; ok {
|
||||||
|
g.AddProcessEnv(e.Key, e.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdjustAnnotations adjusts the annotations in the OCI Spec.
|
||||||
|
func (g *Generator) AdjustAnnotations(annotations map[string]string) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if annotations, err = g.filterAnnotations(annotations); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for k, v := range annotations {
|
||||||
|
if key, marked := nri.IsMarkedForRemoval(k); marked {
|
||||||
|
g.RemoveAnnotation(key)
|
||||||
|
} else {
|
||||||
|
g.AddAnnotation(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdjustHooks adjusts the OCI hooks in the OCI Spec.
|
||||||
|
func (g *Generator) AdjustHooks(hooks *nri.Hooks) {
|
||||||
|
if hooks == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, h := range hooks.Prestart {
|
||||||
|
g.AddPreStartHook(h.ToOCI())
|
||||||
|
}
|
||||||
|
for _, h := range hooks.Poststart {
|
||||||
|
g.AddPostStartHook(h.ToOCI())
|
||||||
|
}
|
||||||
|
for _, h := range hooks.Poststop {
|
||||||
|
g.AddPostStopHook(h.ToOCI())
|
||||||
|
}
|
||||||
|
for _, h := range hooks.CreateRuntime {
|
||||||
|
g.AddCreateRuntimeHook(h.ToOCI())
|
||||||
|
}
|
||||||
|
for _, h := range hooks.CreateContainer {
|
||||||
|
g.AddCreateContainerHook(h.ToOCI())
|
||||||
|
}
|
||||||
|
for _, h := range hooks.StartContainer {
|
||||||
|
g.AddStartContainerHook(h.ToOCI())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdjustResources adjusts the (Linux) resources in the OCI Spec.
|
||||||
|
func (g *Generator) AdjustResources(r *nri.LinuxResources) error {
|
||||||
|
if r == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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.Memory != nil {
|
||||||
|
if l := r.Memory.GetLimit().GetValue(); l != 0 {
|
||||||
|
g.SetLinuxResourcesMemoryLimit(l)
|
||||||
|
g.SetLinuxResourcesMemorySwap(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, l := range r.HugepageLimits {
|
||||||
|
g.AddLinuxResourcesHugepageLimit(l.PageSize, l.Limit)
|
||||||
|
}
|
||||||
|
for k, v := range r.Unified {
|
||||||
|
g.AddLinuxResourcesUnified(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.checkResources != nil {
|
||||||
|
if err := g.checkResources(g.Config.Linux.Resources); err != nil {
|
||||||
|
return fmt.Errorf("failed to adjust resources in OCI Spec: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdjustBlockIOClass adjusts the block I/O class in the OCI Spec.
|
||||||
|
func (g *Generator) AdjustBlockIOClass(blockIOClass *string) error {
|
||||||
|
if blockIOClass == nil || g.resolveBlockIO == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if *blockIOClass == "" {
|
||||||
|
g.ClearLinuxResourcesBlockIO()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
blockIO, err := g.resolveBlockIO(*blockIOClass)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to adjust BlockIO class in OCI Spec: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
g.SetLinuxResourcesBlockIO(blockIO)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdjustRdtClass adjusts the RDT class in the OCI Spec.
|
||||||
|
func (g *Generator) AdjustRdtClass(rdtClass *string) error {
|
||||||
|
if rdtClass == nil || g.resolveRdt == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if *rdtClass == "" {
|
||||||
|
g.ClearLinuxIntelRdt()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
rdt, err := g.resolveRdt(*rdtClass)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to adjust RDT class in OCI Spec: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
g.SetLinuxIntelRdt(rdt)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdjustCgroupsPath adjusts the cgroup pseudofs path in the OCI Spec.
|
||||||
|
func (g *Generator) AdjustCgroupsPath(path string) {
|
||||||
|
if path != "" {
|
||||||
|
g.SetLinuxCgroupsPath(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdjustDevices adjusts the (Linux) devices in the OCI Spec.
|
||||||
|
func (g *Generator) AdjustDevices(devices []*nri.LinuxDevice) {
|
||||||
|
for _, d := range devices {
|
||||||
|
key, marked := d.IsMarkedForRemoval()
|
||||||
|
g.RemoveDevice(key)
|
||||||
|
if marked {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
g.AddDevice(d.ToOCI())
|
||||||
|
major, minor, access := &d.Major, &d.Minor, d.AccessString()
|
||||||
|
g.AddLinuxResourcesDevice(true, d.Type, major, minor, access)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AdjustMounts adjusts the mounts in the OCI Spec.
|
||||||
|
func (g *Generator) AdjustMounts(mounts []*nri.Mount) error {
|
||||||
|
var (
|
||||||
|
propagation string
|
||||||
|
)
|
||||||
|
|
||||||
|
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":
|
||||||
|
if err := ensurePropagation(mnt.Source, "rshared"); err != nil {
|
||||||
|
return fmt.Errorf("failed to adjust mounts in OCI Spec: %w", err)
|
||||||
|
}
|
||||||
|
if err := g.SetLinuxRootPropagation("rshared"); err != nil {
|
||||||
|
return fmt.Errorf("failed to adjust rootfs propagation in OCI Spec: %w", err)
|
||||||
|
}
|
||||||
|
case "rslave":
|
||||||
|
if err := ensurePropagation(mnt.Source, "rshared", "rslave"); err != nil {
|
||||||
|
return fmt.Errorf("failed to adjust mounts in OCI Spec: %w", err)
|
||||||
|
}
|
||||||
|
rootProp := g.Config.Linux.RootfsPropagation
|
||||||
|
if rootProp != "rshared" && rootProp != "rslave" {
|
||||||
|
if err := g.SetLinuxRootPropagation("rslave"); err != nil {
|
||||||
|
return fmt.Errorf("failed to adjust rootfs propagation in OCI Spec: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.AddMount(mnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func nopFilter(m map[string]string) (map[string]string, error) {
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO: these could be added to the stock Spec generator...
|
||||||
|
//
|
||||||
|
|
||||||
|
// AddCreateRuntimeHook adds a hooks new CreateRuntime hooks.
|
||||||
|
func (g *Generator) AddCreateRuntimeHook(hook rspec.Hook) {
|
||||||
|
g.initConfigHooks()
|
||||||
|
g.Config.Hooks.CreateRuntime = append(g.Config.Hooks.CreateRuntime, hook)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddCreateContainerHook adds a hooks new CreateContainer hooks.
|
||||||
|
func (g *Generator) AddCreateContainerHook(hook rspec.Hook) {
|
||||||
|
g.initConfigHooks()
|
||||||
|
g.Config.Hooks.CreateContainer = append(g.Config.Hooks.CreateContainer, hook)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddStartContainerHook adds a hooks new StartContainer hooks.
|
||||||
|
func (g *Generator) AddStartContainerHook(hook rspec.Hook) {
|
||||||
|
g.initConfigHooks()
|
||||||
|
g.Config.Hooks.StartContainer = append(g.Config.Hooks.StartContainer, hook)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearLinuxIntelRdt clears RDT CLOS.
|
||||||
|
func (g *Generator) ClearLinuxIntelRdt() {
|
||||||
|
g.initConfigLinux()
|
||||||
|
g.Config.Linux.IntelRdt = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxIntelRdt sets RDT CLOS.
|
||||||
|
func (g *Generator) SetLinuxIntelRdt(rdt *rspec.LinuxIntelRdt) {
|
||||||
|
g.initConfigLinux()
|
||||||
|
g.Config.Linux.IntelRdt = rdt
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearLinuxResourcesBlockIO clears Block I/O settings.
|
||||||
|
func (g *Generator) ClearLinuxResourcesBlockIO() {
|
||||||
|
g.initConfigLinuxResources()
|
||||||
|
g.Config.Linux.Resources.BlockIO = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxResourcesBlockIO sets Block I/O settings.
|
||||||
|
func (g *Generator) SetLinuxResourcesBlockIO(blockIO *rspec.LinuxBlockIO) {
|
||||||
|
g.initConfigLinuxResources()
|
||||||
|
g.Config.Linux.Resources.BlockIO = blockIO
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Generator) initConfig() {
|
||||||
|
if g.Config == nil {
|
||||||
|
g.Config = &rspec.Spec{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Generator) initConfigHooks() {
|
||||||
|
g.initConfig()
|
||||||
|
if g.Config.Hooks == nil {
|
||||||
|
g.Config.Hooks = &rspec.Hooks{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Generator) initConfigLinux() {
|
||||||
|
g.initConfig()
|
||||||
|
if g.Config.Linux == nil {
|
||||||
|
g.Config.Linux = &rspec.Linux{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Generator) initConfigLinuxResources() {
|
||||||
|
g.initConfigLinux()
|
||||||
|
if g.Config.Linux.Resources == nil {
|
||||||
|
g.Config.Linux.Resources = &rspec.LinuxResources{}
|
||||||
|
}
|
||||||
|
}
|
78
vendor/github.com/containerd/nri/pkg/runtime-tools/generate/helpers_linux.go
generated
vendored
Normal file
78
vendor/github.com/containerd/nri/pkg/runtime-tools/generate/helpers_linux.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 generate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/moby/sys/mountinfo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getPropagation(path string) (string, error) {
|
||||||
|
var (
|
||||||
|
dir = filepath.Clean(path)
|
||||||
|
mnt *mountinfo.Info
|
||||||
|
)
|
||||||
|
|
||||||
|
mounts, err := mountinfo.GetMounts(mountinfo.ParentsFilter(dir))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if len(mounts) == 0 {
|
||||||
|
return "", fmt.Errorf("failed to get mount info for %q", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
maxLen := 0
|
||||||
|
for _, m := range mounts {
|
||||||
|
if l := len(m.Mountpoint); l > maxLen {
|
||||||
|
mnt = m
|
||||||
|
maxLen = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range strings.Split(mnt.Optional, " ") {
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(opt, "shared:"):
|
||||||
|
return "rshared", nil
|
||||||
|
case strings.HasPrefix(opt, "master:"):
|
||||||
|
return "rslave", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ensurePropagation(path string, accepted ...string) error {
|
||||||
|
prop, err := getPropagation(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range accepted {
|
||||||
|
if p == prop {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("path %q mount propagation is %q, not %q",
|
||||||
|
path, prop, strings.Join(accepted, " or "))
|
||||||
|
}
|
24
vendor/github.com/containerd/nri/pkg/runtime-tools/generate/helpers_other.go
generated
vendored
Normal file
24
vendor/github.com/containerd/nri/pkg/runtime-tools/generate/helpers_other.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//go:build !linux
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 generate
|
||||||
|
|
||||||
|
func ensurePropagation(path string, accepted ...string) error {
|
||||||
|
return nil
|
||||||
|
}
|
757
vendor/github.com/containerd/nri/pkg/stub/stub.go
generated
vendored
Normal file
757
vendor/github.com/containerd/nri/pkg/stub/stub.go
generated
vendored
Normal file
@ -0,0 +1,757 @@
|
|||||||
|
/*
|
||||||
|
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 stub
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
stdnet "net"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/nri/pkg/api"
|
||||||
|
nrilog "github.com/containerd/nri/pkg/log"
|
||||||
|
"github.com/containerd/nri/pkg/net"
|
||||||
|
"github.com/containerd/nri/pkg/net/multiplex"
|
||||||
|
"github.com/containerd/ttrpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Plugin can implement a number of interfaces related to Pod and Container
|
||||||
|
// lifecycle events. No any single such inteface is mandatory, therefore the
|
||||||
|
// Plugin interface itself is empty. Plugins are required to implement at
|
||||||
|
// least one of these interfaces and this is verified during stub creation.
|
||||||
|
// Trying to create a stub for a plugin violating this requirement will fail
|
||||||
|
// with and error.
|
||||||
|
type Plugin interface{}
|
||||||
|
|
||||||
|
// ConfigureInterface handles Configure API request.
|
||||||
|
type ConfigureInterface interface {
|
||||||
|
// Configure the plugin with the given NRI-supplied configuration.
|
||||||
|
// If a non-zero EventMask is returned, the plugin will be subscribed
|
||||||
|
// to the corresponding.
|
||||||
|
Configure(config, runtime, version string) (api.EventMask, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SynchronizeInterface handles Synchronize API requests.
|
||||||
|
type SynchronizeInterface interface {
|
||||||
|
// Synchronize the state of the plugin with the runtime.
|
||||||
|
// The plugin can request updates to containers in response.
|
||||||
|
Synchronize([]*api.PodSandbox, []*api.Container) ([]*api.ContainerUpdate, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShutdownInterface handles a Shutdown API request.
|
||||||
|
type ShutdownInterface interface {
|
||||||
|
// Shutdown notifies the plugin about the runtime shutting down.
|
||||||
|
Shutdown(*api.ShutdownRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunPodInterface handles RunPodSandbox API events.
|
||||||
|
type RunPodInterface interface {
|
||||||
|
// RunPodSandbox relays a RunPodSandbox event to the plugin.
|
||||||
|
RunPodSandbox(*api.PodSandbox) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopPodInterface handles StopPodSandbox API events.
|
||||||
|
type StopPodInterface interface {
|
||||||
|
// StopPodSandbox relays a StopPodSandbox event to the plugin.
|
||||||
|
StopPodSandbox(*api.PodSandbox) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemovePodInterface handles RemovePodSandbox API events.
|
||||||
|
type RemovePodInterface interface {
|
||||||
|
// RemovePodSandbox relays a RemovePodSandbox event to the plugin.
|
||||||
|
RemovePodSandbox(*api.PodSandbox) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateContainerInterface handles CreateContainer API requests.
|
||||||
|
type CreateContainerInterface interface {
|
||||||
|
// CreateContainer relays a CreateContainer request to the plugin.
|
||||||
|
// The plugin can request adjustments to the container being created
|
||||||
|
// and updates to other unstopped containers in response.
|
||||||
|
CreateContainer(*api.PodSandbox, *api.Container) (*api.ContainerAdjustment, []*api.ContainerUpdate, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartContainerInterface handles StartContainer API requests.
|
||||||
|
type StartContainerInterface interface {
|
||||||
|
// StartContainer relays a StartContainer event to the plugin.
|
||||||
|
StartContainer(*api.PodSandbox, *api.Container) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateContainerInterface handles UpdateContainer API requests.
|
||||||
|
type UpdateContainerInterface interface {
|
||||||
|
// UpdateContainer relays an UpdateContainer request to the plugin.
|
||||||
|
// The plugin can request updates both to the container being updated
|
||||||
|
// (which then supersedes the original update) and to other unstopped
|
||||||
|
// containers in response.
|
||||||
|
UpdateContainer(*api.PodSandbox, *api.Container) ([]*api.ContainerUpdate, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopContainerInterface handles StopContainer API requests.
|
||||||
|
type StopContainerInterface interface {
|
||||||
|
// StopContainer relays a StopContainer request to the plugin.
|
||||||
|
// The plugin can request updates to unstopped containers in response.
|
||||||
|
StopContainer(*api.PodSandbox, *api.Container) ([]*api.ContainerUpdate, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveContainerInterface handles RemoveContainer API events.
|
||||||
|
type RemoveContainerInterface interface {
|
||||||
|
// RemoveContainer relays a RemoveContainer event to the plugin.
|
||||||
|
RemoveContainer(*api.PodSandbox, *api.Container) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostCreateContainerInterface handles PostCreateContainer API events.
|
||||||
|
type PostCreateContainerInterface interface {
|
||||||
|
// PostCreateContainer relays a PostCreateContainer event to the plugin.
|
||||||
|
PostCreateContainer(*api.PodSandbox, *api.Container) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostStartContainerInterface handles PostStartContainer API events.
|
||||||
|
type PostStartContainerInterface interface {
|
||||||
|
// PostStartContainer relays a PostStartContainer event to the plugin.
|
||||||
|
PostStartContainer(*api.PodSandbox, *api.Container) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostUpdateContainerInterface handles PostUpdateContainer API events.
|
||||||
|
type PostUpdateContainerInterface interface {
|
||||||
|
// PostUpdateContainer relays a PostUpdateContainer event to the plugin.
|
||||||
|
PostUpdateContainer(*api.PodSandbox, *api.Container) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stub is the interface the stub provides for the plugin implementation.
|
||||||
|
type Stub interface {
|
||||||
|
// Run the plugin. Starts the plugin then waits for an error or the plugin to stop
|
||||||
|
Run(context.Context) error
|
||||||
|
// Start the plugin.
|
||||||
|
Start(context.Context) error
|
||||||
|
// Stop the plugin.
|
||||||
|
Stop()
|
||||||
|
// Wait for the plugin to stop.
|
||||||
|
Wait()
|
||||||
|
|
||||||
|
// UpdateContainer requests unsolicited updates to containers.
|
||||||
|
UpdateContainers([]*api.ContainerUpdate) ([]*api.ContainerUpdate, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Plugin registration timeout.
|
||||||
|
registrationTimeout = 2 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Logger for messages generated internally by the stub itself.
|
||||||
|
log = nrilog.Get()
|
||||||
|
|
||||||
|
// Used instead of a nil Context in logging.
|
||||||
|
noCtx = context.TODO()
|
||||||
|
)
|
||||||
|
|
||||||
|
// EventMask holds a mask of events for plugin subscription.
|
||||||
|
type EventMask = api.EventMask
|
||||||
|
|
||||||
|
// Option to apply to a plugin during its creation.
|
||||||
|
type Option func(*stub) error
|
||||||
|
|
||||||
|
// WithOnClose sets a notification function to call if the ttRPC connection goes down.
|
||||||
|
func WithOnClose(onClose func()) Option {
|
||||||
|
return func(s *stub) error {
|
||||||
|
s.onClose = onClose
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPluginName sets the name to use in plugin registration.
|
||||||
|
func WithPluginName(name string) Option {
|
||||||
|
return func(s *stub) error {
|
||||||
|
if s.name != "" {
|
||||||
|
return fmt.Errorf("plugin name already set (%q)", s.name)
|
||||||
|
}
|
||||||
|
s.name = name
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPluginIdx sets the index to use in plugin registration.
|
||||||
|
func WithPluginIdx(idx string) Option {
|
||||||
|
return func(s *stub) error {
|
||||||
|
if s.idx != "" {
|
||||||
|
return fmt.Errorf("plugin ID already set (%q)", s.idx)
|
||||||
|
}
|
||||||
|
s.idx = idx
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSocketPath sets the NRI socket path to connect to.
|
||||||
|
func WithSocketPath(path string) Option {
|
||||||
|
return func(s *stub) error {
|
||||||
|
s.socketPath = path
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithConnection sets an existing NRI connection to use.
|
||||||
|
func WithConnection(conn stdnet.Conn) Option {
|
||||||
|
return func(s *stub) error {
|
||||||
|
s.conn = conn
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDialer sets the dialer to use.
|
||||||
|
func WithDialer(d func(string) (stdnet.Conn, error)) Option {
|
||||||
|
return func(s *stub) error {
|
||||||
|
s.dialer = d
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stub implements Stub.
|
||||||
|
type stub struct {
|
||||||
|
sync.Mutex
|
||||||
|
plugin interface{}
|
||||||
|
handlers handlers
|
||||||
|
events api.EventMask
|
||||||
|
name string
|
||||||
|
idx string
|
||||||
|
socketPath string
|
||||||
|
dialer func(string) (stdnet.Conn, error)
|
||||||
|
conn stdnet.Conn
|
||||||
|
onClose func()
|
||||||
|
rpcm multiplex.Mux
|
||||||
|
rpcl stdnet.Listener
|
||||||
|
rpcs *ttrpc.Server
|
||||||
|
rpcc *ttrpc.Client
|
||||||
|
runtime api.RuntimeService
|
||||||
|
closeOnce sync.Once
|
||||||
|
started bool
|
||||||
|
doneC chan struct{}
|
||||||
|
srvErrC chan error
|
||||||
|
cfgErrC chan error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handlers for NRI plugin event and request.
|
||||||
|
type handlers struct {
|
||||||
|
Configure func(string, string, string) (api.EventMask, error)
|
||||||
|
Synchronize func([]*api.PodSandbox, []*api.Container) ([]*api.ContainerUpdate, error)
|
||||||
|
Shutdown func(*api.ShutdownRequest)
|
||||||
|
RunPodSandbox func(*api.PodSandbox) error
|
||||||
|
StopPodSandbox func(*api.PodSandbox) error
|
||||||
|
RemovePodSandbox func(*api.PodSandbox) error
|
||||||
|
CreateContainer func(*api.PodSandbox, *api.Container) (*api.ContainerAdjustment, []*api.ContainerUpdate, error)
|
||||||
|
StartContainer func(*api.PodSandbox, *api.Container) error
|
||||||
|
UpdateContainer func(*api.PodSandbox, *api.Container) ([]*api.ContainerUpdate, error)
|
||||||
|
StopContainer func(*api.PodSandbox, *api.Container) ([]*api.ContainerUpdate, error)
|
||||||
|
RemoveContainer func(*api.PodSandbox, *api.Container) error
|
||||||
|
PostCreateContainer func(*api.PodSandbox, *api.Container) error
|
||||||
|
PostStartContainer func(*api.PodSandbox, *api.Container) error
|
||||||
|
PostUpdateContainer func(*api.PodSandbox, *api.Container) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a stub with the given plugin and options.
|
||||||
|
func New(p interface{}, opts ...Option) (Stub, error) {
|
||||||
|
stub := &stub{
|
||||||
|
plugin: p,
|
||||||
|
name: os.Getenv(api.PluginNameEnvVar),
|
||||||
|
idx: os.Getenv(api.PluginIdxEnvVar),
|
||||||
|
socketPath: api.DefaultSocketPath,
|
||||||
|
dialer: func(p string) (stdnet.Conn, error) { return stdnet.Dial("unix", p) },
|
||||||
|
doneC: make(chan struct{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o := range opts {
|
||||||
|
if err := o(stub); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := stub.setupHandlers(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := stub.getIdentity(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof(noCtx, "Created plugin %s (%s, handles %s)", stub.Name(),
|
||||||
|
filepath.Base(os.Args[0]), stub.events.PrettyString())
|
||||||
|
|
||||||
|
return stub, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start event processing, register to NRI and wait for getting configured.
|
||||||
|
func (stub *stub) Start(ctx context.Context) (retErr error) {
|
||||||
|
stub.Lock()
|
||||||
|
defer stub.Unlock()
|
||||||
|
|
||||||
|
if stub.started {
|
||||||
|
return fmt.Errorf("stub already started")
|
||||||
|
}
|
||||||
|
stub.started = true
|
||||||
|
|
||||||
|
err := stub.connect()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcm := multiplex.Multiplex(stub.conn)
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
rpcm.Close()
|
||||||
|
stub.rpcm = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
rpcl, err := rpcm.Listen(multiplex.PluginServiceConn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
rpcl.Close()
|
||||||
|
stub.rpcl = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
rpcs, err := ttrpc.NewServer()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create ttrpc server: %w", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
rpcs.Close()
|
||||||
|
stub.rpcs = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
api.RegisterPluginService(rpcs, stub)
|
||||||
|
|
||||||
|
conn, err := rpcm.Open(multiplex.RuntimeServiceConn)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to multiplex ttrpc client connection: %w", err)
|
||||||
|
}
|
||||||
|
rpcc := ttrpc.NewClient(conn,
|
||||||
|
ttrpc.WithOnClose(func() {
|
||||||
|
stub.connClosed()
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
rpcc.Close()
|
||||||
|
stub.rpcc = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
stub.srvErrC = make(chan error, 1)
|
||||||
|
stub.cfgErrC = make(chan error, 1)
|
||||||
|
go func() {
|
||||||
|
stub.srvErrC <- rpcs.Serve(ctx, rpcl)
|
||||||
|
close(stub.doneC)
|
||||||
|
}()
|
||||||
|
|
||||||
|
stub.rpcm = rpcm
|
||||||
|
stub.rpcl = rpcl
|
||||||
|
stub.rpcs = rpcs
|
||||||
|
stub.rpcc = rpcc
|
||||||
|
|
||||||
|
stub.runtime = api.NewRuntimeClient(rpcc)
|
||||||
|
|
||||||
|
if err = stub.register(ctx); err != nil {
|
||||||
|
stub.close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = <-stub.cfgErrC; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof(ctx, "Started plugin %s...", stub.Name())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the plugin.
|
||||||
|
func (stub *stub) Stop() {
|
||||||
|
log.Infof(noCtx, "Stopping plugin %s...", stub.Name())
|
||||||
|
|
||||||
|
stub.Lock()
|
||||||
|
defer stub.Unlock()
|
||||||
|
stub.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (stub *stub) close() {
|
||||||
|
stub.closeOnce.Do(func() {
|
||||||
|
if stub.rpcl != nil {
|
||||||
|
stub.rpcl.Close()
|
||||||
|
}
|
||||||
|
if stub.rpcs != nil {
|
||||||
|
stub.rpcs.Close()
|
||||||
|
}
|
||||||
|
if stub.rpcc != nil {
|
||||||
|
stub.rpcc.Close()
|
||||||
|
}
|
||||||
|
if stub.rpcm != nil {
|
||||||
|
stub.rpcm.Close()
|
||||||
|
}
|
||||||
|
if stub.srvErrC != nil {
|
||||||
|
<-stub.doneC
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the plugin. Start event processing then wait for an error or getting stopped.
|
||||||
|
func (stub *stub) Run(ctx context.Context) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if err = stub.Start(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = <-stub.srvErrC
|
||||||
|
if err == ttrpc.ErrServerClosed {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the plugin to stop.
|
||||||
|
func (stub *stub) Wait() {
|
||||||
|
stub.Lock()
|
||||||
|
if stub.srvErrC == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
stub.Unlock()
|
||||||
|
<-stub.doneC
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the full indexed name of the plugin.
|
||||||
|
func (stub *stub) Name() string {
|
||||||
|
return stub.idx + "-" + stub.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect the plugin to NRI.
|
||||||
|
func (stub *stub) connect() error {
|
||||||
|
if stub.conn != nil {
|
||||||
|
log.Infof(noCtx, "Using given plugin connection...")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if env := os.Getenv(api.PluginSocketEnvVar); env != "" {
|
||||||
|
log.Infof(noCtx, "Using connection %q from environment...", env)
|
||||||
|
|
||||||
|
fd, err := strconv.Atoi(env)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid socket in environment (%s=%q): %w",
|
||||||
|
api.PluginSocketEnvVar, env, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stub.conn, err = net.NewFdConn(fd)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid socket (%d) in environment: %w", fd, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := stub.dialer(stub.socketPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to connect to NRI service: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stub.conn = conn
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the plugin with NRI.
|
||||||
|
func (stub *stub) register(ctx context.Context) error {
|
||||||
|
log.Infof(ctx, "Registering plugin %s...", stub.Name())
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, registrationTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
req := &api.RegisterPluginRequest{
|
||||||
|
PluginName: stub.name,
|
||||||
|
PluginIdx: stub.idx,
|
||||||
|
}
|
||||||
|
if _, err := stub.runtime.RegisterPlugin(ctx, req); err != nil {
|
||||||
|
return fmt.Errorf("failed to register with NRI/Runtime: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle a lost connection.
|
||||||
|
func (stub *stub) connClosed() {
|
||||||
|
stub.close()
|
||||||
|
if stub.onClose != nil {
|
||||||
|
stub.onClose()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// plugin event and request handlers
|
||||||
|
//
|
||||||
|
|
||||||
|
// UpdateContainers requests unsolicited updates to containers.
|
||||||
|
func (stub *stub) UpdateContainers(update []*api.ContainerUpdate) ([]*api.ContainerUpdate, error) {
|
||||||
|
ctx := context.Background()
|
||||||
|
req := &api.UpdateContainersRequest{
|
||||||
|
Update: update,
|
||||||
|
}
|
||||||
|
rpl, err := stub.runtime.UpdateContainers(ctx, req)
|
||||||
|
if rpl != nil {
|
||||||
|
return rpl.Failed, err
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure the plugin.
|
||||||
|
func (stub *stub) Configure(ctx context.Context, req *api.ConfigureRequest) (rpl *api.ConfigureResponse, retErr error) {
|
||||||
|
var (
|
||||||
|
events api.EventMask
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
log.Infof(ctx, "Configuring plugin %s for runtime %s/%s...", stub.Name(),
|
||||||
|
req.RuntimeName, req.RuntimeVersion)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
stub.cfgErrC <- retErr
|
||||||
|
}()
|
||||||
|
|
||||||
|
if handler := stub.handlers.Configure; handler == nil {
|
||||||
|
events = stub.events
|
||||||
|
} else {
|
||||||
|
events, err = handler(req.Config, req.RuntimeName, req.RuntimeVersion)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf(ctx, "Plugin configuration failed: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if events == 0 {
|
||||||
|
events = stub.events
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only allow plugins to subscribe to events they can handle.
|
||||||
|
if extra := events & ^stub.events; extra != 0 {
|
||||||
|
log.Errorf(ctx, "Plugin subscribed for unhandled events %s (0x%x)",
|
||||||
|
extra.PrettyString(), extra)
|
||||||
|
return nil, fmt.Errorf("internal error: unhandled events %s (0x%x)",
|
||||||
|
extra.PrettyString(), extra)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof(ctx, "Subscribing plugin %s (%s) for events %s", stub.Name(),
|
||||||
|
filepath.Base(os.Args[0]), events.PrettyString())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.ConfigureResponse{
|
||||||
|
Events: int32(events),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Synchronize the state of the plugin with the runtime.
|
||||||
|
func (stub *stub) Synchronize(ctx context.Context, req *api.SynchronizeRequest) (*api.SynchronizeResponse, error) {
|
||||||
|
handler := stub.handlers.Synchronize
|
||||||
|
if handler == nil {
|
||||||
|
return &api.SynchronizeResponse{}, nil
|
||||||
|
}
|
||||||
|
update, err := handler(req.Pods, req.Containers)
|
||||||
|
return &api.SynchronizeResponse{
|
||||||
|
Update: update,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown the plugin.
|
||||||
|
func (stub *stub) Shutdown(ctx context.Context, req *api.ShutdownRequest) (*api.ShutdownResponse, error) {
|
||||||
|
handler := stub.handlers.Shutdown
|
||||||
|
if handler != nil {
|
||||||
|
handler(req)
|
||||||
|
}
|
||||||
|
return &api.ShutdownResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateContainer request handler.
|
||||||
|
func (stub *stub) CreateContainer(ctx context.Context, req *api.CreateContainerRequest) (*api.CreateContainerResponse, error) {
|
||||||
|
handler := stub.handlers.CreateContainer
|
||||||
|
if handler == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
adjust, update, err := handler(req.Pod, req.Container)
|
||||||
|
return &api.CreateContainerResponse{
|
||||||
|
Adjust: adjust,
|
||||||
|
Update: update,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateContainer request handler.
|
||||||
|
func (stub *stub) UpdateContainer(ctx context.Context, req *api.UpdateContainerRequest) (*api.UpdateContainerResponse, error) {
|
||||||
|
handler := stub.handlers.UpdateContainer
|
||||||
|
if handler == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
update, err := handler(req.Pod, req.Container)
|
||||||
|
return &api.UpdateContainerResponse{
|
||||||
|
Update: update,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopContainer request handler.
|
||||||
|
func (stub *stub) StopContainer(ctx context.Context, req *api.StopContainerRequest) (*api.StopContainerResponse, error) {
|
||||||
|
handler := stub.handlers.StopContainer
|
||||||
|
if handler == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
update, err := handler(req.Pod, req.Container)
|
||||||
|
return &api.StopContainerResponse{
|
||||||
|
Update: update,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StateChange event handler.
|
||||||
|
func (stub *stub) StateChange(ctx context.Context, evt *api.StateChangeEvent) (*api.Empty, error) {
|
||||||
|
var err error
|
||||||
|
switch evt.Event {
|
||||||
|
case api.Event_RUN_POD_SANDBOX:
|
||||||
|
if handler := stub.handlers.RunPodSandbox; handler != nil {
|
||||||
|
err = handler(evt.Pod)
|
||||||
|
}
|
||||||
|
case api.Event_STOP_POD_SANDBOX:
|
||||||
|
if handler := stub.handlers.StopPodSandbox; handler != nil {
|
||||||
|
err = handler(evt.Pod)
|
||||||
|
}
|
||||||
|
case api.Event_REMOVE_POD_SANDBOX:
|
||||||
|
if handler := stub.handlers.RemovePodSandbox; handler != nil {
|
||||||
|
err = handler(evt.Pod)
|
||||||
|
}
|
||||||
|
case api.Event_POST_CREATE_CONTAINER:
|
||||||
|
if handler := stub.handlers.PostCreateContainer; handler != nil {
|
||||||
|
err = handler(evt.Pod, evt.Container)
|
||||||
|
}
|
||||||
|
case api.Event_START_CONTAINER:
|
||||||
|
if handler := stub.handlers.StartContainer; handler != nil {
|
||||||
|
err = handler(evt.Pod, evt.Container)
|
||||||
|
}
|
||||||
|
case api.Event_POST_START_CONTAINER:
|
||||||
|
if handler := stub.handlers.PostStartContainer; handler != nil {
|
||||||
|
err = handler(evt.Pod, evt.Container)
|
||||||
|
}
|
||||||
|
case api.Event_POST_UPDATE_CONTAINER:
|
||||||
|
if handler := stub.handlers.PostUpdateContainer; handler != nil {
|
||||||
|
err = handler(evt.Pod, evt.Container)
|
||||||
|
}
|
||||||
|
case api.Event_REMOVE_CONTAINER:
|
||||||
|
if handler := stub.handlers.RemoveContainer; handler != nil {
|
||||||
|
err = handler(evt.Pod, evt.Container)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.StateChangeResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// getIdentity gets plugin index and name from the binary if those are unset.
|
||||||
|
func (stub *stub) getIdentity() error {
|
||||||
|
if stub.idx != "" && stub.name != "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if stub.idx != "" {
|
||||||
|
stub.name = filepath.Base(os.Args[0])
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
idx, name, err := api.ParsePluginName(filepath.Base(os.Args[0]))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
stub.name = name
|
||||||
|
stub.idx = idx
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up event handlers and the subscription mask for the plugin.
|
||||||
|
func (stub *stub) setupHandlers() error {
|
||||||
|
if plugin, ok := stub.plugin.(ConfigureInterface); ok {
|
||||||
|
stub.handlers.Configure = plugin.Configure
|
||||||
|
}
|
||||||
|
if plugin, ok := stub.plugin.(SynchronizeInterface); ok {
|
||||||
|
stub.handlers.Synchronize = plugin.Synchronize
|
||||||
|
}
|
||||||
|
if plugin, ok := stub.plugin.(ShutdownInterface); ok {
|
||||||
|
stub.handlers.Shutdown = plugin.Shutdown
|
||||||
|
}
|
||||||
|
|
||||||
|
if plugin, ok := stub.plugin.(RunPodInterface); ok {
|
||||||
|
stub.handlers.RunPodSandbox = plugin.RunPodSandbox
|
||||||
|
stub.events.Set(api.Event_RUN_POD_SANDBOX)
|
||||||
|
}
|
||||||
|
if plugin, ok := stub.plugin.(StopPodInterface); ok {
|
||||||
|
stub.handlers.StopPodSandbox = plugin.StopPodSandbox
|
||||||
|
stub.events.Set(api.Event_STOP_POD_SANDBOX)
|
||||||
|
}
|
||||||
|
if plugin, ok := stub.plugin.(RemovePodInterface); ok {
|
||||||
|
stub.handlers.RemovePodSandbox = plugin.RemovePodSandbox
|
||||||
|
stub.events.Set(api.Event_REMOVE_POD_SANDBOX)
|
||||||
|
}
|
||||||
|
if plugin, ok := stub.plugin.(CreateContainerInterface); ok {
|
||||||
|
stub.handlers.CreateContainer = plugin.CreateContainer
|
||||||
|
stub.events.Set(api.Event_CREATE_CONTAINER)
|
||||||
|
}
|
||||||
|
if plugin, ok := stub.plugin.(StartContainerInterface); ok {
|
||||||
|
stub.handlers.StartContainer = plugin.StartContainer
|
||||||
|
stub.events.Set(api.Event_START_CONTAINER)
|
||||||
|
}
|
||||||
|
if plugin, ok := stub.plugin.(UpdateContainerInterface); ok {
|
||||||
|
stub.handlers.UpdateContainer = plugin.UpdateContainer
|
||||||
|
stub.events.Set(api.Event_UPDATE_CONTAINER)
|
||||||
|
}
|
||||||
|
if plugin, ok := stub.plugin.(StopContainerInterface); ok {
|
||||||
|
stub.handlers.StopContainer = plugin.StopContainer
|
||||||
|
stub.events.Set(api.Event_STOP_CONTAINER)
|
||||||
|
}
|
||||||
|
if plugin, ok := stub.plugin.(RemoveContainerInterface); ok {
|
||||||
|
stub.handlers.RemoveContainer = plugin.RemoveContainer
|
||||||
|
stub.events.Set(api.Event_REMOVE_CONTAINER)
|
||||||
|
}
|
||||||
|
if plugin, ok := stub.plugin.(PostCreateContainerInterface); ok {
|
||||||
|
stub.handlers.PostCreateContainer = plugin.PostCreateContainer
|
||||||
|
stub.events.Set(api.Event_POST_CREATE_CONTAINER)
|
||||||
|
}
|
||||||
|
if plugin, ok := stub.plugin.(PostStartContainerInterface); ok {
|
||||||
|
stub.handlers.PostStartContainer = plugin.PostStartContainer
|
||||||
|
stub.events.Set(api.Event_POST_START_CONTAINER)
|
||||||
|
}
|
||||||
|
if plugin, ok := stub.plugin.(PostUpdateContainerInterface); ok {
|
||||||
|
stub.handlers.PostUpdateContainer = plugin.PostUpdateContainer
|
||||||
|
stub.events.Set(api.Event_POST_UPDATE_CONTAINER)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stub.events == 0 {
|
||||||
|
return fmt.Errorf("internal error: plugin %T does not implement any NRI request handlers",
|
||||||
|
stub.plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
3
vendor/github.com/containerd/nri/types/v1/types.go
generated
vendored
3
vendor/github.com/containerd/nri/types/v1/types.go
generated
vendored
@ -18,8 +18,7 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Plugin type and configuration
|
// Plugin type and configuration
|
||||||
|
99
vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
generated
vendored
99
vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
generated
vendored
@ -12,10 +12,12 @@ type Spec struct {
|
|||||||
Root *Root `json:"root,omitempty"`
|
Root *Root `json:"root,omitempty"`
|
||||||
// Hostname configures the container's hostname.
|
// Hostname configures the container's hostname.
|
||||||
Hostname string `json:"hostname,omitempty"`
|
Hostname string `json:"hostname,omitempty"`
|
||||||
|
// Domainname configures the container's domainname.
|
||||||
|
Domainname string `json:"domainname,omitempty"`
|
||||||
// Mounts configures additional mounts (on top of Root).
|
// Mounts configures additional mounts (on top of Root).
|
||||||
Mounts []Mount `json:"mounts,omitempty"`
|
Mounts []Mount `json:"mounts,omitempty"`
|
||||||
// Hooks configures callbacks for container lifecycle events.
|
// Hooks configures callbacks for container lifecycle events.
|
||||||
Hooks *Hooks `json:"hooks,omitempty" platform:"linux,solaris"`
|
Hooks *Hooks `json:"hooks,omitempty" platform:"linux,solaris,zos"`
|
||||||
// Annotations contains arbitrary metadata for the container.
|
// Annotations contains arbitrary metadata for the container.
|
||||||
Annotations map[string]string `json:"annotations,omitempty"`
|
Annotations map[string]string `json:"annotations,omitempty"`
|
||||||
|
|
||||||
@ -27,6 +29,8 @@ type Spec struct {
|
|||||||
Windows *Windows `json:"windows,omitempty" platform:"windows"`
|
Windows *Windows `json:"windows,omitempty" platform:"windows"`
|
||||||
// VM specifies configuration for virtual-machine-based containers.
|
// VM specifies configuration for virtual-machine-based containers.
|
||||||
VM *VM `json:"vm,omitempty" platform:"vm"`
|
VM *VM `json:"vm,omitempty" platform:"vm"`
|
||||||
|
// ZOS is platform-specific configuration for z/OS based containers.
|
||||||
|
ZOS *ZOS `json:"zos,omitempty" platform:"zos"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process contains information to start a specific application inside the container.
|
// Process contains information to start a specific application inside the container.
|
||||||
@ -49,7 +53,7 @@ type Process struct {
|
|||||||
// Capabilities are Linux capabilities that are kept for the process.
|
// Capabilities are Linux capabilities that are kept for the process.
|
||||||
Capabilities *LinuxCapabilities `json:"capabilities,omitempty" platform:"linux"`
|
Capabilities *LinuxCapabilities `json:"capabilities,omitempty" platform:"linux"`
|
||||||
// Rlimits specifies rlimit options to apply to the process.
|
// Rlimits specifies rlimit options to apply to the process.
|
||||||
Rlimits []POSIXRlimit `json:"rlimits,omitempty" platform:"linux,solaris"`
|
Rlimits []POSIXRlimit `json:"rlimits,omitempty" platform:"linux,solaris,zos"`
|
||||||
// NoNewPrivileges controls whether additional privileges could be gained by processes in the container.
|
// NoNewPrivileges controls whether additional privileges could be gained by processes in the container.
|
||||||
NoNewPrivileges bool `json:"noNewPrivileges,omitempty" platform:"linux"`
|
NoNewPrivileges bool `json:"noNewPrivileges,omitempty" platform:"linux"`
|
||||||
// ApparmorProfile specifies the apparmor profile for the container.
|
// ApparmorProfile specifies the apparmor profile for the container.
|
||||||
@ -86,11 +90,11 @@ type Box struct {
|
|||||||
// User specifies specific user (and group) information for the container process.
|
// User specifies specific user (and group) information for the container process.
|
||||||
type User struct {
|
type User struct {
|
||||||
// UID is the user id.
|
// UID is the user id.
|
||||||
UID uint32 `json:"uid" platform:"linux,solaris"`
|
UID uint32 `json:"uid" platform:"linux,solaris,zos"`
|
||||||
// GID is the group id.
|
// GID is the group id.
|
||||||
GID uint32 `json:"gid" platform:"linux,solaris"`
|
GID uint32 `json:"gid" platform:"linux,solaris,zos"`
|
||||||
// Umask is the umask for the init process.
|
// Umask is the umask for the init process.
|
||||||
Umask *uint32 `json:"umask,omitempty" platform:"linux,solaris"`
|
Umask *uint32 `json:"umask,omitempty" platform:"linux,solaris,zos"`
|
||||||
// AdditionalGids are additional group ids set for the container's process.
|
// AdditionalGids are additional group ids set for the container's process.
|
||||||
AdditionalGids []uint32 `json:"additionalGids,omitempty" platform:"linux,solaris"`
|
AdditionalGids []uint32 `json:"additionalGids,omitempty" platform:"linux,solaris"`
|
||||||
// Username is the user name.
|
// Username is the user name.
|
||||||
@ -110,11 +114,16 @@ type Mount struct {
|
|||||||
// Destination is the absolute path where the mount will be placed in the container.
|
// Destination is the absolute path where the mount will be placed in the container.
|
||||||
Destination string `json:"destination"`
|
Destination string `json:"destination"`
|
||||||
// Type specifies the mount kind.
|
// Type specifies the mount kind.
|
||||||
Type string `json:"type,omitempty" platform:"linux,solaris"`
|
Type string `json:"type,omitempty" platform:"linux,solaris,zos"`
|
||||||
// Source specifies the source path of the mount.
|
// Source specifies the source path of the mount.
|
||||||
Source string `json:"source,omitempty"`
|
Source string `json:"source,omitempty"`
|
||||||
// Options are fstab style mount options.
|
// Options are fstab style mount options.
|
||||||
Options []string `json:"options,omitempty"`
|
Options []string `json:"options,omitempty"`
|
||||||
|
|
||||||
|
// UID/GID mappings used for changing file owners w/o calling chown, fs should support it.
|
||||||
|
// Every mount point could have its own mapping.
|
||||||
|
UIDMappings []LinuxIDMapping `json:"uidMappings,omitempty" platform:"linux"`
|
||||||
|
GIDMappings []LinuxIDMapping `json:"gidMappings,omitempty" platform:"linux"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook specifies a command that is run at a particular event in the lifecycle of a container
|
// Hook specifies a command that is run at a particular event in the lifecycle of a container
|
||||||
@ -178,7 +187,7 @@ type Linux struct {
|
|||||||
// MountLabel specifies the selinux context for the mounts in the container.
|
// MountLabel specifies the selinux context for the mounts in the container.
|
||||||
MountLabel string `json:"mountLabel,omitempty"`
|
MountLabel string `json:"mountLabel,omitempty"`
|
||||||
// IntelRdt contains Intel Resource Director Technology (RDT) information for
|
// IntelRdt contains Intel Resource Director Technology (RDT) information for
|
||||||
// handling resource constraints (e.g., L3 cache, memory bandwidth) for the container
|
// handling resource constraints and monitoring metrics (e.g., L3 cache, memory bandwidth) for the container
|
||||||
IntelRdt *LinuxIntelRdt `json:"intelRdt,omitempty"`
|
IntelRdt *LinuxIntelRdt `json:"intelRdt,omitempty"`
|
||||||
// Personality contains configuration for the Linux personality syscall
|
// Personality contains configuration for the Linux personality syscall
|
||||||
Personality *LinuxPersonality `json:"personality,omitempty"`
|
Personality *LinuxPersonality `json:"personality,omitempty"`
|
||||||
@ -250,8 +259,8 @@ type LinuxInterfacePriority struct {
|
|||||||
Priority uint32 `json:"priority"`
|
Priority uint32 `json:"priority"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// linuxBlockIODevice holds major:minor format supported in blkio cgroup
|
// LinuxBlockIODevice holds major:minor format supported in blkio cgroup
|
||||||
type linuxBlockIODevice struct {
|
type LinuxBlockIODevice struct {
|
||||||
// Major is the device's major number.
|
// Major is the device's major number.
|
||||||
Major int64 `json:"major"`
|
Major int64 `json:"major"`
|
||||||
// Minor is the device's minor number.
|
// Minor is the device's minor number.
|
||||||
@ -260,7 +269,7 @@ type linuxBlockIODevice struct {
|
|||||||
|
|
||||||
// LinuxWeightDevice struct holds a `major:minor weight` pair for weightDevice
|
// LinuxWeightDevice struct holds a `major:minor weight` pair for weightDevice
|
||||||
type LinuxWeightDevice struct {
|
type LinuxWeightDevice struct {
|
||||||
linuxBlockIODevice
|
LinuxBlockIODevice
|
||||||
// Weight is the bandwidth rate for the device.
|
// Weight is the bandwidth rate for the device.
|
||||||
Weight *uint16 `json:"weight,omitempty"`
|
Weight *uint16 `json:"weight,omitempty"`
|
||||||
// LeafWeight is the bandwidth rate for the device while competing with the cgroup's child cgroups, CFQ scheduler only
|
// LeafWeight is the bandwidth rate for the device while competing with the cgroup's child cgroups, CFQ scheduler only
|
||||||
@ -269,7 +278,7 @@ type LinuxWeightDevice struct {
|
|||||||
|
|
||||||
// LinuxThrottleDevice struct holds a `major:minor rate_per_second` pair
|
// LinuxThrottleDevice struct holds a `major:minor rate_per_second` pair
|
||||||
type LinuxThrottleDevice struct {
|
type LinuxThrottleDevice struct {
|
||||||
linuxBlockIODevice
|
LinuxBlockIODevice
|
||||||
// Rate is the IO rate limit per cgroup per device
|
// Rate is the IO rate limit per cgroup per device
|
||||||
Rate uint64 `json:"rate"`
|
Rate uint64 `json:"rate"`
|
||||||
}
|
}
|
||||||
@ -328,6 +337,8 @@ type LinuxCPU struct {
|
|||||||
Cpus string `json:"cpus,omitempty"`
|
Cpus string `json:"cpus,omitempty"`
|
||||||
// List of memory nodes in the cpuset. Default is to use any available memory node.
|
// List of memory nodes in the cpuset. Default is to use any available memory node.
|
||||||
Mems string `json:"mems,omitempty"`
|
Mems string `json:"mems,omitempty"`
|
||||||
|
// cgroups are configured with minimum weight, 0: default behavior, 1: SCHED_IDLE.
|
||||||
|
Idle *int64 `json:"idle,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinuxPids for Linux cgroup 'pids' resource management (Linux 4.3)
|
// LinuxPids for Linux cgroup 'pids' resource management (Linux 4.3)
|
||||||
@ -522,11 +533,21 @@ type WindowsMemoryResources struct {
|
|||||||
|
|
||||||
// WindowsCPUResources contains CPU resource management settings.
|
// WindowsCPUResources contains CPU resource management settings.
|
||||||
type WindowsCPUResources struct {
|
type WindowsCPUResources struct {
|
||||||
// Number of CPUs available to the container.
|
// Count is the number of CPUs available to the container. It represents the
|
||||||
|
// fraction of the configured processor `count` in a container in relation
|
||||||
|
// to the processors available in the host. The fraction ultimately
|
||||||
|
// determines the portion of processor cycles that the threads in a
|
||||||
|
// container can use during each scheduling interval, as the number of
|
||||||
|
// cycles per 10,000 cycles.
|
||||||
Count *uint64 `json:"count,omitempty"`
|
Count *uint64 `json:"count,omitempty"`
|
||||||
// CPU shares (relative weight to other containers with cpu shares).
|
// Shares limits the share of processor time given to the container relative
|
||||||
|
// to other workloads on the processor. The processor `shares` (`weight` at
|
||||||
|
// the platform level) is a value between 0 and 10000.
|
||||||
Shares *uint16 `json:"shares,omitempty"`
|
Shares *uint16 `json:"shares,omitempty"`
|
||||||
// Specifies the portion of processor cycles that this container can use as a percentage times 100.
|
// Maximum determines the portion of processor cycles that the threads in a
|
||||||
|
// container can use during each scheduling interval, as the number of
|
||||||
|
// cycles per 10,000 cycles. Set processor `maximum` to a percentage times
|
||||||
|
// 100.
|
||||||
Maximum *uint16 `json:"maximum,omitempty"`
|
Maximum *uint16 `json:"maximum,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,6 +634,19 @@ type Arch string
|
|||||||
// LinuxSeccompFlag is a flag to pass to seccomp(2).
|
// LinuxSeccompFlag is a flag to pass to seccomp(2).
|
||||||
type LinuxSeccompFlag string
|
type LinuxSeccompFlag string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// LinuxSeccompFlagLog is a seccomp flag to request all returned
|
||||||
|
// actions except SECCOMP_RET_ALLOW to be logged. An administrator may
|
||||||
|
// override this filter flag by preventing specific actions from being
|
||||||
|
// logged via the /proc/sys/kernel/seccomp/actions_logged file. (since
|
||||||
|
// Linux 4.14)
|
||||||
|
LinuxSeccompFlagLog LinuxSeccompFlag = "SECCOMP_FILTER_FLAG_LOG"
|
||||||
|
|
||||||
|
// LinuxSeccompFlagSpecAllow can be used to disable Speculative Store
|
||||||
|
// Bypass mitigation. (since Linux 4.17)
|
||||||
|
LinuxSeccompFlagSpecAllow LinuxSeccompFlag = "SECCOMP_FILTER_FLAG_SPEC_ALLOW"
|
||||||
|
)
|
||||||
|
|
||||||
// Additional architectures permitted to be used for system calls
|
// Additional architectures permitted to be used for system calls
|
||||||
// By default only the native architecture of the kernel is permitted
|
// By default only the native architecture of the kernel is permitted
|
||||||
const (
|
const (
|
||||||
@ -683,8 +717,9 @@ type LinuxSyscall struct {
|
|||||||
Args []LinuxSeccompArg `json:"args,omitempty"`
|
Args []LinuxSeccompArg `json:"args,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinuxIntelRdt has container runtime resource constraints for Intel RDT
|
// LinuxIntelRdt has container runtime resource constraints for Intel RDT CAT and MBA
|
||||||
// CAT and MBA features which introduced in Linux 4.10 and 4.12 kernel
|
// features and flags enabling Intel RDT CMT and MBM features.
|
||||||
|
// Intel RDT features are available in Linux 4.14 and newer kernel versions.
|
||||||
type LinuxIntelRdt struct {
|
type LinuxIntelRdt struct {
|
||||||
// The identity for RDT Class of Service
|
// The identity for RDT Class of Service
|
||||||
ClosID string `json:"closID,omitempty"`
|
ClosID string `json:"closID,omitempty"`
|
||||||
@ -697,4 +732,36 @@ type LinuxIntelRdt struct {
|
|||||||
// The unit of memory bandwidth is specified in "percentages" by
|
// The unit of memory bandwidth is specified in "percentages" by
|
||||||
// default, and in "MBps" if MBA Software Controller is enabled.
|
// default, and in "MBps" if MBA Software Controller is enabled.
|
||||||
MemBwSchema string `json:"memBwSchema,omitempty"`
|
MemBwSchema string `json:"memBwSchema,omitempty"`
|
||||||
|
|
||||||
|
// EnableCMT is the flag to indicate if the Intel RDT CMT is enabled. CMT (Cache Monitoring Technology) supports monitoring of
|
||||||
|
// the last-level cache (LLC) occupancy for the container.
|
||||||
|
EnableCMT bool `json:"enableCMT,omitempty"`
|
||||||
|
|
||||||
|
// EnableMBM is the flag to indicate if the Intel RDT MBM is enabled. MBM (Memory Bandwidth Monitoring) supports monitoring of
|
||||||
|
// total and local memory bandwidth for the container.
|
||||||
|
EnableMBM bool `json:"enableMBM,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZOS contains platform-specific configuration for z/OS based containers.
|
||||||
|
type ZOS struct {
|
||||||
|
// Devices are a list of device nodes that are created for the container
|
||||||
|
Devices []ZOSDevice `json:"devices,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZOSDevice represents the mknod information for a z/OS special device file
|
||||||
|
type ZOSDevice struct {
|
||||||
|
// Path to the device.
|
||||||
|
Path string `json:"path"`
|
||||||
|
// Device type, block, char, etc.
|
||||||
|
Type string `json:"type"`
|
||||||
|
// Major is the device's major number.
|
||||||
|
Major int64 `json:"major"`
|
||||||
|
// Minor is the device's minor number.
|
||||||
|
Minor int64 `json:"minor"`
|
||||||
|
// FileMode permission bits for the device.
|
||||||
|
FileMode *os.FileMode `json:"fileMode,omitempty"`
|
||||||
|
// UID of the device.
|
||||||
|
UID *uint32 `json:"uid,omitempty"`
|
||||||
|
// Gid of the device.
|
||||||
|
GID *uint32 `json:"gid,omitempty"`
|
||||||
}
|
}
|
||||||
|
122
vendor/github.com/opencontainers/runtime-tools/error/error.go
generated
vendored
122
vendor/github.com/opencontainers/runtime-tools/error/error.go
generated
vendored
@ -1,122 +0,0 @@
|
|||||||
// Package error implements generic tooling for tracking RFC 2119
|
|
||||||
// violations and linking back to the appropriate specification section.
|
|
||||||
package error
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Level represents the RFC 2119 compliance levels
|
|
||||||
type Level int
|
|
||||||
|
|
||||||
const (
|
|
||||||
// MAY-level
|
|
||||||
|
|
||||||
// May represents 'MAY' in RFC 2119.
|
|
||||||
May Level = iota
|
|
||||||
// Optional represents 'OPTIONAL' in RFC 2119.
|
|
||||||
Optional
|
|
||||||
|
|
||||||
// SHOULD-level
|
|
||||||
|
|
||||||
// Should represents 'SHOULD' in RFC 2119.
|
|
||||||
Should
|
|
||||||
// ShouldNot represents 'SHOULD NOT' in RFC 2119.
|
|
||||||
ShouldNot
|
|
||||||
// Recommended represents 'RECOMMENDED' in RFC 2119.
|
|
||||||
Recommended
|
|
||||||
// NotRecommended represents 'NOT RECOMMENDED' in RFC 2119.
|
|
||||||
NotRecommended
|
|
||||||
|
|
||||||
// MUST-level
|
|
||||||
|
|
||||||
// Must represents 'MUST' in RFC 2119
|
|
||||||
Must
|
|
||||||
// MustNot represents 'MUST NOT' in RFC 2119.
|
|
||||||
MustNot
|
|
||||||
// Shall represents 'SHALL' in RFC 2119.
|
|
||||||
Shall
|
|
||||||
// ShallNot represents 'SHALL NOT' in RFC 2119.
|
|
||||||
ShallNot
|
|
||||||
// Required represents 'REQUIRED' in RFC 2119.
|
|
||||||
Required
|
|
||||||
)
|
|
||||||
|
|
||||||
// Error represents an error with compliance level and specification reference.
|
|
||||||
type Error struct {
|
|
||||||
// Level represents the RFC 2119 compliance level.
|
|
||||||
Level Level
|
|
||||||
|
|
||||||
// Reference is a URL for the violated specification requirement.
|
|
||||||
Reference string
|
|
||||||
|
|
||||||
// Err holds additional details about the violation.
|
|
||||||
Err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseLevel takes a string level and returns the RFC 2119 compliance level constant.
|
|
||||||
func ParseLevel(level string) (Level, error) {
|
|
||||||
switch strings.ToUpper(level) {
|
|
||||||
case "MAY":
|
|
||||||
fallthrough
|
|
||||||
case "OPTIONAL":
|
|
||||||
return May, nil
|
|
||||||
case "SHOULD":
|
|
||||||
fallthrough
|
|
||||||
case "SHOULDNOT":
|
|
||||||
fallthrough
|
|
||||||
case "RECOMMENDED":
|
|
||||||
fallthrough
|
|
||||||
case "NOTRECOMMENDED":
|
|
||||||
return Should, nil
|
|
||||||
case "MUST":
|
|
||||||
fallthrough
|
|
||||||
case "MUSTNOT":
|
|
||||||
fallthrough
|
|
||||||
case "SHALL":
|
|
||||||
fallthrough
|
|
||||||
case "SHALLNOT":
|
|
||||||
fallthrough
|
|
||||||
case "REQUIRED":
|
|
||||||
return Must, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var l Level
|
|
||||||
return l, fmt.Errorf("%q is not a valid compliance level", level)
|
|
||||||
}
|
|
||||||
|
|
||||||
// String takes a RFC 2119 compliance level constant and returns a string representation.
|
|
||||||
func (level Level) String() string {
|
|
||||||
switch level {
|
|
||||||
case May:
|
|
||||||
return "MAY"
|
|
||||||
case Optional:
|
|
||||||
return "OPTIONAL"
|
|
||||||
case Should:
|
|
||||||
return "SHOULD"
|
|
||||||
case ShouldNot:
|
|
||||||
return "SHOULD NOT"
|
|
||||||
case Recommended:
|
|
||||||
return "RECOMMENDED"
|
|
||||||
case NotRecommended:
|
|
||||||
return "NOT RECOMMENDED"
|
|
||||||
case Must:
|
|
||||||
return "MUST"
|
|
||||||
case MustNot:
|
|
||||||
return "MUST NOT"
|
|
||||||
case Shall:
|
|
||||||
return "SHALL"
|
|
||||||
case ShallNot:
|
|
||||||
return "SHALL NOT"
|
|
||||||
case Required:
|
|
||||||
return "REQUIRED"
|
|
||||||
}
|
|
||||||
|
|
||||||
panic(fmt.Sprintf("%d is not a valid compliance level", level))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns the error message with specification reference.
|
|
||||||
func (err *Error) Error() string {
|
|
||||||
return fmt.Sprintf("%s\nRefer to: %s", err.Err.Error(), err.Reference)
|
|
||||||
}
|
|
48
vendor/github.com/opencontainers/runtime-tools/filepath/abs.go
generated
vendored
48
vendor/github.com/opencontainers/runtime-tools/filepath/abs.go
generated
vendored
@ -1,48 +0,0 @@
|
|||||||
package filepath
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var windowsAbs = regexp.MustCompile(`^[a-zA-Z]:\\.*$`)
|
|
||||||
|
|
||||||
// Abs is a version of path/filepath's Abs with an explicit operating
|
|
||||||
// system and current working directory.
|
|
||||||
func Abs(os, path, cwd string) (_ string, err error) {
|
|
||||||
if IsAbs(os, path) {
|
|
||||||
return Clean(os, path), nil
|
|
||||||
}
|
|
||||||
return Clean(os, Join(os, cwd, path)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsAbs is a version of path/filepath's IsAbs with an explicit
|
|
||||||
// operating system.
|
|
||||||
func IsAbs(os, path string) bool {
|
|
||||||
if os == "windows" {
|
|
||||||
// FIXME: copy hideous logic from Go's
|
|
||||||
// src/path/filepath/path_windows.go into somewhere where we can
|
|
||||||
// put 3-clause BSD licensed code.
|
|
||||||
return windowsAbs.MatchString(path)
|
|
||||||
}
|
|
||||||
sep := Separator(os)
|
|
||||||
|
|
||||||
// POSIX has [1]:
|
|
||||||
//
|
|
||||||
// > If a pathname begins with two successive <slash> characters,
|
|
||||||
// > the first component following the leading <slash> characters
|
|
||||||
// > may be interpreted in an implementation-defined manner,
|
|
||||||
// > although more than two leading <slash> characters shall be
|
|
||||||
// > treated as a single <slash> character.
|
|
||||||
//
|
|
||||||
// And Boost treats // as non-absolute [2], but Linux [3,4], Python
|
|
||||||
// [5] and Go [6] all treat // as absolute.
|
|
||||||
//
|
|
||||||
// [1]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
|
|
||||||
// [2]: https://github.com/boostorg/filesystem/blob/boost-1.64.0/test/path_test.cpp#L861
|
|
||||||
// [3]: http://man7.org/linux/man-pages/man7/path_resolution.7.html
|
|
||||||
// [4]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/path-lookup.md?h=v4.12#n41
|
|
||||||
// [5]: https://github.com/python/cpython/blob/v3.6.1/Lib/posixpath.py#L64-L66
|
|
||||||
// [6]: https://go.googlesource.com/go/+/go1.8.3/src/path/path.go#199
|
|
||||||
return strings.HasPrefix(path, string(sep))
|
|
||||||
}
|
|
32
vendor/github.com/opencontainers/runtime-tools/filepath/ancestor.go
generated
vendored
32
vendor/github.com/opencontainers/runtime-tools/filepath/ancestor.go
generated
vendored
@ -1,32 +0,0 @@
|
|||||||
package filepath
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsAncestor returns true when pathB is an strict ancestor of pathA,
|
|
||||||
// and false where the paths are equal or pathB is outside of pathA.
|
|
||||||
// Paths that are not absolute will be made absolute with Abs.
|
|
||||||
func IsAncestor(os, pathA, pathB, cwd string) (_ bool, err error) {
|
|
||||||
if pathA == pathB {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pathA, err = Abs(os, pathA, cwd)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
pathB, err = Abs(os, pathB, cwd)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
sep := Separator(os)
|
|
||||||
if !strings.HasSuffix(pathA, string(sep)) {
|
|
||||||
pathA = fmt.Sprintf("%s%c", pathA, sep)
|
|
||||||
}
|
|
||||||
if pathA == pathB {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return strings.HasPrefix(pathB, pathA), nil
|
|
||||||
}
|
|
74
vendor/github.com/opencontainers/runtime-tools/filepath/clean.go
generated
vendored
74
vendor/github.com/opencontainers/runtime-tools/filepath/clean.go
generated
vendored
@ -1,74 +0,0 @@
|
|||||||
package filepath
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Clean is an explicit-OS version of path/filepath's Clean.
|
|
||||||
func Clean(os, path string) string {
|
|
||||||
abs := IsAbs(os, path)
|
|
||||||
sep := Separator(os)
|
|
||||||
elements := strings.Split(path, string(sep))
|
|
||||||
|
|
||||||
// Replace multiple Separator elements with a single one.
|
|
||||||
for i := 0; i < len(elements); i++ {
|
|
||||||
if len(elements[i]) == 0 {
|
|
||||||
elements = append(elements[:i], elements[i+1:]...)
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eliminate each . path name element (the current directory).
|
|
||||||
for i := 0; i < len(elements); i++ {
|
|
||||||
if elements[i] == "." && len(elements) > 1 {
|
|
||||||
elements = append(elements[:i], elements[i+1:]...)
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eliminate each inner .. path name element (the parent directory)
|
|
||||||
// along with the non-.. element that precedes it.
|
|
||||||
for i := 1; i < len(elements); i++ {
|
|
||||||
if i == 1 && abs && sep == '\\' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if i > 0 && elements[i] == ".." {
|
|
||||||
elements = append(elements[:i-1], elements[i+1:]...)
|
|
||||||
i -= 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eliminate .. elements that begin a rooted path:
|
|
||||||
// that is, replace "/.." by "/" at the beginning of a path,
|
|
||||||
// assuming Separator is '/'.
|
|
||||||
offset := 0
|
|
||||||
if sep == '\\' {
|
|
||||||
offset = 1
|
|
||||||
}
|
|
||||||
if abs {
|
|
||||||
for len(elements) > offset && elements[offset] == ".." {
|
|
||||||
elements = append(elements[:offset], elements[offset+1:]...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cleaned := strings.Join(elements, string(sep))
|
|
||||||
if abs {
|
|
||||||
if sep == '/' {
|
|
||||||
cleaned = fmt.Sprintf("%c%s", sep, cleaned)
|
|
||||||
} else if len(elements) == 1 {
|
|
||||||
cleaned = fmt.Sprintf("%s%c", cleaned, sep)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the result of this process is an empty string, Clean returns
|
|
||||||
// the string ".".
|
|
||||||
if len(cleaned) == 0 {
|
|
||||||
cleaned = "."
|
|
||||||
}
|
|
||||||
|
|
||||||
if cleaned == path {
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
return Clean(os, cleaned)
|
|
||||||
}
|
|
6
vendor/github.com/opencontainers/runtime-tools/filepath/doc.go
generated
vendored
6
vendor/github.com/opencontainers/runtime-tools/filepath/doc.go
generated
vendored
@ -1,6 +0,0 @@
|
|||||||
// Package filepath implements Go's filepath package with explicit
|
|
||||||
// operating systems (and for some functions and explicit working
|
|
||||||
// directory). This allows tools built for one OS to operate on paths
|
|
||||||
// targeting another OS. For example, a Linux build can determine
|
|
||||||
// whether a path is absolute on Linux or on Windows.
|
|
||||||
package filepath
|
|
9
vendor/github.com/opencontainers/runtime-tools/filepath/join.go
generated
vendored
9
vendor/github.com/opencontainers/runtime-tools/filepath/join.go
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
package filepath
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
// Join is an explicit-OS version of path/filepath's Join.
|
|
||||||
func Join(os string, elem ...string) string {
|
|
||||||
sep := Separator(os)
|
|
||||||
return Clean(os, strings.Join(elem, string(sep)))
|
|
||||||
}
|
|
9
vendor/github.com/opencontainers/runtime-tools/filepath/separator.go
generated
vendored
9
vendor/github.com/opencontainers/runtime-tools/filepath/separator.go
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
package filepath
|
|
||||||
|
|
||||||
// Separator is an explicit-OS version of path/filepath's Separator.
|
|
||||||
func Separator(os string) rune {
|
|
||||||
if os == "windows" {
|
|
||||||
return '\\'
|
|
||||||
}
|
|
||||||
return '/'
|
|
||||||
}
|
|
28
vendor/github.com/opencontainers/runtime-tools/generate/config.go
generated
vendored
28
vendor/github.com/opencontainers/runtime-tools/generate/config.go
generated
vendored
@ -123,6 +123,13 @@ func (g *Generator) initConfigLinuxResourcesPids() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Generator) initConfigLinuxResourcesUnified() {
|
||||||
|
g.initConfigLinuxResources()
|
||||||
|
if g.Config.Linux.Resources.Unified == nil {
|
||||||
|
g.Config.Linux.Resources.Unified = map[string]string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (g *Generator) initConfigSolaris() {
|
func (g *Generator) initConfigSolaris() {
|
||||||
g.initConfig()
|
g.initConfig()
|
||||||
if g.Config.Solaris == nil {
|
if g.Config.Solaris == nil {
|
||||||
@ -185,24 +192,3 @@ func (g *Generator) initConfigVM() {
|
|||||||
g.Config.VM = &rspec.VM{}
|
g.Config.VM = &rspec.VM{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Generator) initConfigVMHypervisor() {
|
|
||||||
g.initConfigVM()
|
|
||||||
if &g.Config.VM.Hypervisor == nil {
|
|
||||||
g.Config.VM.Hypervisor = rspec.VMHypervisor{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Generator) initConfigVMKernel() {
|
|
||||||
g.initConfigVM()
|
|
||||||
if &g.Config.VM.Kernel == nil {
|
|
||||||
g.Config.VM.Kernel = rspec.VMKernel{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Generator) initConfigVMImage() {
|
|
||||||
g.initConfigVM()
|
|
||||||
if &g.Config.VM.Image == nil {
|
|
||||||
g.Config.VM.Image = rspec.VMImage{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
124
vendor/github.com/opencontainers/runtime-tools/generate/generate.go
generated
vendored
124
vendor/github.com/opencontainers/runtime-tools/generate/generate.go
generated
vendored
@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/opencontainers/runtime-tools/generate/seccomp"
|
"github.com/opencontainers/runtime-tools/generate/seccomp"
|
||||||
"github.com/opencontainers/runtime-tools/validate"
|
capsCheck "github.com/opencontainers/runtime-tools/validate/capabilities"
|
||||||
"github.com/syndtr/gocapability/capability"
|
"github.com/syndtr/gocapability/capability"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ type ExportOptions struct {
|
|||||||
// New creates a configuration Generator with the default
|
// New creates a configuration Generator with the default
|
||||||
// configuration for the target operating system.
|
// configuration for the target operating system.
|
||||||
func New(os string) (generator Generator, err error) {
|
func New(os string) (generator Generator, err error) {
|
||||||
if os != "linux" && os != "solaris" && os != "windows" {
|
if os != "linux" && os != "solaris" && os != "windows" && os != "freebsd" {
|
||||||
return generator, fmt.Errorf("no defaults configured for %s", os)
|
return generator, fmt.Errorf("no defaults configured for %s", os)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ func New(os string) (generator Generator, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if os == "linux" || os == "solaris" {
|
if os == "linux" || os == "solaris" || os == "freebsd" {
|
||||||
config.Process.User = rspec.User{}
|
config.Process.User = rspec.User{}
|
||||||
config.Process.Env = []string{
|
config.Process.Env = []string{
|
||||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||||
@ -182,7 +182,7 @@ func New(os string) (generator Generator, err error) {
|
|||||||
Destination: "/dev",
|
Destination: "/dev",
|
||||||
Type: "tmpfs",
|
Type: "tmpfs",
|
||||||
Source: "tmpfs",
|
Source: "tmpfs",
|
||||||
Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
|
Options: []string{"nosuid", "noexec", "strictatime", "mode=755", "size=65536k"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Destination: "/dev/pts",
|
Destination: "/dev/pts",
|
||||||
@ -237,6 +237,21 @@ func New(os string) (generator Generator, err error) {
|
|||||||
},
|
},
|
||||||
Seccomp: seccomp.DefaultProfile(&config),
|
Seccomp: seccomp.DefaultProfile(&config),
|
||||||
}
|
}
|
||||||
|
} else if os == "freebsd" {
|
||||||
|
config.Mounts = []rspec.Mount{
|
||||||
|
{
|
||||||
|
Destination: "/dev",
|
||||||
|
Type: "devfs",
|
||||||
|
Source: "devfs",
|
||||||
|
Options: []string{"ruleset=4"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Destination: "/dev/fd",
|
||||||
|
Type: "fdescfs",
|
||||||
|
Source: "fdesc",
|
||||||
|
Options: []string{},
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
envCache := map[string]int{}
|
envCache := map[string]int{}
|
||||||
@ -249,10 +264,6 @@ func New(os string) (generator Generator, err error) {
|
|||||||
|
|
||||||
// NewFromSpec creates a configuration Generator from a given
|
// NewFromSpec creates a configuration Generator from a given
|
||||||
// configuration.
|
// configuration.
|
||||||
//
|
|
||||||
// Deprecated: Replace with:
|
|
||||||
//
|
|
||||||
// generator := Generator{Config: config}
|
|
||||||
func NewFromSpec(config *rspec.Spec) Generator {
|
func NewFromSpec(config *rspec.Spec) Generator {
|
||||||
envCache := map[string]int{}
|
envCache := map[string]int{}
|
||||||
if config != nil && config.Process != nil {
|
if config != nil && config.Process != nil {
|
||||||
@ -444,6 +455,13 @@ func (g *Generator) SetProcessUsername(username string) {
|
|||||||
g.Config.Process.User.Username = username
|
g.Config.Process.User.Username = username
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetProcessUmask sets g.Config.Process.User.Umask.
|
||||||
|
func (g *Generator) SetProcessUmask(umask uint32) {
|
||||||
|
g.initConfigProcess()
|
||||||
|
u := umask
|
||||||
|
g.Config.Process.User.Umask = &u
|
||||||
|
}
|
||||||
|
|
||||||
// SetProcessGID sets g.Config.Process.User.GID.
|
// SetProcessGID sets g.Config.Process.User.GID.
|
||||||
func (g *Generator) SetProcessGID(gid uint32) {
|
func (g *Generator) SetProcessGID(gid uint32) {
|
||||||
g.initConfigProcess()
|
g.initConfigProcess()
|
||||||
@ -597,6 +615,12 @@ func (g *Generator) SetLinuxCgroupsPath(path string) {
|
|||||||
g.Config.Linux.CgroupsPath = path
|
g.Config.Linux.CgroupsPath = path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLinuxIntelRdtClosID sets g.Config.Linux.IntelRdt.ClosID
|
||||||
|
func (g *Generator) SetLinuxIntelRdtClosID(clos string) {
|
||||||
|
g.initConfigLinuxIntelRdt()
|
||||||
|
g.Config.Linux.IntelRdt.ClosID = clos
|
||||||
|
}
|
||||||
|
|
||||||
// SetLinuxIntelRdtL3CacheSchema sets g.Config.Linux.IntelRdt.L3CacheSchema
|
// SetLinuxIntelRdtL3CacheSchema sets g.Config.Linux.IntelRdt.L3CacheSchema
|
||||||
func (g *Generator) SetLinuxIntelRdtL3CacheSchema(schema string) {
|
func (g *Generator) SetLinuxIntelRdtL3CacheSchema(schema string) {
|
||||||
g.initConfigLinuxIntelRdt()
|
g.initConfigLinuxIntelRdt()
|
||||||
@ -844,6 +868,28 @@ func (g *Generator) DropLinuxResourcesHugepageLimit(pageSize string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddLinuxResourcesUnified sets the g.Config.Linux.Resources.Unified
|
||||||
|
func (g *Generator) SetLinuxResourcesUnified(unified map[string]string) {
|
||||||
|
g.initConfigLinuxResourcesUnified()
|
||||||
|
for k, v := range unified {
|
||||||
|
g.Config.Linux.Resources.Unified[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLinuxResourcesUnified adds or updates the key-value pair from g.Config.Linux.Resources.Unified
|
||||||
|
func (g *Generator) AddLinuxResourcesUnified(key, val string) {
|
||||||
|
g.initConfigLinuxResourcesUnified()
|
||||||
|
g.Config.Linux.Resources.Unified[key] = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// DropLinuxResourcesUnified drops a key-value pair from g.Config.Linux.Resources.Unified
|
||||||
|
func (g *Generator) DropLinuxResourcesUnified(key string) {
|
||||||
|
if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.Unified == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete(g.Config.Linux.Resources.Unified, key)
|
||||||
|
}
|
||||||
|
|
||||||
// SetLinuxResourcesMemoryLimit sets g.Config.Linux.Resources.Memory.Limit.
|
// SetLinuxResourcesMemoryLimit sets g.Config.Linux.Resources.Memory.Limit.
|
||||||
func (g *Generator) SetLinuxResourcesMemoryLimit(limit int64) {
|
func (g *Generator) SetLinuxResourcesMemoryLimit(limit int64) {
|
||||||
g.initConfigLinuxResourcesMemory()
|
g.initConfigLinuxResourcesMemory()
|
||||||
@ -1018,10 +1064,9 @@ func (g *Generator) ClearPreStartHooks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddPreStartHook add a prestart hook into g.Config.Hooks.Prestart.
|
// AddPreStartHook add a prestart hook into g.Config.Hooks.Prestart.
|
||||||
func (g *Generator) AddPreStartHook(preStartHook rspec.Hook) error {
|
func (g *Generator) AddPreStartHook(preStartHook rspec.Hook) {
|
||||||
g.initConfigHooks()
|
g.initConfigHooks()
|
||||||
g.Config.Hooks.Prestart = append(g.Config.Hooks.Prestart, preStartHook)
|
g.Config.Hooks.Prestart = append(g.Config.Hooks.Prestart, preStartHook)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearPostStopHooks clear g.Config.Hooks.Poststop.
|
// ClearPostStopHooks clear g.Config.Hooks.Poststop.
|
||||||
@ -1033,10 +1078,9 @@ func (g *Generator) ClearPostStopHooks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddPostStopHook adds a poststop hook into g.Config.Hooks.Poststop.
|
// AddPostStopHook adds a poststop hook into g.Config.Hooks.Poststop.
|
||||||
func (g *Generator) AddPostStopHook(postStopHook rspec.Hook) error {
|
func (g *Generator) AddPostStopHook(postStopHook rspec.Hook) {
|
||||||
g.initConfigHooks()
|
g.initConfigHooks()
|
||||||
g.Config.Hooks.Poststop = append(g.Config.Hooks.Poststop, postStopHook)
|
g.Config.Hooks.Poststop = append(g.Config.Hooks.Poststop, postStopHook)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearPostStartHooks clear g.Config.Hooks.Poststart.
|
// ClearPostStartHooks clear g.Config.Hooks.Poststart.
|
||||||
@ -1048,10 +1092,9 @@ func (g *Generator) ClearPostStartHooks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddPostStartHook adds a poststart hook into g.Config.Hooks.Poststart.
|
// AddPostStartHook adds a poststart hook into g.Config.Hooks.Poststart.
|
||||||
func (g *Generator) AddPostStartHook(postStartHook rspec.Hook) error {
|
func (g *Generator) AddPostStartHook(postStartHook rspec.Hook) {
|
||||||
g.initConfigHooks()
|
g.initConfigHooks()
|
||||||
g.Config.Hooks.Poststart = append(g.Config.Hooks.Poststart, postStartHook)
|
g.Config.Hooks.Poststart = append(g.Config.Hooks.Poststart, postStartHook)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddMount adds a mount into g.Config.Mounts.
|
// AddMount adds a mount into g.Config.Mounts.
|
||||||
@ -1093,7 +1136,7 @@ func (g *Generator) SetupPrivileged(privileged bool) {
|
|||||||
if privileged { // Add all capabilities in privileged mode.
|
if privileged { // Add all capabilities in privileged mode.
|
||||||
var finalCapList []string
|
var finalCapList []string
|
||||||
for _, cap := range capability.List() {
|
for _, cap := range capability.List() {
|
||||||
if g.HostSpecific && cap > validate.LastCap() {
|
if g.HostSpecific && cap > capsCheck.LastCap() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
finalCapList = append(finalCapList, fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())))
|
finalCapList = append(finalCapList, fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())))
|
||||||
@ -1127,7 +1170,7 @@ func (g *Generator) ClearProcessCapabilities() {
|
|||||||
// AddProcessCapability adds a process capability into all 5 capability sets.
|
// AddProcessCapability adds a process capability into all 5 capability sets.
|
||||||
func (g *Generator) AddProcessCapability(c string) error {
|
func (g *Generator) AddProcessCapability(c string) error {
|
||||||
cp := strings.ToUpper(c)
|
cp := strings.ToUpper(c)
|
||||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1190,7 +1233,7 @@ func (g *Generator) AddProcessCapability(c string) error {
|
|||||||
// AddProcessCapabilityAmbient adds a process capability into g.Config.Process.Capabilities.Ambient.
|
// AddProcessCapabilityAmbient adds a process capability into g.Config.Process.Capabilities.Ambient.
|
||||||
func (g *Generator) AddProcessCapabilityAmbient(c string) error {
|
func (g *Generator) AddProcessCapabilityAmbient(c string) error {
|
||||||
cp := strings.ToUpper(c)
|
cp := strings.ToUpper(c)
|
||||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1214,7 +1257,7 @@ func (g *Generator) AddProcessCapabilityAmbient(c string) error {
|
|||||||
// AddProcessCapabilityBounding adds a process capability into g.Config.Process.Capabilities.Bounding.
|
// AddProcessCapabilityBounding adds a process capability into g.Config.Process.Capabilities.Bounding.
|
||||||
func (g *Generator) AddProcessCapabilityBounding(c string) error {
|
func (g *Generator) AddProcessCapabilityBounding(c string) error {
|
||||||
cp := strings.ToUpper(c)
|
cp := strings.ToUpper(c)
|
||||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1237,7 +1280,7 @@ func (g *Generator) AddProcessCapabilityBounding(c string) error {
|
|||||||
// AddProcessCapabilityEffective adds a process capability into g.Config.Process.Capabilities.Effective.
|
// AddProcessCapabilityEffective adds a process capability into g.Config.Process.Capabilities.Effective.
|
||||||
func (g *Generator) AddProcessCapabilityEffective(c string) error {
|
func (g *Generator) AddProcessCapabilityEffective(c string) error {
|
||||||
cp := strings.ToUpper(c)
|
cp := strings.ToUpper(c)
|
||||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1260,7 +1303,7 @@ func (g *Generator) AddProcessCapabilityEffective(c string) error {
|
|||||||
// AddProcessCapabilityInheritable adds a process capability into g.Config.Process.Capabilities.Inheritable.
|
// AddProcessCapabilityInheritable adds a process capability into g.Config.Process.Capabilities.Inheritable.
|
||||||
func (g *Generator) AddProcessCapabilityInheritable(c string) error {
|
func (g *Generator) AddProcessCapabilityInheritable(c string) error {
|
||||||
cp := strings.ToUpper(c)
|
cp := strings.ToUpper(c)
|
||||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1283,7 +1326,7 @@ func (g *Generator) AddProcessCapabilityInheritable(c string) error {
|
|||||||
// AddProcessCapabilityPermitted adds a process capability into g.Config.Process.Capabilities.Permitted.
|
// AddProcessCapabilityPermitted adds a process capability into g.Config.Process.Capabilities.Permitted.
|
||||||
func (g *Generator) AddProcessCapabilityPermitted(c string) error {
|
func (g *Generator) AddProcessCapabilityPermitted(c string) error {
|
||||||
cp := strings.ToUpper(c)
|
cp := strings.ToUpper(c)
|
||||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1336,7 +1379,7 @@ func (g *Generator) DropProcessCapability(c string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return validate.CapValid(cp, false)
|
return capsCheck.CapValid(cp, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropProcessCapabilityAmbient drops a process capability from g.Config.Process.Capabilities.Ambient.
|
// DropProcessCapabilityAmbient drops a process capability from g.Config.Process.Capabilities.Ambient.
|
||||||
@ -1352,7 +1395,7 @@ func (g *Generator) DropProcessCapabilityAmbient(c string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return validate.CapValid(cp, false)
|
return capsCheck.CapValid(cp, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropProcessCapabilityBounding drops a process capability from g.Config.Process.Capabilities.Bounding.
|
// DropProcessCapabilityBounding drops a process capability from g.Config.Process.Capabilities.Bounding.
|
||||||
@ -1368,7 +1411,7 @@ func (g *Generator) DropProcessCapabilityBounding(c string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return validate.CapValid(cp, false)
|
return capsCheck.CapValid(cp, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropProcessCapabilityEffective drops a process capability from g.Config.Process.Capabilities.Effective.
|
// DropProcessCapabilityEffective drops a process capability from g.Config.Process.Capabilities.Effective.
|
||||||
@ -1384,7 +1427,7 @@ func (g *Generator) DropProcessCapabilityEffective(c string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return validate.CapValid(cp, false)
|
return capsCheck.CapValid(cp, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropProcessCapabilityInheritable drops a process capability from g.Config.Process.Capabilities.Inheritable.
|
// DropProcessCapabilityInheritable drops a process capability from g.Config.Process.Capabilities.Inheritable.
|
||||||
@ -1400,7 +1443,7 @@ func (g *Generator) DropProcessCapabilityInheritable(c string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return validate.CapValid(cp, false)
|
return capsCheck.CapValid(cp, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropProcessCapabilityPermitted drops a process capability from g.Config.Process.Capabilities.Permitted.
|
// DropProcessCapabilityPermitted drops a process capability from g.Config.Process.Capabilities.Permitted.
|
||||||
@ -1416,7 +1459,7 @@ func (g *Generator) DropProcessCapabilityPermitted(c string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return validate.CapValid(cp, false)
|
return capsCheck.CapValid(cp, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapStrToNamespace(ns string, path string) (rspec.LinuxNamespace, error) {
|
func mapStrToNamespace(ns string, path string) (rspec.LinuxNamespace, error) {
|
||||||
@ -1495,9 +1538,6 @@ func (g *Generator) AddDevice(device rspec.LinuxDevice) {
|
|||||||
g.Config.Linux.Devices[i] = device
|
g.Config.Linux.Devices[i] = device
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if dev.Type == device.Type && dev.Major == device.Major && dev.Minor == device.Minor {
|
|
||||||
fmt.Fprintln(os.Stderr, "WARNING: The same type, major and minor should not be used for multiple devices.")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g.Config.Linux.Devices = append(g.Config.Linux.Devices, device)
|
g.Config.Linux.Devices = append(g.Config.Linux.Devices, device)
|
||||||
@ -1556,12 +1596,8 @@ func (g *Generator) RemoveLinuxResourcesDevice(allow bool, devType string, major
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// strPtr returns the pointer pointing to the string s.
|
|
||||||
func strPtr(s string) *string { return &s }
|
|
||||||
|
|
||||||
// SetSyscallAction adds rules for syscalls with the specified action
|
// SetSyscallAction adds rules for syscalls with the specified action
|
||||||
func (g *Generator) SetSyscallAction(arguments seccomp.SyscallOpts) error {
|
func (g *Generator) SetSyscallAction(arguments seccomp.SyscallOpts) error {
|
||||||
g.initConfigLinuxSeccomp()
|
g.initConfigLinuxSeccomp()
|
||||||
@ -1581,6 +1617,12 @@ func (g *Generator) SetDefaultSeccompActionForce(action string) error {
|
|||||||
return seccomp.ParseDefaultActionForce(action, g.Config.Linux.Seccomp)
|
return seccomp.ParseDefaultActionForce(action, g.Config.Linux.Seccomp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDomainName sets g.Config.Domainname
|
||||||
|
func (g *Generator) SetDomainName(domain string) {
|
||||||
|
g.initConfig()
|
||||||
|
g.Config.Domainname = domain
|
||||||
|
}
|
||||||
|
|
||||||
// SetSeccompArchitecture sets the supported seccomp architectures
|
// SetSeccompArchitecture sets the supported seccomp architectures
|
||||||
func (g *Generator) SetSeccompArchitecture(architecture string) error {
|
func (g *Generator) SetSeccompArchitecture(architecture string) error {
|
||||||
g.initConfigLinuxSeccomp()
|
g.initConfigLinuxSeccomp()
|
||||||
@ -1687,14 +1729,14 @@ func (g *Generator) SetVMHypervisorPath(path string) error {
|
|||||||
if !strings.HasPrefix(path, "/") {
|
if !strings.HasPrefix(path, "/") {
|
||||||
return fmt.Errorf("hypervisorPath %v is not an absolute path", path)
|
return fmt.Errorf("hypervisorPath %v is not an absolute path", path)
|
||||||
}
|
}
|
||||||
g.initConfigVMHypervisor()
|
g.initConfigVM()
|
||||||
g.Config.VM.Hypervisor.Path = path
|
g.Config.VM.Hypervisor.Path = path
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVMHypervisorParameters sets g.Config.VM.Hypervisor.Parameters
|
// SetVMHypervisorParameters sets g.Config.VM.Hypervisor.Parameters
|
||||||
func (g *Generator) SetVMHypervisorParameters(parameters []string) {
|
func (g *Generator) SetVMHypervisorParameters(parameters []string) {
|
||||||
g.initConfigVMHypervisor()
|
g.initConfigVM()
|
||||||
g.Config.VM.Hypervisor.Parameters = parameters
|
g.Config.VM.Hypervisor.Parameters = parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1703,14 +1745,14 @@ func (g *Generator) SetVMKernelPath(path string) error {
|
|||||||
if !strings.HasPrefix(path, "/") {
|
if !strings.HasPrefix(path, "/") {
|
||||||
return fmt.Errorf("kernelPath %v is not an absolute path", path)
|
return fmt.Errorf("kernelPath %v is not an absolute path", path)
|
||||||
}
|
}
|
||||||
g.initConfigVMKernel()
|
g.initConfigVM()
|
||||||
g.Config.VM.Kernel.Path = path
|
g.Config.VM.Kernel.Path = path
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVMKernelParameters sets g.Config.VM.Kernel.Parameters
|
// SetVMKernelParameters sets g.Config.VM.Kernel.Parameters
|
||||||
func (g *Generator) SetVMKernelParameters(parameters []string) {
|
func (g *Generator) SetVMKernelParameters(parameters []string) {
|
||||||
g.initConfigVMKernel()
|
g.initConfigVM()
|
||||||
g.Config.VM.Kernel.Parameters = parameters
|
g.Config.VM.Kernel.Parameters = parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1719,7 +1761,7 @@ func (g *Generator) SetVMKernelInitRD(initrd string) error {
|
|||||||
if !strings.HasPrefix(initrd, "/") {
|
if !strings.HasPrefix(initrd, "/") {
|
||||||
return fmt.Errorf("kernelInitrd %v is not an absolute path", initrd)
|
return fmt.Errorf("kernelInitrd %v is not an absolute path", initrd)
|
||||||
}
|
}
|
||||||
g.initConfigVMKernel()
|
g.initConfigVM()
|
||||||
g.Config.VM.Kernel.InitRD = initrd
|
g.Config.VM.Kernel.InitRD = initrd
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1729,7 +1771,7 @@ func (g *Generator) SetVMImagePath(path string) error {
|
|||||||
if !strings.HasPrefix(path, "/") {
|
if !strings.HasPrefix(path, "/") {
|
||||||
return fmt.Errorf("imagePath %v is not an absolute path", path)
|
return fmt.Errorf("imagePath %v is not an absolute path", path)
|
||||||
}
|
}
|
||||||
g.initConfigVMImage()
|
g.initConfigVM()
|
||||||
g.Config.VM.Image.Path = path
|
g.Config.VM.Image.Path = path
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1745,7 +1787,7 @@ func (g *Generator) SetVMImageFormat(format string) error {
|
|||||||
default:
|
default:
|
||||||
return fmt.Errorf("Commonly supported formats are: raw, qcow2, vdi, vmdk, vhd")
|
return fmt.Errorf("Commonly supported formats are: raw, qcow2, vdi, vmdk, vhd")
|
||||||
}
|
}
|
||||||
g.initConfigVMImage()
|
g.initConfigVM()
|
||||||
g.Config.VM.Image.Format = format
|
g.Config.VM.Image.Format = format
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
5
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go
generated
vendored
5
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go
generated
vendored
@ -4,9 +4,4 @@ const (
|
|||||||
seccompOverwrite = "overwrite"
|
seccompOverwrite = "overwrite"
|
||||||
seccompAppend = "append"
|
seccompAppend = "append"
|
||||||
nothing = "nothing"
|
nothing = "nothing"
|
||||||
kill = "kill"
|
|
||||||
trap = "trap"
|
|
||||||
trace = "trace"
|
|
||||||
allow = "allow"
|
|
||||||
errno = "errno"
|
|
||||||
)
|
)
|
||||||
|
32
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go
generated
vendored
32
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go
generated
vendored
@ -151,6 +151,9 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
|
|||||||
"io_submit",
|
"io_submit",
|
||||||
"ipc",
|
"ipc",
|
||||||
"kill",
|
"kill",
|
||||||
|
"landlock_add_rule",
|
||||||
|
"landlock_create_ruleset",
|
||||||
|
"landlock_restrict_self",
|
||||||
"lchown",
|
"lchown",
|
||||||
"lchown32",
|
"lchown32",
|
||||||
"lgetxattr",
|
"lgetxattr",
|
||||||
@ -303,6 +306,7 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
|
|||||||
"stat64",
|
"stat64",
|
||||||
"statfs",
|
"statfs",
|
||||||
"statfs64",
|
"statfs64",
|
||||||
|
"statx",
|
||||||
"symlink",
|
"symlink",
|
||||||
"symlinkat",
|
"symlinkat",
|
||||||
"sync",
|
"sync",
|
||||||
@ -353,11 +357,23 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
|
|||||||
Value: 0x0,
|
Value: 0x0,
|
||||||
Op: rspec.OpEqualTo,
|
Op: rspec.OpEqualTo,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"personality"},
|
||||||
|
Action: rspec.ActAllow,
|
||||||
|
Args: []rspec.LinuxSeccompArg{
|
||||||
{
|
{
|
||||||
Index: 0,
|
Index: 0,
|
||||||
Value: 0x0008,
|
Value: 0x0008,
|
||||||
Op: rspec.OpEqualTo,
|
Op: rspec.OpEqualTo,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"personality"},
|
||||||
|
Action: rspec.ActAllow,
|
||||||
|
Args: []rspec.LinuxSeccompArg{
|
||||||
{
|
{
|
||||||
Index: 0,
|
Index: 0,
|
||||||
Value: 0xffffffff,
|
Value: 0xffffffff,
|
||||||
@ -512,7 +528,7 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
|
|||||||
Args: []rspec.LinuxSeccompArg{
|
Args: []rspec.LinuxSeccompArg{
|
||||||
{
|
{
|
||||||
Index: sysCloneFlagsIndex,
|
Index: sysCloneFlagsIndex,
|
||||||
Value: CloneNewNS | CloneNewUTS | CloneNewIPC | CloneNewUser | CloneNewPID | CloneNewNet,
|
Value: CloneNewNS | CloneNewUTS | CloneNewIPC | CloneNewUser | CloneNewPID | CloneNewNet | CloneNewCgroup,
|
||||||
ValueTwo: 0,
|
ValueTwo: 0,
|
||||||
Op: rspec.OpMaskedEqual,
|
Op: rspec.OpMaskedEqual,
|
||||||
},
|
},
|
||||||
@ -566,6 +582,20 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
|
|||||||
},
|
},
|
||||||
}...)
|
}...)
|
||||||
/* Flags parameter of the clone syscall is the 2nd on s390 */
|
/* Flags parameter of the clone syscall is the 2nd on s390 */
|
||||||
|
syscalls = append(syscalls, []rspec.LinuxSyscall{
|
||||||
|
{
|
||||||
|
Names: []string{"clone"},
|
||||||
|
Action: rspec.ActAllow,
|
||||||
|
Args: []rspec.LinuxSeccompArg{
|
||||||
|
{
|
||||||
|
Index: 1,
|
||||||
|
Value: 2080505856,
|
||||||
|
ValueTwo: 0,
|
||||||
|
Op: rspec.OpMaskedEqual,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &rspec.LinuxSeccomp{
|
return &rspec.LinuxSeccomp{
|
||||||
|
16
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go
generated
vendored
16
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go
generated
vendored
@ -1,15 +1,17 @@
|
|||||||
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package seccomp
|
package seccomp
|
||||||
|
|
||||||
import "syscall"
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
// System values passed through on linux
|
// System values passed through on linux
|
||||||
const (
|
const (
|
||||||
CloneNewIPC = syscall.CLONE_NEWIPC
|
CloneNewIPC = unix.CLONE_NEWIPC
|
||||||
CloneNewNet = syscall.CLONE_NEWNET
|
CloneNewNet = unix.CLONE_NEWNET
|
||||||
CloneNewNS = syscall.CLONE_NEWNS
|
CloneNewNS = unix.CLONE_NEWNS
|
||||||
CloneNewPID = syscall.CLONE_NEWPID
|
CloneNewPID = unix.CLONE_NEWPID
|
||||||
CloneNewUser = syscall.CLONE_NEWUSER
|
CloneNewUser = unix.CLONE_NEWUSER
|
||||||
CloneNewUTS = syscall.CLONE_NEWUTS
|
CloneNewUTS = unix.CLONE_NEWUTS
|
||||||
|
CloneNewCgroup = unix.CLONE_NEWCGROUP
|
||||||
)
|
)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !linux
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package seccomp
|
package seccomp
|
||||||
|
16
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go
generated
vendored
16
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go
generated
vendored
@ -92,22 +92,6 @@ func identical(config1, config2 *rspec.LinuxSyscall) bool {
|
|||||||
return reflect.DeepEqual(config1, config2)
|
return reflect.DeepEqual(config1, config2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func identicalExceptAction(config1, config2 *rspec.LinuxSyscall) bool {
|
|
||||||
samename := sameName(config1, config2)
|
|
||||||
sameAction := sameAction(config1, config2)
|
|
||||||
sameArgs := sameArgs(config1, config2)
|
|
||||||
|
|
||||||
return samename && !sameAction && sameArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
func identicalExceptArgs(config1, config2 *rspec.LinuxSyscall) bool {
|
|
||||||
samename := sameName(config1, config2)
|
|
||||||
sameAction := sameAction(config1, config2)
|
|
||||||
sameArgs := sameArgs(config1, config2)
|
|
||||||
|
|
||||||
return samename && sameAction && !sameArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
func sameName(config1, config2 *rspec.LinuxSyscall) bool {
|
func sameName(config1, config2 *rspec.LinuxSyscall) bool {
|
||||||
return reflect.DeepEqual(config1.Names, config2.Names)
|
return reflect.DeepEqual(config1.Names, config2.Names)
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user