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/leases/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/v2"
|
||||
_ "github.com/containerd/containerd/services/containers"
|
||||
|
@ -38,7 +38,7 @@ func FuzzCRIServer(data []byte) int {
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
c, err := server.NewCRIService(criconfig.Config{}, client)
|
||||
c, err := server.NewCRIService(criconfig.Config{}, client, nil)
|
||||
if err != nil {
|
||||
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-runc v1.0.0
|
||||
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/typeurl v1.0.3-0.20220422153119-7f6e6d160d67
|
||||
github.com/containerd/zfs v1.0.0
|
||||
@ -47,7 +49,10 @@ require (
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
|
||||
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/pelletier/go-toml v1.9.3
|
||||
github.com/prometheus/client_golang v1.12.1
|
||||
@ -82,7 +87,6 @@ require (
|
||||
require (
|
||||
cloud.google.com/go/compute/metadata v0.2.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/cenkalti/backoff/v4 v4.1.3 // 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/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // 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/pmezard/go-difflib v1.0.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/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // 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.opencensus.io v0.23.0 // 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/text v0.4.0 // 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
|
||||
gopkg.in/inf.v0 v0.9.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/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/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/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||
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.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
|
||||
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/go.mod h1:7XX96hdvnwWGdXnksDNdhfFcUH1BtQY6bL2L3f9Abyk=
|
||||
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/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.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||
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/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-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-20211001041855-01bcc9b48dfe/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-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-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-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-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
|
||||
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.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.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.3/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.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
|
||||
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-20190815185530-f2a389ac0a02/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/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-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-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
|
||||
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/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
|
||||
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/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/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=
|
||||
@ -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.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.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/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=
|
||||
@ -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.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.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
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-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.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
||||
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.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=
|
||||
@ -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 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/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/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
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/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/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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
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/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.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-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
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.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.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-20180430190053-c9281466c8b2/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.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.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/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||
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-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.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||
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/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
|
||||
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/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-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e h1:2Tg49TNXSTIsX8AAtmo1aQ1IbfnoUFzkOp7p2iWygtc=
|
||||
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb h1:1xSVPOd7/UA+39/hXEGnBJ13p6JFB0E1EvQFlrRDOXI=
|
||||
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 h1:WSwkWIIS4s+E/dPF6HuVZ/hnq1WfXN371eESjREnU8k=
|
||||
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.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.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||
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/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.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.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||
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_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/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 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.22.1/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-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
|
||||
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/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||
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.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
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/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=
|
||||
@ -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-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-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/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
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.1/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/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
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-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-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-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/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
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-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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
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/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-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-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-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-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-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.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/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-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-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/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
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.1/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.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.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.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-20191011141410-1b5146add898/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-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-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/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||
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.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.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/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
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/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/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
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.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
|
||||
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/go.mod h1:E49tenyB7esgfIguEd7+g9qYhHOr9peyyBcSaeH6Gxw=
|
||||
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/opencontainers/go-digest v1.0.0
|
||||
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/stretchr/testify v1.8.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/sync v0.1.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/grpc v1.50.1 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
@ -70,4 +70,10 @@ require (
|
||||
// IMPORTANT: this replace rule ONLY replaces containerd itself; dependencies
|
||||
// in the "require" section above are still taken into account for version
|
||||
// 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.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
||||
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/go.mod h1:7XX96hdvnwWGdXnksDNdhfFcUH1BtQY6bL2L3f9Abyk=
|
||||
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/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
|
||||
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
|
||||
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
||||
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.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.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
||||
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.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
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.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
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/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.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=
|
||||
@ -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 v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
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/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
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/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||
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/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
|
||||
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.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/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
|
||||
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.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.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/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/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
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.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/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||
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.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.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-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||
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 h1:1xSVPOd7/UA+39/hXEGnBJ13p6JFB0E1EvQFlrRDOXI=
|
||||
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.9.1/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/go.mod h1:cARutUbaUrlRClyvxOICCgKixCs6L05aUsohzA3EkHQ=
|
||||
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-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
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.2/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.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.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.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-20191011141410-1b5146add898/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/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.25.3/go.mod h1:riC/P0yOGUf2K1735wW+CXs1aY2ctBgePtnnoFLd0dU=
|
||||
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-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"),
|
||||
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/log"
|
||||
"github.com/containerd/containerd/pkg/cri/sbserver"
|
||||
"github.com/containerd/containerd/pkg/nri"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/plugin"
|
||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
@ -46,6 +47,7 @@ func init() {
|
||||
Requires: []plugin.Type{
|
||||
plugin.EventPlugin,
|
||||
plugin.ServicePlugin,
|
||||
plugin.NRIApiPlugin,
|
||||
},
|
||||
InitFn: initCRIService,
|
||||
})
|
||||
@ -85,12 +87,19 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) {
|
||||
}
|
||||
|
||||
var s server.CRIService
|
||||
var nrip nri.API
|
||||
if os.Getenv("ENABLE_CRI_SANDBOXES") != "" {
|
||||
log.G(ctx).Info("using experimental CRI Sandbox server - unset ENABLE_CRI_SANDBOXES to disable")
|
||||
s, err = sbserver.NewCRIService(c, client)
|
||||
} else {
|
||||
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 {
|
||||
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.
|
||||
}()
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -128,3 +145,24 @@ func setGLogLevel() error {
|
||||
}
|
||||
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.WithContainerLabels(containerLabels),
|
||||
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
|
||||
if cntr, err = c.client.NewContainer(ctx, id, opts...); err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
// 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,
|
||||
|
@ -27,8 +27,6 @@ import (
|
||||
containerdio "github.com/containerd/containerd/cio"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/nri"
|
||||
v1 "github.com/containerd/nri/types/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
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()
|
||||
defer deferCancel()
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
@ -146,17 +144,22 @@ func (c *criService) StartContainer(ctx context.Context, r *runtime.StartContain
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to wait for containerd task: %w", err)
|
||||
}
|
||||
nric, err := nri.New()
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Error("unable to create nri client")
|
||||
}
|
||||
if nric != nil {
|
||||
nriSB := &nri.Sandbox{
|
||||
ID: sandboxID,
|
||||
Labels: sandbox.Config.Labels,
|
||||
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
deferCtx, deferCancel := ctrdutil.DeferContext()
|
||||
defer deferCancel()
|
||||
err = c.nri.stopContainer(deferCtx, &sandbox, &cntr)
|
||||
if err != nil {
|
||||
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.
|
||||
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)
|
||||
|
||||
return &runtime.StartContainerResponse{}, nil
|
||||
|
@ -47,6 +47,18 @@ func (c *criService) StopContainer(ctx context.Context, r *runtime.StopContainer
|
||||
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)
|
||||
if err != nil {
|
||||
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.
|
||||
if state == runtime.ContainerState_CONTAINER_UNKNOWN {
|
||||
return cleanupUnknownContainer(ctx, id, container)
|
||||
return c.cleanupUnknownContainer(ctx, id, container)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -93,7 +105,7 @@ func (c *criService) stopContainer(ctx context.Context, container containerstore
|
||||
if !errdefs.IsNotFound(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())
|
||||
@ -196,7 +208,7 @@ func (c *criService) waitContainerStop(ctx context.Context, container containers
|
||||
}
|
||||
|
||||
// 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.
|
||||
return handleContainerExit(ctx, &eventtypes.TaskExit{
|
||||
ContainerID: id,
|
||||
@ -204,5 +216,5 @@ func cleanupUnknownContainer(ctx context.Context, id string, cntr containerstore
|
||||
Pid: 0,
|
||||
ExitStatus: unknownExitCode,
|
||||
ExitedAt: protobuf.ToTimestamp(time.Now()),
|
||||
}, cntr)
|
||||
}, cntr, c)
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import (
|
||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
@ -42,6 +43,24 @@ func (c *criService) UpdateContainerResources(ctx context.Context, r *runtime.Up
|
||||
if err != nil {
|
||||
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:
|
||||
// 1) There won't be race condition with container start.
|
||||
// 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 {
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ func (em *eventMonitor) startSandboxExitMonitor(ctx context.Context, id string,
|
||||
|
||||
sb, err := em.c.sandboxStore.Get(e.ID)
|
||||
if err == nil {
|
||||
if err := handleSandboxExit(dctx, e, sb); err != nil {
|
||||
if err := handleSandboxExit(dctx, e, sb, em.c); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -187,7 +187,7 @@ func (em *eventMonitor) startContainerExitMonitor(ctx context.Context, id string
|
||||
|
||||
cntr, err := em.c.containerStore.Get(e.ID)
|
||||
if err == nil {
|
||||
if err := handleContainerExit(dctx, e, cntr); err != nil {
|
||||
if err := handleContainerExit(dctx, e, cntr, em.c); err != nil {
|
||||
return err
|
||||
}
|
||||
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.
|
||||
cntr, err := em.c.containerStore.Get(e.ID)
|
||||
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 nil
|
||||
@ -322,7 +322,7 @@ func (em *eventMonitor) handleEvent(any interface{}) error {
|
||||
}
|
||||
sb, err := em.c.sandboxStore.Get(e.ID)
|
||||
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 nil
|
||||
@ -362,7 +362,7 @@ func (em *eventMonitor) handleEvent(any interface{}) error {
|
||||
}
|
||||
|
||||
// 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.
|
||||
task, err := cntr.Container.Task(ctx,
|
||||
func(*containerdio.FIFOSet) (containerdio.IO, error) {
|
||||
@ -384,7 +384,7 @@ func handleContainerExit(ctx context.Context, e *eventtypes.TaskExit, cntr conta
|
||||
}
|
||||
} else {
|
||||
// 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) {
|
||||
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.
|
||||
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.
|
||||
task, err := sb.Container.Task(ctx, nil)
|
||||
if err != nil {
|
||||
@ -424,7 +424,7 @@ func handleSandboxExit(ctx context.Context, e *eventtypes.TaskExit, sb sandboxst
|
||||
}
|
||||
} else {
|
||||
// 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) {
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
// deleted:
|
||||
// 1) ListPodSandbox will not include this sandbox.
|
||||
|
@ -28,8 +28,6 @@ import (
|
||||
"time"
|
||||
|
||||
cni "github.com/containerd/go-cni"
|
||||
"github.com/containerd/nri"
|
||||
v1 "github.com/containerd/nri/types/v1"
|
||||
"github.com/containerd/typeurl"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
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()
|
||||
defer deferCancel()
|
||||
// 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)
|
||||
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)
|
||||
}
|
||||
|
||||
nric, err := nri.New()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create nri client: %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)
|
||||
if c.nri.isEnabled() {
|
||||
err = c.nri.runPodSandbox(ctx, &sandbox)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("NRI RunPodSandbox failed: %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 {
|
||||
|
@ -82,6 +82,13 @@ func (c *criService) stopPodSandbox(ctx context.Context, sandbox sandboxstore.Sa
|
||||
}
|
||||
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.
|
||||
if sandbox.NetNS != nil {
|
||||
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.
|
||||
if state == sandboxstore.StateUnknown {
|
||||
return cleanupUnknownSandbox(ctx, id, sandbox)
|
||||
return c.cleanupUnknownSandbox(ctx, id, sandbox)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -136,7 +143,7 @@ func (c *criService) stopSandboxContainer(ctx context.Context, sandbox sandboxst
|
||||
if !errdefs.IsNotFound(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())
|
||||
@ -190,7 +197,7 @@ func (c *criService) teardownPodNetwork(ctx context.Context, sandbox sandboxstor
|
||||
}
|
||||
|
||||
// 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.
|
||||
return handleSandboxExit(ctx, &eventtypes.TaskExit{
|
||||
ContainerID: id,
|
||||
@ -198,5 +205,5 @@ func cleanupUnknownSandbox(ctx context.Context, id string, sandbox sandboxstore.
|
||||
Pid: 0,
|
||||
ExitStatus: unknownExitCode,
|
||||
ExitedAt: protobuf.ToTimestamp(time.Now()),
|
||||
}, sandbox)
|
||||
}, sandbox, c)
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import (
|
||||
"github.com/containerd/containerd/oci"
|
||||
"github.com/containerd/containerd/pkg/cri/streaming"
|
||||
"github.com/containerd/containerd/pkg/kmutex"
|
||||
"github.com/containerd/containerd/pkg/nri"
|
||||
"github.com/containerd/containerd/plugin"
|
||||
runtime_alpha "github.com/containerd/containerd/third_party/k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||
cni "github.com/containerd/go-cni"
|
||||
@ -67,6 +68,7 @@ type grpcAlphaServices interface {
|
||||
// CRIService is the interface implement CRI remote service server.
|
||||
type CRIService interface {
|
||||
Run() error
|
||||
|
||||
// io.Closer is used by containerd to gracefully stop cri service.
|
||||
io.Closer
|
||||
Register(*grpc.Server) error
|
||||
@ -118,10 +120,12 @@ type criService struct {
|
||||
// one in-flight fetch request or unpack handler for a given descriptor's
|
||||
// or chain ID.
|
||||
unpackDuplicationSuppressor kmutex.KeyedLocker
|
||||
|
||||
nri *nriAPI
|
||||
}
|
||||
|
||||
// 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
|
||||
labels := label.NewStore()
|
||||
c := &criService{
|
||||
@ -181,6 +185,13 @@ func NewCRIService(config criconfig.Config, client *containerd.Client) (CRIServi
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if nrip != nil {
|
||||
c.nri = &nriAPI{
|
||||
cri: c,
|
||||
nri: nrip,
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
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"
|
||||
// TracingProcessorPlugin implements a open telemetry span processor
|
||||
TracingProcessorPlugin Type = "io.containerd.tracing.processor.v1"
|
||||
// NRIApiPlugin implements the NRI adaptation interface for containerd.
|
||||
NRIApiPlugin Type = "io.containerd.nri.v1"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -51,6 +51,20 @@ EOF
|
||||
cat >>${config_file} <<EOF
|
||||
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
|
||||
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
|
||||
fi
|
||||
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:
|
||||
enable:
|
||||
- structcheck
|
||||
- varcheck
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- gofmt
|
||||
- goimports
|
||||
- golint
|
||||
- ineffassign
|
||||
- vet
|
||||
- unused
|
||||
- misspell
|
||||
- revive
|
||||
disable:
|
||||
- errcheck
|
||||
|
||||
issues:
|
||||
include:
|
||||
- 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:
|
||||
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
|
||||
# limitations under the License.
|
||||
|
||||
all:
|
||||
go build -v
|
||||
PROTO_SOURCES = $(shell find . -name '*.proto' | grep -v /vendor/)
|
||||
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)
|
||||
[](https://github.com/containerd/nri/actions?query=workflow%3ACI)
|
||||
[](https://codecov.io/gh/containerd/nri)
|
||||
[](https://goreportcard.com/report/github.com/containerd/nri)
|
||||
### Goal
|
||||
|
||||
*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.
|
||||
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.
|
||||
### Background
|
||||
|
||||
## 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.
|
||||
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.
|
||||
[NRI v0.1.0](README-v0.1.0.md) used an OCI hook-like one-shot plugin invocation
|
||||
mechanism where a separate instance of a plugin was spawned for every NRI
|
||||
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`.
|
||||
Binaries are named with their type as the binary name, same as the CNI plugin naming scheme.
|
||||
The rest of the components are the [NRI plugin stub library](pkg/stub)
|
||||
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
|
||||
{
|
||||
"version": "0.1",
|
||||
"plugins": [
|
||||
{
|
||||
"type": "konfine",
|
||||
"conf": {
|
||||
"systemReserved": [0, 1]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "clearcfs"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
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
|
||||
functions for
|
||||
|
||||
### 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
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
- configuring the plugin
|
||||
- getting initial list of already existing pods and containers
|
||||
- hooking the plugin into pod/container lifecycle events
|
||||
- shutting down the plugin
|
||||
|
||||
### Output
|
||||
#### Plugin Registration
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "0.1",
|
||||
"state": "create",
|
||||
"id": "redis",
|
||||
"pid": 1234,
|
||||
"cgroupsPath": "qos-ls/default/redis"
|
||||
}
|
||||
```
|
||||
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
|
||||
handshake sequence which consists of the following steps:
|
||||
|
||||
## 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
|
||||
- states: `setup|pause|resume|update|delete`
|
||||
The plugin identifies itself to NRI by a plugin name and a plugin index. The
|
||||
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
|
||||
package main
|
||||
### Runtime Adaptation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
The NRI [runtime adaptation](pkg/adaptation) package is the interface
|
||||
runtimes use to integrate to NRI and interact with NRI plugins. It
|
||||
implements basic plugin discovery, startup and configuration. It also
|
||||
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"
|
||||
"github.com/containerd/containerd/pkg/nri/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
The package hides the fact that multiple NRI plugins might be processing
|
||||
any single pod or container lifecycle event. It takes care of invoking
|
||||
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
|
||||
type clearCFS struct {
|
||||
}
|
||||
The [OCI Spec generator](pkg/runtime-tools/generate) package wraps the
|
||||
[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 {
|
||||
return "clearcfs"
|
||||
}
|
||||
### Plugin Stub Library
|
||||
|
||||
func (c *clearCFS) Invoke(ctx context.Context, r *types.Request) (*types.Result, error) {
|
||||
result := r.NewResult()
|
||||
if r.State != types.Create {
|
||||
return result, nil
|
||||
}
|
||||
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
|
||||
}
|
||||
The plugin stub hides many of the low-level details of implementing an NRI
|
||||
plugin. It takes care of connection establishment, plugin registration,
|
||||
configuration, and event subscription. All [sample plugins](pkg/plugins)
|
||||
are implemented using the stub. Any of these can be used as a tutorial on
|
||||
how the stub library should be used.
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
if err := skel.Run(ctx, &clearCFS{}); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
```
|
||||
### Sample Plugins
|
||||
|
||||
## Project details
|
||||
The following sample plugins exist for NRI:
|
||||
|
||||
nri is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
|
||||
As a containerd sub-project, you will find the:
|
||||
- [logger](plugins/logger)
|
||||
- [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),
|
||||
* [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS),
|
||||
* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
|
||||
|
||||
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
||||
Please see the documentation of these plugins for further details
|
||||
about what and how each of these plugins can be used for.
|
||||
|
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/oci"
|
||||
types "github.com/containerd/nri/types/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -107,7 +106,7 @@ func (c *Client) InvokeWithSandbox(ctx context.Context, task containerd.Task, st
|
||||
r.Conf = p.Conf
|
||||
result, err := c.invokePlugin(ctx, p.Type, r)
|
||||
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)
|
||||
}
|
||||
@ -141,7 +140,7 @@ func (c *Client) invokePlugin(ctx context.Context, name string, r *types.Request
|
||||
}
|
||||
var result types.Result
|
||||
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 {
|
||||
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 (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// 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"`
|
||||
// Hostname configures the container's hostname.
|
||||
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 []Mount `json:"mounts,omitempty"`
|
||||
// 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 map[string]string `json:"annotations,omitempty"`
|
||||
|
||||
@ -27,6 +29,8 @@ type Spec struct {
|
||||
Windows *Windows `json:"windows,omitempty" platform:"windows"`
|
||||
// VM specifies configuration for virtual-machine-based containers.
|
||||
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.
|
||||
@ -49,7 +53,7 @@ type Process struct {
|
||||
// Capabilities are Linux capabilities that are kept for the process.
|
||||
Capabilities *LinuxCapabilities `json:"capabilities,omitempty" platform:"linux"`
|
||||
// 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 bool `json:"noNewPrivileges,omitempty" platform:"linux"`
|
||||
// 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.
|
||||
type User struct {
|
||||
// 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 uint32 `json:"gid" platform:"linux,solaris"`
|
||||
GID uint32 `json:"gid" platform:"linux,solaris,zos"`
|
||||
// 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 []uint32 `json:"additionalGids,omitempty" platform:"linux,solaris"`
|
||||
// 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 string `json:"destination"`
|
||||
// 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 string `json:"source,omitempty"`
|
||||
// Options are fstab style mount options.
|
||||
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
|
||||
@ -178,7 +187,7 @@ type Linux struct {
|
||||
// MountLabel specifies the selinux context for the mounts in the container.
|
||||
MountLabel string `json:"mountLabel,omitempty"`
|
||||
// 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"`
|
||||
// Personality contains configuration for the Linux personality syscall
|
||||
Personality *LinuxPersonality `json:"personality,omitempty"`
|
||||
@ -250,8 +259,8 @@ type LinuxInterfacePriority struct {
|
||||
Priority uint32 `json:"priority"`
|
||||
}
|
||||
|
||||
// linuxBlockIODevice holds major:minor format supported in blkio cgroup
|
||||
type linuxBlockIODevice struct {
|
||||
// LinuxBlockIODevice holds major:minor format supported in blkio cgroup
|
||||
type LinuxBlockIODevice struct {
|
||||
// Major is the device's major number.
|
||||
Major int64 `json:"major"`
|
||||
// Minor is the device's minor number.
|
||||
@ -260,7 +269,7 @@ type linuxBlockIODevice struct {
|
||||
|
||||
// LinuxWeightDevice struct holds a `major:minor weight` pair for weightDevice
|
||||
type LinuxWeightDevice struct {
|
||||
linuxBlockIODevice
|
||||
LinuxBlockIODevice
|
||||
// Weight is the bandwidth rate for the device.
|
||||
Weight *uint16 `json:"weight,omitempty"`
|
||||
// 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
|
||||
type LinuxThrottleDevice struct {
|
||||
linuxBlockIODevice
|
||||
LinuxBlockIODevice
|
||||
// Rate is the IO rate limit per cgroup per device
|
||||
Rate uint64 `json:"rate"`
|
||||
}
|
||||
@ -328,6 +337,8 @@ type LinuxCPU struct {
|
||||
Cpus string `json:"cpus,omitempty"`
|
||||
// List of memory nodes in the cpuset. Default is to use any available memory node.
|
||||
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)
|
||||
@ -522,11 +533,21 @@ type WindowsMemoryResources struct {
|
||||
|
||||
// WindowsCPUResources contains CPU resource management settings.
|
||||
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"`
|
||||
// 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"`
|
||||
// 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"`
|
||||
}
|
||||
|
||||
@ -613,6 +634,19 @@ type Arch string
|
||||
// LinuxSeccompFlag is a flag to pass to seccomp(2).
|
||||
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
|
||||
// By default only the native architecture of the kernel is permitted
|
||||
const (
|
||||
@ -683,8 +717,9 @@ type LinuxSyscall struct {
|
||||
Args []LinuxSeccompArg `json:"args,omitempty"`
|
||||
}
|
||||
|
||||
// LinuxIntelRdt has container runtime resource constraints for Intel RDT
|
||||
// CAT and MBA features which introduced in Linux 4.10 and 4.12 kernel
|
||||
// LinuxIntelRdt has container runtime resource constraints for Intel RDT CAT and MBA
|
||||
// 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 {
|
||||
// The identity for RDT Class of Service
|
||||
ClosID string `json:"closID,omitempty"`
|
||||
@ -697,4 +732,36 @@ type LinuxIntelRdt struct {
|
||||
// The unit of memory bandwidth is specified in "percentages" by
|
||||
// default, and in "MBps" if MBA Software Controller is enabled.
|
||||
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() {
|
||||
g.initConfig()
|
||||
if g.Config.Solaris == nil {
|
||||
@ -185,24 +192,3 @@ func (g *Generator) initConfigVM() {
|
||||
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"
|
||||
"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"
|
||||
)
|
||||
|
||||
@ -42,7 +42,7 @@ type ExportOptions struct {
|
||||
// New creates a configuration Generator with the default
|
||||
// configuration for the target operating system.
|
||||
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)
|
||||
}
|
||||
|
||||
@ -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.Env = []string{
|
||||
"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",
|
||||
Type: "tmpfs",
|
||||
Source: "tmpfs",
|
||||
Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
|
||||
Options: []string{"nosuid", "noexec", "strictatime", "mode=755", "size=65536k"},
|
||||
},
|
||||
{
|
||||
Destination: "/dev/pts",
|
||||
@ -237,6 +237,21 @@ func New(os string) (generator Generator, err error) {
|
||||
},
|
||||
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{}
|
||||
@ -249,10 +264,6 @@ func New(os string) (generator Generator, err error) {
|
||||
|
||||
// NewFromSpec creates a configuration Generator from a given
|
||||
// configuration.
|
||||
//
|
||||
// Deprecated: Replace with:
|
||||
//
|
||||
// generator := Generator{Config: config}
|
||||
func NewFromSpec(config *rspec.Spec) Generator {
|
||||
envCache := map[string]int{}
|
||||
if config != nil && config.Process != nil {
|
||||
@ -444,6 +455,13 @@ func (g *Generator) SetProcessUsername(username string) {
|
||||
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.
|
||||
func (g *Generator) SetProcessGID(gid uint32) {
|
||||
g.initConfigProcess()
|
||||
@ -597,6 +615,12 @@ func (g *Generator) SetLinuxCgroupsPath(path string) {
|
||||
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
|
||||
func (g *Generator) SetLinuxIntelRdtL3CacheSchema(schema string) {
|
||||
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.
|
||||
func (g *Generator) SetLinuxResourcesMemoryLimit(limit int64) {
|
||||
g.initConfigLinuxResourcesMemory()
|
||||
@ -1018,10 +1064,9 @@ func (g *Generator) ClearPreStartHooks() {
|
||||
}
|
||||
|
||||
// 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.Config.Hooks.Prestart = append(g.Config.Hooks.Prestart, preStartHook)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClearPostStopHooks clear g.Config.Hooks.Poststop.
|
||||
@ -1033,10 +1078,9 @@ func (g *Generator) ClearPostStopHooks() {
|
||||
}
|
||||
|
||||
// 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.Config.Hooks.Poststop = append(g.Config.Hooks.Poststop, postStopHook)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClearPostStartHooks clear g.Config.Hooks.Poststart.
|
||||
@ -1048,10 +1092,9 @@ func (g *Generator) ClearPostStartHooks() {
|
||||
}
|
||||
|
||||
// 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.Config.Hooks.Poststart = append(g.Config.Hooks.Poststart, postStartHook)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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.
|
||||
var finalCapList []string
|
||||
for _, cap := range capability.List() {
|
||||
if g.HostSpecific && cap > validate.LastCap() {
|
||||
if g.HostSpecific && cap > capsCheck.LastCap() {
|
||||
continue
|
||||
}
|
||||
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.
|
||||
func (g *Generator) AddProcessCapability(c string) error {
|
||||
cp := strings.ToUpper(c)
|
||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
||||
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1190,7 +1233,7 @@ func (g *Generator) AddProcessCapability(c string) error {
|
||||
// AddProcessCapabilityAmbient adds a process capability into g.Config.Process.Capabilities.Ambient.
|
||||
func (g *Generator) AddProcessCapabilityAmbient(c string) error {
|
||||
cp := strings.ToUpper(c)
|
||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
||||
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1214,7 +1257,7 @@ func (g *Generator) AddProcessCapabilityAmbient(c string) error {
|
||||
// AddProcessCapabilityBounding adds a process capability into g.Config.Process.Capabilities.Bounding.
|
||||
func (g *Generator) AddProcessCapabilityBounding(c string) error {
|
||||
cp := strings.ToUpper(c)
|
||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
||||
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1237,7 +1280,7 @@ func (g *Generator) AddProcessCapabilityBounding(c string) error {
|
||||
// AddProcessCapabilityEffective adds a process capability into g.Config.Process.Capabilities.Effective.
|
||||
func (g *Generator) AddProcessCapabilityEffective(c string) error {
|
||||
cp := strings.ToUpper(c)
|
||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
||||
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1260,7 +1303,7 @@ func (g *Generator) AddProcessCapabilityEffective(c string) error {
|
||||
// AddProcessCapabilityInheritable adds a process capability into g.Config.Process.Capabilities.Inheritable.
|
||||
func (g *Generator) AddProcessCapabilityInheritable(c string) error {
|
||||
cp := strings.ToUpper(c)
|
||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
||||
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -1283,7 +1326,7 @@ func (g *Generator) AddProcessCapabilityInheritable(c string) error {
|
||||
// AddProcessCapabilityPermitted adds a process capability into g.Config.Process.Capabilities.Permitted.
|
||||
func (g *Generator) AddProcessCapabilityPermitted(c string) error {
|
||||
cp := strings.ToUpper(c)
|
||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
||||
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||
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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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) {
|
||||
@ -1495,9 +1538,6 @@ func (g *Generator) AddDevice(device rspec.LinuxDevice) {
|
||||
g.Config.Linux.Devices[i] = device
|
||||
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)
|
||||
@ -1556,12 +1596,8 @@ func (g *Generator) RemoveLinuxResourcesDevice(allow bool, devType string, major
|
||||
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
|
||||
func (g *Generator) SetSyscallAction(arguments seccomp.SyscallOpts) error {
|
||||
g.initConfigLinuxSeccomp()
|
||||
@ -1581,6 +1617,12 @@ func (g *Generator) SetDefaultSeccompActionForce(action string) error {
|
||||
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
|
||||
func (g *Generator) SetSeccompArchitecture(architecture string) error {
|
||||
g.initConfigLinuxSeccomp()
|
||||
@ -1687,14 +1729,14 @@ func (g *Generator) SetVMHypervisorPath(path string) error {
|
||||
if !strings.HasPrefix(path, "/") {
|
||||
return fmt.Errorf("hypervisorPath %v is not an absolute path", path)
|
||||
}
|
||||
g.initConfigVMHypervisor()
|
||||
g.initConfigVM()
|
||||
g.Config.VM.Hypervisor.Path = path
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetVMHypervisorParameters sets g.Config.VM.Hypervisor.Parameters
|
||||
func (g *Generator) SetVMHypervisorParameters(parameters []string) {
|
||||
g.initConfigVMHypervisor()
|
||||
g.initConfigVM()
|
||||
g.Config.VM.Hypervisor.Parameters = parameters
|
||||
}
|
||||
|
||||
@ -1703,14 +1745,14 @@ func (g *Generator) SetVMKernelPath(path string) error {
|
||||
if !strings.HasPrefix(path, "/") {
|
||||
return fmt.Errorf("kernelPath %v is not an absolute path", path)
|
||||
}
|
||||
g.initConfigVMKernel()
|
||||
g.initConfigVM()
|
||||
g.Config.VM.Kernel.Path = path
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetVMKernelParameters sets g.Config.VM.Kernel.Parameters
|
||||
func (g *Generator) SetVMKernelParameters(parameters []string) {
|
||||
g.initConfigVMKernel()
|
||||
g.initConfigVM()
|
||||
g.Config.VM.Kernel.Parameters = parameters
|
||||
}
|
||||
|
||||
@ -1719,7 +1761,7 @@ func (g *Generator) SetVMKernelInitRD(initrd string) error {
|
||||
if !strings.HasPrefix(initrd, "/") {
|
||||
return fmt.Errorf("kernelInitrd %v is not an absolute path", initrd)
|
||||
}
|
||||
g.initConfigVMKernel()
|
||||
g.initConfigVM()
|
||||
g.Config.VM.Kernel.InitRD = initrd
|
||||
return nil
|
||||
}
|
||||
@ -1729,7 +1771,7 @@ func (g *Generator) SetVMImagePath(path string) error {
|
||||
if !strings.HasPrefix(path, "/") {
|
||||
return fmt.Errorf("imagePath %v is not an absolute path", path)
|
||||
}
|
||||
g.initConfigVMImage()
|
||||
g.initConfigVM()
|
||||
g.Config.VM.Image.Path = path
|
||||
return nil
|
||||
}
|
||||
@ -1745,7 +1787,7 @@ func (g *Generator) SetVMImageFormat(format string) error {
|
||||
default:
|
||||
return fmt.Errorf("Commonly supported formats are: raw, qcow2, vdi, vmdk, vhd")
|
||||
}
|
||||
g.initConfigVMImage()
|
||||
g.initConfigVM()
|
||||
g.Config.VM.Image.Format = format
|
||||
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"
|
||||
seccompAppend = "append"
|
||||
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",
|
||||
"ipc",
|
||||
"kill",
|
||||
"landlock_add_rule",
|
||||
"landlock_create_ruleset",
|
||||
"landlock_restrict_self",
|
||||
"lchown",
|
||||
"lchown32",
|
||||
"lgetxattr",
|
||||
@ -303,6 +306,7 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
|
||||
"stat64",
|
||||
"statfs",
|
||||
"statfs64",
|
||||
"statx",
|
||||
"symlink",
|
||||
"symlinkat",
|
||||
"sync",
|
||||
@ -353,11 +357,23 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
|
||||
Value: 0x0,
|
||||
Op: rspec.OpEqualTo,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Names: []string{"personality"},
|
||||
Action: rspec.ActAllow,
|
||||
Args: []rspec.LinuxSeccompArg{
|
||||
{
|
||||
Index: 0,
|
||||
Value: 0x0008,
|
||||
Op: rspec.OpEqualTo,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Names: []string{"personality"},
|
||||
Action: rspec.ActAllow,
|
||||
Args: []rspec.LinuxSeccompArg{
|
||||
{
|
||||
Index: 0,
|
||||
Value: 0xffffffff,
|
||||
@ -512,7 +528,7 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
|
||||
Args: []rspec.LinuxSeccompArg{
|
||||
{
|
||||
Index: sysCloneFlagsIndex,
|
||||
Value: CloneNewNS | CloneNewUTS | CloneNewIPC | CloneNewUser | CloneNewPID | CloneNewNet,
|
||||
Value: CloneNewNS | CloneNewUTS | CloneNewIPC | CloneNewUser | CloneNewPID | CloneNewNet | CloneNewCgroup,
|
||||
ValueTwo: 0,
|
||||
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 */
|
||||
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{
|
||||
|
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
|
||||
|
||||
package seccomp
|
||||
|
||||
import "syscall"
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
// System values passed through on linux
|
||||
const (
|
||||
CloneNewIPC = syscall.CLONE_NEWIPC
|
||||
CloneNewNet = syscall.CLONE_NEWNET
|
||||
CloneNewNS = syscall.CLONE_NEWNS
|
||||
CloneNewPID = syscall.CLONE_NEWPID
|
||||
CloneNewUser = syscall.CLONE_NEWUSER
|
||||
CloneNewUTS = syscall.CLONE_NEWUTS
|
||||
CloneNewIPC = unix.CLONE_NEWIPC
|
||||
CloneNewNet = unix.CLONE_NEWNET
|
||||
CloneNewNS = unix.CLONE_NEWNS
|
||||
CloneNewPID = unix.CLONE_NEWPID
|
||||
CloneNewUser = unix.CLONE_NEWUSER
|
||||
CloneNewUTS = unix.CLONE_NEWUTS
|
||||
CloneNewCgroup = unix.CLONE_NEWCGROUP
|
||||
)
|
||||
|
@ -1,3 +1,4 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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 {
|
||||
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