diff --git a/pkg/server/container_start.go b/pkg/server/container_start.go index c1f860d59..d00eb3d8e 100644 --- a/pkg/server/container_start.go +++ b/pkg/server/container_start.go @@ -24,6 +24,8 @@ 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/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/net/context" @@ -107,7 +109,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, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { + if _, err := task.Delete(deferCtx, WithNRISandboxDelete(sandboxID), containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { log.G(ctx).WithError(err).Errorf("Failed to delete containerd task %q", id) } } @@ -118,6 +120,18 @@ func (c *criService) StartContainer(ctx context.Context, r *runtime.StartContain if err != nil { return nil, errors.Wrap(err, "failed to wait for containerd task") } + 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, + } + if _, err := nric.InvokeWithSandbox(ctx, task, v1.Create, nriSB); err != nil { + return nil, errors.Wrap(err, "nri invoke") + } + } // Start containerd task. if err := task.Start(ctx); err != nil { diff --git a/pkg/server/events.go b/pkg/server/events.go index df465f22c..8f35bf0bd 100644 --- a/pkg/server/events.go +++ b/pkg/server/events.go @@ -317,7 +317,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, containerd.WithProcessKill); err != nil { + if _, err = task.Delete(ctx, WithNRISandboxDelete(cntr.SandboxID), containerd.WithProcessKill); err != nil { if !errdefs.IsNotFound(err) { return errors.Wrap(err, "failed to stop container") } @@ -359,7 +359,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, containerd.WithProcessKill); err != nil { + if _, err = task.Delete(ctx, WithNRISandboxDelete(sb.ID), containerd.WithProcessKill); err != nil { if !errdefs.IsNotFound(err) { return errors.Wrap(err, "failed to stop sandbox") } diff --git a/pkg/server/opts.go b/pkg/server/opts.go new file mode 100644 index 000000000..58520dbc3 --- /dev/null +++ b/pkg/server/opts.go @@ -0,0 +1,51 @@ +/* + 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 + } +} diff --git a/pkg/server/sandbox_run.go b/pkg/server/sandbox_run.go index 1fc92adbf..e4b46e26b 100644 --- a/pkg/server/sandbox_run.go +++ b/pkg/server/sandbox_run.go @@ -27,6 +27,8 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/log" 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" "github.com/pkg/errors" @@ -269,7 +271,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, containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { + if _, err := task.Delete(deferCtx, WithNRISandboxDelete(id), containerd.WithProcessKill); err != nil && !errdefs.IsNotFound(err) { log.G(ctx).WithError(err).Errorf("Failed to delete sandbox container %q", id) } } @@ -281,6 +283,20 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox return nil, errors.Wrap(err, "failed to wait for sandbox container task") } + nric, err := nri.New() + if err != nil { + return nil, errors.Wrap(err, "unable to create nri client") + } + if nric != nil { + nriSB := &nri.Sandbox{ + ID: id, + Labels: config.Labels, + } + if _, err := nric.InvokeWithSandbox(ctx, task, v1.Create, nriSB); err != nil { + return nil, errors.Wrap(err, "nri invoke") + } + } + if err := task.Start(ctx); err != nil { return nil, errors.Wrapf(err, "failed to start sandbox container task %q", id) } diff --git a/vendor.conf b/vendor.conf index 3e0494a49..7d76da660 100644 --- a/vendor.conf +++ b/vendor.conf @@ -14,6 +14,7 @@ github.com/containerd/containerd v1.4.0 github.com/containerd/continuity efbc4488d8fe1bdc16bde3b2d2990d9b3a899165 github.com/containerd/fifo f15a3290365b9d2627d189e619ab4008e0069caf github.com/containerd/go-runc 7016d3ce2328dd2cb1192b2076ebd565c4e8df0c +github.com/containerd/nri 0afc7f031eaf9c7d9c1a381b7ab5462e89c998fc github.com/containerd/ttrpc v1.0.1 github.com/containerd/typeurl v1.0.1 github.com/coreos/go-systemd/v22 v22.1.0 diff --git a/vendor/github.com/containerd/nri/LICENSE b/vendor/github.com/containerd/nri/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/vendor/github.com/containerd/nri/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/github.com/containerd/nri/README.md b/vendor/github.com/containerd/nri/README.md new file mode 100644 index 000000000..63bfbb998 --- /dev/null +++ b/vendor/github.com/containerd/nri/README.md @@ -0,0 +1,163 @@ +# nri - Node Resource Interface + +*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** + +Clear the cfs quotas for `ls` services. + + +```go +package main + +import ( + "context" + "fmt" + "os" + + "github.com/containerd/containerd/pkg/nri/skel" + "github.com/containerd/containerd/pkg/nri/types" + "github.com/sirupsen/logrus" +) + +var max = []byte("max") + +// clearCFS clears any cfs quotas for the containers +type clearCFS struct { +} + +func (c *clearCFS) Type() string { + return "clearcfs" +} + +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 +} + +func main() { + ctx := context.Background() + if err := skel.Run(ctx, &clearCFS{}); err != nil { + fmt.Fprintf(os.Stderr, "%s", err) + os.Exit(1) + } +} +``` + +## 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/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. diff --git a/vendor/github.com/containerd/nri/client.go b/vendor/github.com/containerd/nri/client.go new file mode 100644 index 000000000..6b6c6e409 --- /dev/null +++ b/vendor/github.com/containerd/nri/client.go @@ -0,0 +1,165 @@ +package nri + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "os" + "os/exec" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/oci" + types "github.com/containerd/nri/types/v1" + "github.com/pkg/errors" +) + +const ( + // DefaultBinaryPath for nri plugins + DefaultBinaryPath = "/opt/nri/bin" + // DefaultConfPath for the global nri configuration + DefaultConfPath = "/etc/nri/conf.json" + // Version of NRI + Version = "0.1" +) + +// New nri client +func New() (*Client, error) { + conf, err := loadConfig(DefaultConfPath) + if err != nil { + return nil, err + } + if err := os.Setenv("PATH", fmt.Sprintf("%s:%s", os.Getenv("PATH"), DefaultBinaryPath)); err != nil { + return nil, err + } + return &Client{ + conf: conf, + }, nil +} + +// Client for calling nri plugins +type Client struct { + conf *types.ConfigList +} + +// Sandbox information +type Sandbox struct { + // ID of the sandbox + ID string + // Labels of the sandbox + Labels map[string]string +} + +// Invoke the ConfList of nri plugins +func (c *Client) Invoke(ctx context.Context, task containerd.Task, state types.State) ([]*types.Result, error) { + return c.InvokeWithSandbox(ctx, task, state, nil) +} + +// Invoke the ConfList of nri plugins +func (c *Client) InvokeWithSandbox(ctx context.Context, task containerd.Task, state types.State, sandbox *Sandbox) ([]*types.Result, error) { + if len(c.conf.Plugins) == 0 { + return nil, nil + } + spec, err := task.Spec(ctx) + if err != nil { + return nil, err + } + rs, err := createSpec(spec) + if err != nil { + return nil, err + } + r := &types.Request{ + Version: c.conf.Version, + ID: task.ID(), + Pid: int(task.Pid()), + State: state, + Spec: rs, + } + if sandbox != nil { + r.SandboxID = sandbox.ID + r.Labels = sandbox.Labels + } + for _, p := range c.conf.Plugins { + r.Conf = p.Conf + result, err := c.invokePlugin(ctx, p.Type, r) + if err != nil { + return nil, errors.Wrapf(err, "plugin: %s", p.Type) + } + r.Results = append(r.Results, result) + } + return r.Results, nil +} + +func (c *Client) invokePlugin(ctx context.Context, name string, r *types.Request) (*types.Result, error) { + payload, err := json.Marshal(r) + if err != nil { + return nil, err + } + cmd := exec.CommandContext(ctx, name, "invoke") + cmd.Stdin = bytes.NewBuffer(payload) + cmd.Stderr = os.Stderr + + out, err := cmd.Output() + if err != nil { + // ExitError is returned when there is a non-zero exit status + if _, ok := err.(*exec.ExitError); ok { + var pe types.PluginError + if err := json.Unmarshal(out, &pe); err != nil { + return nil, errors.Wrapf(err, "%s: %s", name, out) + } + return nil, &pe + } + return nil, errors.Wrapf(err, "%s: %s", name, out) + } + var result types.Result + if err := json.Unmarshal(out, &result); err != nil { + return nil, err + } + return &result, nil +} + +func loadConfig(path string) (*types.ConfigList, error) { + f, err := os.Open(path) + if err != nil { + // if we don't have a config list on disk, create a new one for use + if os.IsNotExist(err) { + return &types.ConfigList{ + Version: Version, + }, nil + } + return nil, err + } + var c types.ConfigList + err = json.NewDecoder(f).Decode(&c) + f.Close() + if err != nil { + return nil, err + } + return &c, nil +} + +func createSpec(spec *oci.Spec) (*types.Spec, error) { + s := types.Spec{ + Namespaces: make(map[string]string), + Annotations: spec.Annotations, + } + switch { + case spec.Linux != nil: + s.CgroupsPath = spec.Linux.CgroupsPath + data, err := json.Marshal(spec.Linux.Resources) + if err != nil { + return nil, err + } + s.Resources = json.RawMessage(data) + for _, ns := range spec.Linux.Namespaces { + s.Namespaces[string(ns.Type)] = ns.Path + } + case spec.Windows != nil: + data, err := json.Marshal(spec.Windows.Resources) + if err != nil { + return nil, err + } + s.Resources = json.RawMessage(data) + } + return &s, nil +} diff --git a/vendor/github.com/containerd/nri/go.mod b/vendor/github.com/containerd/nri/go.mod new file mode 100644 index 000000000..1de3c01e5 --- /dev/null +++ b/vendor/github.com/containerd/nri/go.mod @@ -0,0 +1,30 @@ +module github.com/containerd/nri + +go 1.14 + +require ( + github.com/Microsoft/hcsshim v0.8.9 // indirect + github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340 // indirect + github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410 + github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe // indirect + github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b // indirect + github.com/containerd/ttrpc v1.0.1 // indirect + github.com/containerd/typeurl v1.0.1 // indirect + github.com/docker/distribution v2.7.1+incompatible // indirect + github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect + github.com/gogo/googleapis v1.4.0 // indirect + github.com/google/go-cmp v0.5.1 // indirect + github.com/google/uuid v1.1.1 // indirect + github.com/imdario/mergo v0.3.10 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.1 // indirect + github.com/opencontainers/runc v0.1.1 // indirect + github.com/opencontainers/selinux v1.6.0 // indirect + github.com/pkg/errors v0.9.1 + github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 // indirect + go.etcd.io/bbolt v1.3.5 // indirect + golang.org/x/net v0.0.0-20200707034311-ab3426394381 // indirect + golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 // indirect + golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1 // indirect + google.golang.org/grpc v1.30.0 // indirect +) diff --git a/vendor/github.com/containerd/nri/types/v1/types.go b/vendor/github.com/containerd/nri/types/v1/types.go new file mode 100644 index 000000000..e0703f5a0 --- /dev/null +++ b/vendor/github.com/containerd/nri/types/v1/types.go @@ -0,0 +1,119 @@ +package v1 + +import ( + "encoding/json" + "fmt" +) + +// Plugin type and configuration +type Plugin struct { + // Type of plugin + Type string `json:"type"` + // Conf for the specific plugin + Conf json.RawMessage `json:"conf,omitempty"` +} + +// ConfigList for the global configuration of NRI +// +// Normally located at /etc/nri/conf.json +type ConfigList struct { + // Verion of the list + Version string `json:"version"` + // Plugins + Plugins []*Plugin `json:"plugins"` +} + +// Spec for the container being processed +type Spec struct { + // Resources struct from the OCI specification + // + // Can be WindowsResources or LinuxResources + Resources json.RawMessage `json:"resources"` + // Namespaces for the container + Namespaces map[string]string `json:"namespaces,omitempty"` + // CgroupsPath for the container + CgroupsPath string `json:"cgroupsPath,omitempty"` + // Annotations passed down to the OCI runtime specification + Annotations map[string]string `json:"annotations,omitempty"` +} + +// State of the request +type State string + +const ( + // Create the initial resource for the container + Create State = "create" + // Delete any resources for the container + Delete State = "delete" + // Update the resources for the container + Update State = "update" + // Pause action of the container + Pause State = "pause" + // Resume action for the container + Resume State = "resume" +) + +// Request for a plugin invocation +type Request struct { + // Conf specific for the plugin + Conf json.RawMessage `json:"conf,omitempty"` + + // Version of the plugin + Version string `json:"version"` + // State action for the request + State State `json:"state"` + // ID for the container + ID string `json:"id"` + // SandboxID for the sandbox that the request belongs to + // + // If ID and SandboxID are the same, this is a request for the sandbox + // SandboxID is empty for a non sandboxed container + SandboxID string `json:"sandboxID,omitempty"` + // Pid of the container + // + // -1 if there is no pid + Pid int `json:"pid,omitempty"` + // Spec generated from the OCI runtime specification + Spec *Spec `json:"spec"` + // Labels of a sandbox + Labels map[string]string `json:"labels,omitempty"` + // Results from previous plugins in the chain + Results []*Result `json:"results,omitempty"` +} + +// PluginError for specific plugin execution +type PluginError struct { + // Plugin name + Plugin string `json:"plugin"` + // Message for the error + Message string `json:"message"` +} + +// Error as a string +func (p *PluginError) Error() string { + return fmt.Sprintf("%s: %s", p.Plugin, p.Message) +} + +// IsSandbox returns true if the request is for a sandbox +func (r *Request) IsSandbox() bool { + return r.ID == r.SandboxID +} + +// NewResult returns a result from the original request +func (r *Request) NewResult(plugin string) *Result { + return &Result{ + Plugin: plugin, + Version: r.Version, + Metadata: make(map[string]string), + } +} + +// Result of the plugin invocation +type Result struct { + // Plugin name that populated the result + Plugin string `json:"plugin"` + // Version of the plugin + Version string `json:"version"` + // Metadata specific to actions taken by the plugin + Metadata map[string]string `json:"metadata,omitempty"` +}