nri: add experimental NRI plugin.
Add a common NRI 'service' plugin. It takes care of relaying requests and respones to and from NRI (external NRI plugins) and the high-level containerd namespace-independent logic of applying NRI container adjustments and updates to actual CRI and other containers. The namespace-dependent details of the necessary container manipulation operations are to be implemented by namespace- specific adaptations. This NRI plugin defines the API which such adaptations need to implement. Signed-off-by: Krisztian Litkey <krisztian.litkey@intel.com>
This commit is contained in:
parent
e0be97ccee
commit
43704ca888
@ -23,6 +23,7 @@ import (
|
|||||||
_ "github.com/containerd/containerd/gc/scheduler"
|
_ "github.com/containerd/containerd/gc/scheduler"
|
||||||
_ "github.com/containerd/containerd/leases/plugin"
|
_ "github.com/containerd/containerd/leases/plugin"
|
||||||
_ "github.com/containerd/containerd/metadata/plugin"
|
_ "github.com/containerd/containerd/metadata/plugin"
|
||||||
|
_ "github.com/containerd/containerd/pkg/nri/plugin"
|
||||||
_ "github.com/containerd/containerd/runtime/restart/monitor"
|
_ "github.com/containerd/containerd/runtime/restart/monitor"
|
||||||
_ "github.com/containerd/containerd/runtime/v2"
|
_ "github.com/containerd/containerd/runtime/v2"
|
||||||
_ "github.com/containerd/containerd/services/containers"
|
_ "github.com/containerd/containerd/services/containers"
|
||||||
|
22
go.mod
22
go.mod
@ -17,7 +17,9 @@ require (
|
|||||||
github.com/containerd/go-cni v1.1.6
|
github.com/containerd/go-cni v1.1.6
|
||||||
github.com/containerd/go-runc v1.0.0
|
github.com/containerd/go-runc v1.0.0
|
||||||
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028
|
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028
|
||||||
github.com/containerd/nri v0.1.0
|
// We need an NRI with the updated interface. We use a replace to
|
||||||
|
// divert it until the corresponding PR lands in the NRI repo.
|
||||||
|
github.com/containerd/nri v0.2.0
|
||||||
github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3
|
github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3
|
||||||
github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67
|
github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67
|
||||||
github.com/containerd/zfs v1.0.0
|
github.com/containerd/zfs v1.0.0
|
||||||
@ -47,7 +49,7 @@ require (
|
|||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
|
||||||
github.com/opencontainers/runc v1.1.4
|
github.com/opencontainers/runc v1.1.4
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb
|
||||||
github.com/opencontainers/selinux v1.10.2
|
github.com/opencontainers/selinux v1.10.2
|
||||||
github.com/pelletier/go-toml v1.9.3
|
github.com/pelletier/go-toml v1.9.3
|
||||||
github.com/prometheus/client_golang v1.12.1
|
github.com/prometheus/client_golang v1.12.1
|
||||||
@ -82,7 +84,6 @@ require (
|
|||||||
require (
|
require (
|
||||||
cloud.google.com/go/compute/metadata v0.2.1 // indirect
|
cloud.google.com/go/compute/metadata v0.2.1 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
|
||||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
@ -106,7 +107,9 @@ require (
|
|||||||
github.com/moby/spdystream v0.2.0 // indirect
|
github.com/moby/spdystream v0.2.0 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e // indirect
|
// 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 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
@ -117,9 +120,6 @@ require (
|
|||||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
|
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
|
||||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
|
||||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
|
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
|
||||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect
|
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect
|
||||||
go.opencensus.io v0.23.0 // indirect
|
go.opencensus.io v0.23.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 // indirect
|
||||||
@ -131,7 +131,7 @@ require (
|
|||||||
golang.org/x/term v0.1.0 // indirect
|
golang.org/x/term v0.1.0 // indirect
|
||||||
golang.org/x/text v0.4.0 // indirect
|
golang.org/x/text v0.4.0 // indirect
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
||||||
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854 // indirect
|
golang.org/x/tools v0.2.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||||
@ -141,3 +141,9 @@ require (
|
|||||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace (
|
||||||
|
// Temporarily divert repo for updated/extended NRI.
|
||||||
|
github.com/containerd/nri => github.com/klihub/nri v0.0.0-20221122201439-2b09b4ad5cf3
|
||||||
|
github.com/opencontainers/runtime-tools => github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809
|
||||||
|
)
|
||||||
|
83
go.sum
83
go.sum
@ -76,6 +76,7 @@ github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JP
|
|||||||
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
|
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||||
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||||
@ -89,6 +90,7 @@ github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwT
|
|||||||
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
||||||
github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
|
github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
|
||||||
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
||||||
|
github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
||||||
github.com/Microsoft/hcsshim v0.10.0-rc.1 h1:Lms8jwpaIdIUvoBNee8ZuvIi1XnNy9uvnxSC9L1q1x4=
|
github.com/Microsoft/hcsshim v0.10.0-rc.1 h1:Lms8jwpaIdIUvoBNee8ZuvIi1XnNy9uvnxSC9L1q1x4=
|
||||||
github.com/Microsoft/hcsshim v0.10.0-rc.1/go.mod h1:7XX96hdvnwWGdXnksDNdhfFcUH1BtQY6bL2L3f9Abyk=
|
github.com/Microsoft/hcsshim v0.10.0-rc.1/go.mod h1:7XX96hdvnwWGdXnksDNdhfFcUH1BtQY6bL2L3f9Abyk=
|
||||||
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
|
||||||
@ -129,7 +131,6 @@ github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngE
|
|||||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||||
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
|
||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||||
@ -173,6 +174,7 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP
|
|||||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
|
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
|
||||||
@ -192,7 +194,6 @@ github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2v
|
|||||||
github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
|
github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
|
||||||
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
||||||
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
|
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
|
||||||
github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
|
|
||||||
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
|
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
|
||||||
github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
|
github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
|
||||||
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
|
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
|
||||||
@ -213,7 +214,6 @@ github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.
|
|||||||
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
|
||||||
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
@ -225,6 +225,7 @@ github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTV
|
|||||||
github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
|
github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
|
||||||
github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
|
github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
|
||||||
github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE=
|
github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE=
|
||||||
|
github.com/containerd/containerd v1.6.9/go.mod h1:XVicUvkxOrftE2Q1YWUXgZwkkAxwQYNOFzYWvfVfEfQ=
|
||||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
@ -237,7 +238,6 @@ github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvA
|
|||||||
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
|
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
|
||||||
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||||
github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
|
|
||||||
github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
|
github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
|
||||||
github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
|
github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
|
||||||
github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU=
|
github.com/containerd/fifo v1.0.0 h1:6PirWBr9/L7GDamKr+XM0IeUFXu5mf3M/BPpH9gaLBU=
|
||||||
@ -259,12 +259,9 @@ github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6T
|
|||||||
github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow=
|
github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow=
|
||||||
github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
|
github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms=
|
||||||
github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4=
|
github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4=
|
||||||
|
github.com/containerd/imgcrypt v1.1.4/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
|
||||||
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028 h1:CqFTne8EGv2eAWAS0O6weGE5RtP0Q8XiFUdkDT840Yc=
|
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028 h1:CqFTne8EGv2eAWAS0O6weGE5RtP0Q8XiFUdkDT840Yc=
|
||||||
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
|
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
|
||||||
github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c=
|
|
||||||
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
|
||||||
github.com/containerd/nri v0.1.0 h1:6QioHRlThlKh2RkRTR4kIT3PKAcrLo3gIWnjkM4dQmQ=
|
|
||||||
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
|
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
|
||||||
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||||
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||||
@ -377,6 +374,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
|
|||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
@ -504,6 +502,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
|
github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
|
||||||
@ -624,6 +623,8 @@ github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
|
|||||||
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
||||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||||
|
github.com/klihub/nri v0.0.0-20221122201439-2b09b4ad5cf3 h1:8V9PThT2f1pBaGz0lSJ6EtLnIuxKEz5utRh1/8tHD0U=
|
||||||
|
github.com/klihub/nri v0.0.0-20221122201439-2b09b4ad5cf3/go.mod h1:Q2u9Sudol4IkJ6YK0gShznKMxM6Un0Y3O4Wslf5Nerg=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
@ -674,6 +675,7 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
|
|||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||||
|
github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
|
||||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||||
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||||
@ -709,6 +711,7 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
|
|||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||||
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||||
|
github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
@ -729,7 +732,12 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k
|
|||||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||||
github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU=
|
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.5.0 h1:TRtrvv2vdQqzkwrQ1ke6vtXf7IK34RBUJafIy1wMwls=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
|
||||||
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
@ -740,7 +748,12 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
|
|||||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||||
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
|
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
|
||||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||||
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||||
|
github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
|
||||||
|
github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
|
||||||
|
github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
|
||||||
|
github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg=
|
||||||
|
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
@ -751,15 +764,16 @@ github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM
|
|||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
|
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||||
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
|
||||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
||||||
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||||
github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
|
github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
|
||||||
|
github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
|
||||||
github.com/opencontainers/runc v1.1.4 h1:nRCz/8sKg6K6jgYAFLDlXzPeITBZJyX28DBVhWD+5dg=
|
github.com/opencontainers/runc v1.1.4 h1:nRCz/8sKg6K6jgYAFLDlXzPeITBZJyX28DBVhWD+5dg=
|
||||||
github.com/opencontainers/runc v1.1.4/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
|
github.com/opencontainers/runc v1.1.4/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
|
||||||
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
@ -767,15 +781,16 @@ github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/
|
|||||||
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
|
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb h1:1xSVPOd7/UA+39/hXEGnBJ13p6JFB0E1EvQFlrRDOXI=
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e h1:2Tg49TNXSTIsX8AAtmo1aQ1IbfnoUFzkOp7p2iWygtc=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809 h1:WSwkWIIS4s+E/dPF6HuVZ/hnq1WfXN371eESjREnU8k=
|
||||||
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI=
|
||||||
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
||||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||||
|
github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||||
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||||
|
github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||||
github.com/opencontainers/selinux v1.10.2 h1:NFy2xCsjn7+WspbfZkUd5zyVeisV7VFbPSP96+8/ha4=
|
github.com/opencontainers/selinux v1.10.2 h1:NFy2xCsjn7+WspbfZkUd5zyVeisV7VFbPSP96+8/ha4=
|
||||||
github.com/opencontainers/selinux v1.10.2/go.mod h1:cARutUbaUrlRClyvxOICCgKixCs6L05aUsohzA3EkHQ=
|
github.com/opencontainers/selinux v1.10.2/go.mod h1:cARutUbaUrlRClyvxOICCgKixCs6L05aUsohzA3EkHQ=
|
||||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
@ -801,6 +816,7 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
|
|||||||
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
|
||||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||||
|
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
|
||||||
github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
|
github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
|
||||||
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||||
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
@ -916,6 +932,7 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1
|
|||||||
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
|
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
|
||||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
|
github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
@ -931,7 +948,6 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17
|
|||||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
|
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
|
||||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
|
||||||
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
|
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
@ -947,6 +963,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||||
@ -1038,6 +1056,8 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
@ -1075,6 +1095,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -1131,8 +1153,14 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
|
|||||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
golang.org/x/net v0.1.1-0.20221027164007-c63010009c80 h1:CtRWmqbiPSOXwJV1JoY7pWiTx2xzVKQ813bvU+Y/9jI=
|
golang.org/x/net v0.1.1-0.20221027164007-c63010009c80 h1:CtRWmqbiPSOXwJV1JoY7pWiTx2xzVKQ813bvU+Y/9jI=
|
||||||
golang.org/x/net v0.1.1-0.20221027164007-c63010009c80/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
golang.org/x/net v0.1.1-0.20221027164007-c63010009c80/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
@ -1161,6 +1189,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -1256,19 +1285,26 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
|
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
|
||||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@ -1355,9 +1391,12 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
|
|||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854 h1:fzDvmJnoyma87dC7IBnNQWmMZNalsNrtiY1X6PwmME0=
|
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||||
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854/go.mod h1:VsjNM1dMo+Ofkp5d7y7fOdQZD8MTXSQ4w3EPk65AvKU=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||||
|
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -1443,6 +1482,7 @@ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxH
|
|||||||
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||||
|
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
|
||||||
google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd h1:1eV6KuDTxraYYsYGWksp1thEGP+8dtX/TINL9h+ppiI=
|
google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd h1:1eV6KuDTxraYYsYGWksp1thEGP+8dtX/TINL9h+ppiI=
|
||||||
google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
@ -1473,6 +1513,8 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
|
|||||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
|
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||||
|
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||||
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
|
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
|
||||||
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
@ -1488,6 +1530,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
|
|||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||||
@ -1576,6 +1619,8 @@ k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
|
|||||||
k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
|
k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
|
||||||
k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
|
k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
|
||||||
k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4=
|
k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4=
|
||||||
|
k8s.io/cri-api v0.25.0/go.mod h1:J1rAyQkSJ2Q6I+aBMOVgg2/cbbebso6FNa0UagiR0kc=
|
||||||
|
k8s.io/cri-api v0.25.3/go.mod h1:riC/P0yOGUf2K1735wW+CXs1aY2ctBgePtnnoFLd0dU=
|
||||||
k8s.io/cri-api v0.26.0-beta.0 h1:mVt2/80VZy2dRN4mpVYJbPB9L/Zt/EvVev++zPTV9Tw=
|
k8s.io/cri-api v0.26.0-beta.0 h1:mVt2/80VZy2dRN4mpVYJbPB9L/Zt/EvVev++zPTV9Tw=
|
||||||
k8s.io/cri-api v0.26.0-beta.0/go.mod h1:E49tenyB7esgfIguEd7+g9qYhHOr9peyyBcSaeH6Gxw=
|
k8s.io/cri-api v0.26.0-beta.0/go.mod h1:E49tenyB7esgfIguEd7+g9qYhHOr9peyyBcSaeH6Gxw=
|
||||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
|
@ -13,7 +13,7 @@ require (
|
|||||||
github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67
|
github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67
|
||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.0
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
golang.org/x/sys v0.2.0
|
golang.org/x/sys v0.2.0
|
||||||
@ -58,7 +58,7 @@ require (
|
|||||||
golang.org/x/net v0.1.1-0.20221027164007-c63010009c80 // indirect
|
golang.org/x/net v0.1.1-0.20221027164007-c63010009c80 // indirect
|
||||||
golang.org/x/sync v0.1.0 // indirect
|
golang.org/x/sync v0.1.0 // indirect
|
||||||
golang.org/x/text v0.4.0 // indirect
|
golang.org/x/text v0.4.0 // indirect
|
||||||
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854 // indirect
|
golang.org/x/tools v0.2.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd // indirect
|
google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd // indirect
|
||||||
google.golang.org/grpc v1.50.1 // indirect
|
google.golang.org/grpc v1.50.1 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
@ -70,4 +70,10 @@ require (
|
|||||||
// IMPORTANT: this replace rule ONLY replaces containerd itself; dependencies
|
// IMPORTANT: this replace rule ONLY replaces containerd itself; dependencies
|
||||||
// in the "require" section above are still taken into account for version
|
// in the "require" section above are still taken into account for version
|
||||||
// resolution if newer.
|
// resolution if newer.
|
||||||
replace github.com/containerd/containerd => ../../
|
replace (
|
||||||
|
github.com/containerd/containerd => ../../
|
||||||
|
|
||||||
|
// Temporarily divert repo for updated/extended NRI.
|
||||||
|
github.com/containerd/nri => github.com/klihub/nri v0.0.0-20221122201439-2b09b4ad5cf3
|
||||||
|
github.com/opencontainers/runtime-tools => github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809
|
||||||
|
)
|
||||||
|
@ -390,6 +390,7 @@ github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2B
|
|||||||
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
|
||||||
github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
|
||||||
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
||||||
|
github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
|
||||||
github.com/Microsoft/hcsshim v0.10.0-rc.1 h1:Lms8jwpaIdIUvoBNee8ZuvIi1XnNy9uvnxSC9L1q1x4=
|
github.com/Microsoft/hcsshim v0.10.0-rc.1 h1:Lms8jwpaIdIUvoBNee8ZuvIi1XnNy9uvnxSC9L1q1x4=
|
||||||
github.com/Microsoft/hcsshim v0.10.0-rc.1/go.mod h1:7XX96hdvnwWGdXnksDNdhfFcUH1BtQY6bL2L3f9Abyk=
|
github.com/Microsoft/hcsshim v0.10.0-rc.1/go.mod h1:7XX96hdvnwWGdXnksDNdhfFcUH1BtQY6bL2L3f9Abyk=
|
||||||
github.com/Microsoft/hcsshim/test v0.0.0-20210408205431-da33ecd607e1 h1:pVKfKyPkXna29XlGjxSr9J0A7vNucOUHZ/2ClcTWalw=
|
github.com/Microsoft/hcsshim/test v0.0.0-20210408205431-da33ecd607e1 h1:pVKfKyPkXna29XlGjxSr9J0A7vNucOUHZ/2ClcTWalw=
|
||||||
@ -485,7 +486,6 @@ github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0Z
|
|||||||
github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0=
|
github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0=
|
||||||
github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
|
github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
|
||||||
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
|
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo=
|
||||||
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
|
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
|
||||||
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
|
github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
|
||||||
github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
|
github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
|
||||||
@ -611,6 +611,7 @@ github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
|
|||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
||||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||||
@ -779,8 +780,10 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
|
|||||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
||||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||||
|
github.com/klihub/nri v0.0.0-20221122201439-2b09b4ad5cf3/go.mod h1:Q2u9Sudol4IkJ6YK0gShznKMxM6Un0Y3O4Wslf5Nerg=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
@ -824,6 +827,7 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
|
|||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
|
github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
|
||||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||||
@ -833,6 +837,7 @@ github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vyg
|
|||||||
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||||
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||||
|
github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
|
||||||
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
|
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
|
||||||
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
|
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
|
||||||
github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs=
|
github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs=
|
||||||
@ -865,6 +870,9 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv
|
|||||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||||
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
|
github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
|
||||||
github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
|
||||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
@ -874,10 +882,14 @@ github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+t
|
|||||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||||
github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
|
github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
|
||||||
|
github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
|
||||||
|
github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
|
||||||
|
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
|
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
|
||||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||||
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||||
@ -888,12 +900,14 @@ github.com/opencontainers/runc v1.1.4/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJ
|
|||||||
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
|
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb h1:1xSVPOd7/UA+39/hXEGnBJ13p6JFB0E1EvQFlrRDOXI=
|
||||||
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
|
github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI=
|
||||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||||
|
github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||||
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||||
|
github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||||
github.com/opencontainers/selinux v1.10.2 h1:NFy2xCsjn7+WspbfZkUd5zyVeisV7VFbPSP96+8/ha4=
|
github.com/opencontainers/selinux v1.10.2 h1:NFy2xCsjn7+WspbfZkUd5zyVeisV7VFbPSP96+8/ha4=
|
||||||
github.com/opencontainers/selinux v1.10.2/go.mod h1:cARutUbaUrlRClyvxOICCgKixCs6L05aUsohzA3EkHQ=
|
github.com/opencontainers/selinux v1.10.2/go.mod h1:cARutUbaUrlRClyvxOICCgKixCs6L05aUsohzA3EkHQ=
|
||||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
@ -1011,6 +1025,7 @@ github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwD
|
|||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
|
github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
@ -1452,8 +1467,9 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854 h1:fzDvmJnoyma87dC7IBnNQWmMZNalsNrtiY1X6PwmME0=
|
|
||||||
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854/go.mod h1:VsjNM1dMo+Ofkp5d7y7fOdQZD8MTXSQ4w3EPk65AvKU=
|
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854/go.mod h1:VsjNM1dMo+Ofkp5d7y7fOdQZD8MTXSQ4w3EPk65AvKU=
|
||||||
|
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||||
|
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -1736,6 +1752,7 @@ k8s.io/client-go v0.25.4/go.mod h1:8trHCAC83XKY0wsBIpbirZU4NTUpbuhc2JnI7OruGZw=
|
|||||||
k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0=
|
k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0=
|
||||||
k8s.io/component-base v0.25.4/go.mod h1:nnZJU8OP13PJEm6/p5V2ztgX2oyteIaAGKGMYb2L2cY=
|
k8s.io/component-base v0.25.4/go.mod h1:nnZJU8OP13PJEm6/p5V2ztgX2oyteIaAGKGMYb2L2cY=
|
||||||
k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
|
k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI=
|
||||||
|
k8s.io/cri-api v0.25.3/go.mod h1:riC/P0yOGUf2K1735wW+CXs1aY2ctBgePtnnoFLd0dU=
|
||||||
k8s.io/cri-api v0.26.0-beta.0/go.mod h1:E49tenyB7esgfIguEd7+g9qYhHOr9peyyBcSaeH6Gxw=
|
k8s.io/cri-api v0.26.0-beta.0/go.mod h1:E49tenyB7esgfIguEd7+g9qYhHOr9peyyBcSaeH6Gxw=
|
||||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
|
58
pkg/nri/config.go
Normal file
58
pkg/nri/config.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config data for NRI.
|
||||||
|
type Config struct {
|
||||||
|
// Disable this NRI plugin and containerd NRI functionality altogether.
|
||||||
|
Disable bool `toml:"disable" json:"disable"`
|
||||||
|
// ConfigPath is the path to the NRI configuration file to use.
|
||||||
|
ConfigPath string `toml:"config_file" json:"configFile"`
|
||||||
|
// SocketPath is the path to the NRI socket to create for NRI plugins to connect to.
|
||||||
|
SocketPath string `toml:"socket_path" json:"socketPath"`
|
||||||
|
// PluginPath is the path to search for NRI plugins to launch on startup.
|
||||||
|
PluginPath string `toml:"plugin_path" json:"pluginPath"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultConfig returns the default configuration.
|
||||||
|
func DefaultConfig() *Config {
|
||||||
|
return &Config{
|
||||||
|
Disable: true,
|
||||||
|
ConfigPath: nri.DefaultConfigPath,
|
||||||
|
SocketPath: nri.DefaultSocketPath,
|
||||||
|
PluginPath: nri.DefaultPluginPath,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// toOptions returns NRI options for this configuration.
|
||||||
|
func (c *Config) toOptions() []nri.Option {
|
||||||
|
opts := []nri.Option{}
|
||||||
|
if c.ConfigPath != "" {
|
||||||
|
opts = append(opts, nri.WithConfigPath(c.ConfigPath))
|
||||||
|
}
|
||||||
|
if c.SocketPath != "" {
|
||||||
|
opts = append(opts, nri.WithSocketPath(c.SocketPath))
|
||||||
|
}
|
||||||
|
if c.PluginPath != "" {
|
||||||
|
opts = append(opts, nri.WithPluginPath(c.PluginPath))
|
||||||
|
}
|
||||||
|
return opts
|
||||||
|
}
|
72
pkg/nri/container.go
Normal file
72
pkg/nri/container.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Container interface for interacting with NRI.
|
||||||
|
type Container interface {
|
||||||
|
GetDomain() string
|
||||||
|
|
||||||
|
GetPodSandboxID() string
|
||||||
|
GetID() string
|
||||||
|
GetName() string
|
||||||
|
GetState() nri.ContainerState
|
||||||
|
GetLabels() map[string]string
|
||||||
|
GetAnnotations() map[string]string
|
||||||
|
GetArgs() []string
|
||||||
|
GetEnv() []string
|
||||||
|
GetMounts() []*nri.Mount
|
||||||
|
GetHooks() *nri.Hooks
|
||||||
|
GetLinuxContainer() LinuxContainer
|
||||||
|
|
||||||
|
GetPid() uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type LinuxContainer interface {
|
||||||
|
GetLinuxNamespaces() []*nri.LinuxNamespace
|
||||||
|
GetLinuxDevices() []*nri.LinuxDevice
|
||||||
|
GetLinuxResources() *nri.LinuxResources
|
||||||
|
GetOOMScoreAdj() *int
|
||||||
|
GetCgroupsPath() string
|
||||||
|
}
|
||||||
|
|
||||||
|
func commonContainerToNRI(ctr Container) *nri.Container {
|
||||||
|
return &nri.Container{
|
||||||
|
Id: ctr.GetID(),
|
||||||
|
PodSandboxId: ctr.GetPodSandboxID(),
|
||||||
|
Name: ctr.GetName(),
|
||||||
|
State: ctr.GetState(),
|
||||||
|
Labels: ctr.GetLabels(),
|
||||||
|
Annotations: ctr.GetAnnotations(),
|
||||||
|
Args: ctr.GetArgs(),
|
||||||
|
Env: ctr.GetEnv(),
|
||||||
|
Mounts: ctr.GetMounts(),
|
||||||
|
Hooks: ctr.GetHooks(),
|
||||||
|
Pid: ctr.GetPid(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func containersToNRI(ctrList []Container) []*nri.Container {
|
||||||
|
ctrs := []*nri.Container{}
|
||||||
|
for _, ctr := range ctrList {
|
||||||
|
ctrs = append(ctrs, containerToNRI(ctr))
|
||||||
|
}
|
||||||
|
return ctrs
|
||||||
|
}
|
37
pkg/nri/container_linux.go
Normal file
37
pkg/nri/container_linux.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
func containerToNRI(ctr Container) *nri.Container {
|
||||||
|
nriCtr := commonContainerToNRI(ctr)
|
||||||
|
lnxCtr := ctr.GetLinuxContainer()
|
||||||
|
nriCtr.Linux = &nri.LinuxContainer{
|
||||||
|
Namespaces: lnxCtr.GetLinuxNamespaces(),
|
||||||
|
Devices: lnxCtr.GetLinuxDevices(),
|
||||||
|
Resources: lnxCtr.GetLinuxResources(),
|
||||||
|
OomScoreAdj: nri.Int(lnxCtr.GetOOMScoreAdj()),
|
||||||
|
CgroupsPath: lnxCtr.GetCgroupsPath(),
|
||||||
|
}
|
||||||
|
return nriCtr
|
||||||
|
}
|
28
pkg/nri/container_other.go
Normal file
28
pkg/nri/container_other.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//go:build !linux
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
func containerToNRI(ctr Container) *nri.Container {
|
||||||
|
return commonContainerToNRI(ctr)
|
||||||
|
}
|
183
pkg/nri/domain.go
Normal file
183
pkg/nri/domain.go
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/containerd/containerd/namespaces"
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Domain implements the functions the generic NRI interface needs to
|
||||||
|
// deal with pods and containers from a particular containerd namespace.
|
||||||
|
type Domain interface {
|
||||||
|
// GetName() returns the containerd namespace for this domain.
|
||||||
|
GetName() string
|
||||||
|
|
||||||
|
// ListPodSandboxes list all pods in this namespace.
|
||||||
|
ListPodSandboxes() []PodSandbox
|
||||||
|
|
||||||
|
// ListContainer list all containers in this namespace.
|
||||||
|
ListContainers() []Container
|
||||||
|
|
||||||
|
// GetPodSandbox returns the pod for the given ID.
|
||||||
|
GetPodSandbox(string) (PodSandbox, bool)
|
||||||
|
|
||||||
|
// GetContainer returns the container for the given ID.
|
||||||
|
GetContainer(string) (Container, bool)
|
||||||
|
|
||||||
|
// UpdateContainer applies an NRI container update request in the namespace.
|
||||||
|
UpdateContainer(context.Context, *nri.ContainerUpdate) error
|
||||||
|
|
||||||
|
// EvictContainer evicts the requested container in the namespace.
|
||||||
|
EvictContainer(context.Context, *nri.ContainerEviction) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterDomain registers an NRI domain for a containerd namespace.
|
||||||
|
func RegisterDomain(d Domain) {
|
||||||
|
err := domains.add(d)
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithError(err).Fatalf("Failed to register namespace %q with NRI", d.GetName())
|
||||||
|
}
|
||||||
|
|
||||||
|
logrus.Infof("Registered namespace %q with NRI", d.GetName())
|
||||||
|
}
|
||||||
|
|
||||||
|
type domainTable struct {
|
||||||
|
sync.Mutex
|
||||||
|
domains map[string]Domain
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *domainTable) add(d Domain) error {
|
||||||
|
t.Lock()
|
||||||
|
defer t.Unlock()
|
||||||
|
|
||||||
|
namespace := d.GetName()
|
||||||
|
|
||||||
|
if _, ok := t.domains[namespace]; ok {
|
||||||
|
return errdefs.ErrAlreadyExists
|
||||||
|
}
|
||||||
|
|
||||||
|
t.domains[namespace] = d
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *domainTable) listPodSandboxes() []PodSandbox {
|
||||||
|
var pods []PodSandbox
|
||||||
|
|
||||||
|
t.Lock()
|
||||||
|
defer t.Unlock()
|
||||||
|
|
||||||
|
for _, d := range t.domains {
|
||||||
|
pods = append(pods, d.ListPodSandboxes()...)
|
||||||
|
}
|
||||||
|
return pods
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *domainTable) listContainers() []Container {
|
||||||
|
var ctrs []Container
|
||||||
|
|
||||||
|
t.Lock()
|
||||||
|
defer t.Unlock()
|
||||||
|
|
||||||
|
for _, d := range t.domains {
|
||||||
|
ctrs = append(ctrs, d.ListContainers()...)
|
||||||
|
}
|
||||||
|
return ctrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *domainTable) getContainer(id string) (Container, Domain) {
|
||||||
|
t.Lock()
|
||||||
|
defer t.Unlock()
|
||||||
|
|
||||||
|
// TODO(klihub): Are ID conflicts across namespaces possible ? Probably...
|
||||||
|
|
||||||
|
for _, d := range t.domains {
|
||||||
|
if ctr, ok := d.GetContainer(id); ok {
|
||||||
|
return ctr, d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *domainTable) updateContainers(ctx context.Context, updates []*nri.ContainerUpdate) ([]*nri.ContainerUpdate, error) {
|
||||||
|
var failed []*nri.ContainerUpdate
|
||||||
|
|
||||||
|
for _, u := range updates {
|
||||||
|
_, d := t.getContainer(u.ContainerId)
|
||||||
|
if d == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
domain := d.GetName()
|
||||||
|
err := d.UpdateContainer(namespaces.WithNamespace(ctx, domain), u)
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Errorf("NRI update of %s container %s failed",
|
||||||
|
domain, u.ContainerId)
|
||||||
|
if !u.IgnoreFailure {
|
||||||
|
failed = append(failed, u)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log.G(ctx).Tracef("NRI update of %s container %s successful", domain, u.ContainerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(failed) != 0 {
|
||||||
|
return failed, fmt.Errorf("NRI update of some containers failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *domainTable) evictContainers(ctx context.Context, evict []*nri.ContainerEviction) ([]*nri.ContainerEviction, error) {
|
||||||
|
var failed []*nri.ContainerEviction
|
||||||
|
|
||||||
|
for _, e := range evict {
|
||||||
|
_, d := t.getContainer(e.ContainerId)
|
||||||
|
if d == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
domain := d.GetName()
|
||||||
|
err := d.EvictContainer(namespaces.WithNamespace(ctx, domain), e)
|
||||||
|
if err != nil {
|
||||||
|
log.G(ctx).WithError(err).Errorf("NRI eviction of %s container %s failed",
|
||||||
|
domain, e.ContainerId)
|
||||||
|
failed = append(failed, e)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log.G(ctx).Tracef("NRI eviction of %s container %s successful", domain, e.ContainerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(failed) != 0 {
|
||||||
|
return failed, fmt.Errorf("NRI eviction of some containers failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var domains = &domainTable{
|
||||||
|
domains: make(map[string]Domain),
|
||||||
|
}
|
525
pkg/nri/nri.go
Normal file
525
pkg/nri/nri.go
Normal file
@ -0,0 +1,525 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"path"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/version"
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// API implements a common API for interfacing NRI from containerd. It is
|
||||||
|
// agnostic to any internal containerd implementation details of pods and
|
||||||
|
// containers. It needs corresponding Domain interfaces for each containerd
|
||||||
|
// namespace it needs to handle. These domains take care of the namespace-
|
||||||
|
// specific details of providing pod and container metadata to NRI and of
|
||||||
|
// applying NRI-requested adjustments to the state of containers.
|
||||||
|
type API interface {
|
||||||
|
// IsEnabled returns true if the NRI interface is enabled and initialized.
|
||||||
|
IsEnabled() bool
|
||||||
|
|
||||||
|
// Start start the NRI interface, allowing external NRI plugins to
|
||||||
|
// connect, register, and hook themselves into the lifecycle events
|
||||||
|
// of pods and containers.
|
||||||
|
Start() error
|
||||||
|
|
||||||
|
// Stop stops the NRI interface.
|
||||||
|
Stop()
|
||||||
|
|
||||||
|
// RunPodSandbox relays pod creation events to NRI.
|
||||||
|
RunPodSandbox(context.Context, PodSandbox) error
|
||||||
|
|
||||||
|
// StopPodSandbox relays pod shutdown events to NRI.
|
||||||
|
StopPodSandbox(context.Context, PodSandbox) error
|
||||||
|
|
||||||
|
// RemovePodSandbox relays pod removal events to NRI.
|
||||||
|
RemovePodSandbox(context.Context, PodSandbox) error
|
||||||
|
|
||||||
|
// CreateContainer relays container creation requests to NRI.
|
||||||
|
CreateContainer(context.Context, PodSandbox, Container) (*nri.ContainerAdjustment, error)
|
||||||
|
|
||||||
|
// PostCreateContainer relays successful container creation events to NRI.
|
||||||
|
PostCreateContainer(context.Context, PodSandbox, Container) error
|
||||||
|
|
||||||
|
// StartContainer relays container start request notifications to NRI.
|
||||||
|
StartContainer(context.Context, PodSandbox, Container) error
|
||||||
|
|
||||||
|
// PostStartContainer relays successful container startup events to NRI.
|
||||||
|
PostStartContainer(context.Context, PodSandbox, Container) error
|
||||||
|
|
||||||
|
// UpdateContainer relays container update requests to NRI.
|
||||||
|
UpdateContainer(context.Context, PodSandbox, Container, *nri.LinuxResources) (*nri.LinuxResources, error)
|
||||||
|
|
||||||
|
// PostUpdateContainer relays successful container update events to NRI.
|
||||||
|
PostUpdateContainer(context.Context, PodSandbox, Container) error
|
||||||
|
|
||||||
|
// StopContainer relays container stop requests to NRI.
|
||||||
|
StopContainer(context.Context, PodSandbox, Container) error
|
||||||
|
|
||||||
|
// NotifyContainerExit handles the exit event of a container.
|
||||||
|
NotifyContainerExit(context.Context, PodSandbox, Container)
|
||||||
|
|
||||||
|
// StopContainer relays container removal events to NRI.
|
||||||
|
RemoveContainer(context.Context, PodSandbox, Container) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type State int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Created State = iota + 1
|
||||||
|
Running
|
||||||
|
Stopped
|
||||||
|
Removed
|
||||||
|
)
|
||||||
|
|
||||||
|
type local struct {
|
||||||
|
sync.Mutex
|
||||||
|
cfg *Config
|
||||||
|
nri *nri.Adaptation
|
||||||
|
|
||||||
|
state map[string]State
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ API = &local{}
|
||||||
|
|
||||||
|
// New creates an instance of the NRI interface with the given configuration.
|
||||||
|
func New(cfg *Config) (API, error) {
|
||||||
|
l := &local{
|
||||||
|
cfg: cfg,
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg.Disable {
|
||||||
|
logrus.Info("NRI interface is disabled by configuration.")
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
name = path.Base(version.Package)
|
||||||
|
version = version.Version
|
||||||
|
opts = cfg.toOptions()
|
||||||
|
syncFn = l.syncPlugin
|
||||||
|
updateFn = l.updateFromPlugin
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
l.nri, err = nri.New(name, version, syncFn, updateFn, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to initialize NRI interface: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
l.state = make(map[string]State)
|
||||||
|
|
||||||
|
logrus.Info("created NRI interface")
|
||||||
|
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) IsEnabled() bool {
|
||||||
|
return l != nil && !l.cfg.Disable
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) Start() error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.nri.Start()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to start NRI interface: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) Stop() {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
l.nri.Stop()
|
||||||
|
l.nri = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) RunPodSandbox(ctx context.Context, pod PodSandbox) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.RunPodSandboxRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.nri.RunPodSandbox(ctx, request)
|
||||||
|
l.setState(pod.GetID(), Running)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) StopPodSandbox(ctx context.Context, pod PodSandbox) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
if !l.needsStopping(pod.GetID()) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
request := &nri.StopPodSandboxRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.nri.StopPodSandbox(ctx, request)
|
||||||
|
l.setState(pod.GetID(), Stopped)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) RemovePodSandbox(ctx context.Context, pod PodSandbox) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
if !l.needsRemoval(pod.GetID()) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
request := &nri.RemovePodSandboxRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.nri.RemovePodSandbox(ctx, request)
|
||||||
|
l.setState(pod.GetID(), Removed)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) CreateContainer(ctx context.Context, pod PodSandbox, ctr Container) (*nri.ContainerAdjustment, error) {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.CreateContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := l.nri.CreateContainer(ctx, request)
|
||||||
|
l.setState(request.Container.Id, Created)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = l.evictContainers(ctx, response.Evict)
|
||||||
|
if err != nil {
|
||||||
|
// TODO(klihub): we ignore pre-create eviction failures for now
|
||||||
|
log.G(ctx).WithError(err).Warnf("pre-create eviction failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := l.applyUpdates(ctx, response.Update); err != nil {
|
||||||
|
// TODO(klihub): we ignore pre-create update failures for now
|
||||||
|
log.G(ctx).WithError(err).Warnf("pre-create update failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Adjust, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) PostCreateContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.PostCreateContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.nri.PostCreateContainer(ctx, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) StartContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.StartContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := l.nri.StartContainer(ctx, request)
|
||||||
|
l.setState(request.Container.Id, Running)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) PostStartContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.PostStartContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.nri.PostStartContainer(ctx, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) UpdateContainer(ctx context.Context, pod PodSandbox, ctr Container, req *nri.LinuxResources) (*nri.LinuxResources, error) {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.UpdateContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
LinuxResources: req,
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := l.nri.UpdateContainer(ctx, request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = l.evictContainers(ctx, response.Evict)
|
||||||
|
if err != nil {
|
||||||
|
// TODO(klihub): we ignore pre-update eviction failures for now
|
||||||
|
log.G(ctx).WithError(err).Warnf("pre-update eviction failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt := len(response.Update)
|
||||||
|
if cnt == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if cnt > 1 {
|
||||||
|
_, err = l.applyUpdates(ctx, response.Update[0:cnt-1])
|
||||||
|
if err != nil {
|
||||||
|
// TODO(klihub): we ignore pre-update update failures for now
|
||||||
|
log.G(ctx).WithError(err).Warnf("pre-update update failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Update[cnt-1].GetLinux().GetResources(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) PostUpdateContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
request := &nri.PostUpdateContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.nri.PostUpdateContainer(ctx, request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) StopContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
return l.stopContainer(ctx, pod, ctr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) NotifyContainerExit(ctx context.Context, pod PodSandbox, ctr Container) {
|
||||||
|
go func() {
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
l.stopContainer(ctx, pod, ctr)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) stopContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.needsStopping(ctr.GetID()) {
|
||||||
|
log.G(ctx).Tracef("NRI stopContainer: container %s does not need stopping",
|
||||||
|
ctr.GetID())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
request := &nri.StopContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := l.nri.StopContainer(ctx, request)
|
||||||
|
l.setState(request.Container.Id, Stopped)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = l.applyUpdates(ctx, response.Update)
|
||||||
|
if err != nil {
|
||||||
|
// TODO(klihub): we ignore post-stop update failures for now
|
||||||
|
log.G(ctx).WithError(err).Warnf("post-stop update failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) RemoveContainer(ctx context.Context, pod PodSandbox, ctr Container) error {
|
||||||
|
if !l.IsEnabled() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
if !l.needsRemoval(ctr.GetID()) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.stopContainer(ctx, pod, ctr)
|
||||||
|
|
||||||
|
request := &nri.RemoveContainerRequest{
|
||||||
|
Pod: podSandboxToNRI(pod),
|
||||||
|
Container: containerToNRI(ctr),
|
||||||
|
}
|
||||||
|
err := l.nri.RemoveContainer(ctx, request)
|
||||||
|
l.setState(request.Container.Id, Removed)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) syncPlugin(ctx context.Context, syncFn nri.SyncCB) error {
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
log.G(ctx).Info("Synchronizing NRI (plugin) with current runtime state")
|
||||||
|
|
||||||
|
pods := podSandboxesToNRI(domains.listPodSandboxes())
|
||||||
|
containers := containersToNRI(domains.listContainers())
|
||||||
|
|
||||||
|
for _, ctr := range containers {
|
||||||
|
switch ctr.GetState() {
|
||||||
|
case nri.ContainerState_CONTAINER_CREATED:
|
||||||
|
l.setState(ctr.GetId(), Created)
|
||||||
|
case nri.ContainerState_CONTAINER_RUNNING, nri.ContainerState_CONTAINER_PAUSED:
|
||||||
|
l.setState(ctr.GetId(), Running)
|
||||||
|
case nri.ContainerState_CONTAINER_STOPPED:
|
||||||
|
l.setState(ctr.GetId(), Stopped)
|
||||||
|
default:
|
||||||
|
l.setState(ctr.GetId(), Removed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updates, err := syncFn(ctx, pods, containers)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = l.applyUpdates(ctx, updates)
|
||||||
|
if err != nil {
|
||||||
|
// TODO(klihub): we ignore post-sync update failures for now
|
||||||
|
log.G(ctx).WithError(err).Warnf("post-sync update failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) updateFromPlugin(ctx context.Context, req []*nri.ContainerUpdate) ([]*nri.ContainerUpdate, error) {
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
|
||||||
|
log.G(ctx).Trace("Unsolicited NRI container updates")
|
||||||
|
|
||||||
|
failed, err := l.applyUpdates(ctx, req)
|
||||||
|
return failed, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) applyUpdates(ctx context.Context, updates []*nri.ContainerUpdate) ([]*nri.ContainerUpdate, error) {
|
||||||
|
// TODO(klihub): should we pre-save state and attempt a rollback on failure ?
|
||||||
|
failed, err := domains.updateContainers(ctx, updates)
|
||||||
|
return failed, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) evictContainers(ctx context.Context, evict []*nri.ContainerEviction) ([]*nri.ContainerEviction, error) {
|
||||||
|
failed, err := domains.evictContainers(ctx, evict)
|
||||||
|
return failed, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) setState(id string, state State) {
|
||||||
|
if state != Removed {
|
||||||
|
l.state[id] = state
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(l.state, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) getState(id string) State {
|
||||||
|
if state, ok := l.state[id]; ok {
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
return Removed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) needsStopping(id string) bool {
|
||||||
|
s := l.getState(id)
|
||||||
|
if s == Created || s == Running {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *local) needsRemoval(id string) bool {
|
||||||
|
s := l.getState(id)
|
||||||
|
if s == Created || s == Running || s == Stopped {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
36
pkg/nri/plugin/plugin.go
Normal file
36
pkg/nri/plugin/plugin.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containerd/containerd/pkg/nri"
|
||||||
|
"github.com/containerd/containerd/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
plugin.Register(&plugin.Registration{
|
||||||
|
Type: plugin.NRIApiPlugin,
|
||||||
|
ID: "nri",
|
||||||
|
Config: nri.DefaultConfig(),
|
||||||
|
InitFn: initFunc,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func initFunc(ic *plugin.InitContext) (interface{}, error) {
|
||||||
|
l, err := nri.New(ic.Config.(*nri.Config))
|
||||||
|
return l, err
|
||||||
|
}
|
67
pkg/nri/sandbox.go
Normal file
67
pkg/nri/sandbox.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PodSandbox interface for interacting with NRI.
|
||||||
|
type PodSandbox interface {
|
||||||
|
GetDomain() string
|
||||||
|
|
||||||
|
GetID() string
|
||||||
|
GetName() string
|
||||||
|
GetUID() string
|
||||||
|
GetNamespace() string
|
||||||
|
GetLabels() map[string]string
|
||||||
|
GetAnnotations() map[string]string
|
||||||
|
GetRuntimeHandler() string
|
||||||
|
GetLinuxPodSandbox() LinuxPodSandbox
|
||||||
|
|
||||||
|
GetPid() uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type LinuxPodSandbox interface {
|
||||||
|
GetLinuxNamespaces() []*nri.LinuxNamespace
|
||||||
|
GetPodLinuxOverhead() *nri.LinuxResources
|
||||||
|
GetPodLinuxResources() *nri.LinuxResources
|
||||||
|
GetCgroupParent() string
|
||||||
|
GetCgroupsPath() string
|
||||||
|
GetLinuxResources() *nri.LinuxResources
|
||||||
|
}
|
||||||
|
|
||||||
|
func commonPodSandboxToNRI(pod PodSandbox) *nri.PodSandbox {
|
||||||
|
return &nri.PodSandbox{
|
||||||
|
Id: pod.GetID(),
|
||||||
|
Name: pod.GetName(),
|
||||||
|
Uid: pod.GetUID(),
|
||||||
|
Namespace: pod.GetNamespace(),
|
||||||
|
Labels: pod.GetLabels(),
|
||||||
|
Annotations: pod.GetAnnotations(),
|
||||||
|
RuntimeHandler: pod.GetRuntimeHandler(),
|
||||||
|
Pid: pod.GetPid(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func podSandboxesToNRI(podList []PodSandbox) []*nri.PodSandbox {
|
||||||
|
pods := []*nri.PodSandbox{}
|
||||||
|
for _, pod := range podList {
|
||||||
|
pods = append(pods, podSandboxToNRI(pod))
|
||||||
|
}
|
||||||
|
return pods
|
||||||
|
}
|
38
pkg/nri/sandbox_linux.go
Normal file
38
pkg/nri/sandbox_linux.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
func podSandboxToNRI(pod PodSandbox) *nri.PodSandbox {
|
||||||
|
nriPod := commonPodSandboxToNRI(pod)
|
||||||
|
lnxPod := pod.GetLinuxPodSandbox()
|
||||||
|
nriPod.Linux = &nri.LinuxPodSandbox{
|
||||||
|
Namespaces: lnxPod.GetLinuxNamespaces(),
|
||||||
|
PodOverhead: lnxPod.GetPodLinuxOverhead(),
|
||||||
|
PodResources: lnxPod.GetPodLinuxResources(),
|
||||||
|
CgroupParent: lnxPod.GetCgroupParent(),
|
||||||
|
CgroupsPath: lnxPod.GetCgroupsPath(),
|
||||||
|
Resources: lnxPod.GetLinuxResources(),
|
||||||
|
}
|
||||||
|
return nriPod
|
||||||
|
}
|
28
pkg/nri/sandbox_other.go
Normal file
28
pkg/nri/sandbox_other.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//go:build !linux
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package nri
|
||||||
|
|
||||||
|
import (
|
||||||
|
nri "github.com/containerd/nri/pkg/adaptation"
|
||||||
|
)
|
||||||
|
|
||||||
|
func podSandboxToNRI(pod PodSandbox) *nri.PodSandbox {
|
||||||
|
return commonPodSandboxToNRI(pod)
|
||||||
|
}
|
@ -80,6 +80,8 @@ const (
|
|||||||
LeasePlugin Type = "io.containerd.lease.v1"
|
LeasePlugin Type = "io.containerd.lease.v1"
|
||||||
// TracingProcessorPlugin implements a open telemetry span processor
|
// TracingProcessorPlugin implements a open telemetry span processor
|
||||||
TracingProcessorPlugin Type = "io.containerd.tracing.processor.v1"
|
TracingProcessorPlugin Type = "io.containerd.tracing.processor.v1"
|
||||||
|
// NRIApiPlugin implements the NRI adaptation interface for containerd.
|
||||||
|
NRIApiPlugin Type = "io.containerd.nri.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
21
vendor/github.com/blang/semver/.travis.yml
generated
vendored
21
vendor/github.com/blang/semver/.travis.yml
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
language: go
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- go: 1.4.3
|
|
||||||
- go: 1.5.4
|
|
||||||
- go: 1.6.3
|
|
||||||
- go: 1.7
|
|
||||||
- go: tip
|
|
||||||
allow_failures:
|
|
||||||
- go: tip
|
|
||||||
install:
|
|
||||||
- go get golang.org/x/tools/cmd/cover
|
|
||||||
- go get github.com/mattn/goveralls
|
|
||||||
script:
|
|
||||||
- echo "Test and track coverage" ; $HOME/gopath/bin/goveralls -package "." -service=travis-ci
|
|
||||||
-repotoken $COVERALLS_TOKEN
|
|
||||||
- echo "Build examples" ; cd examples && go build
|
|
||||||
- echo "Check if gofmt'd" ; diff -u <(echo -n) <(gofmt -d -s .)
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
secure: HroGEAUQpVq9zX1b1VIkraLiywhGbzvNnTZq2TMxgK7JHP8xqNplAeF1izrR2i4QLL9nsY+9WtYss4QuPvEtZcVHUobw6XnL6radF7jS1LgfYZ9Y7oF+zogZ2I5QUMRLGA7rcxQ05s7mKq3XZQfeqaNts4bms/eZRefWuaFZbkw=
|
|
22
vendor/github.com/blang/semver/LICENSE
generated
vendored
22
vendor/github.com/blang/semver/LICENSE
generated
vendored
@ -1,22 +0,0 @@
|
|||||||
The MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2014 Benedikt Lang <github at benediktlang.de>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
|
|
194
vendor/github.com/blang/semver/README.md
generated
vendored
194
vendor/github.com/blang/semver/README.md
generated
vendored
@ -1,194 +0,0 @@
|
|||||||
semver for golang [](https://travis-ci.org/blang/semver) [](https://godoc.org/github.com/blang/semver) [](https://coveralls.io/r/blang/semver?branch=master)
|
|
||||||
======
|
|
||||||
|
|
||||||
semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`.
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
```bash
|
|
||||||
$ go get github.com/blang/semver
|
|
||||||
```
|
|
||||||
Note: Always vendor your dependencies or fix on a specific version tag.
|
|
||||||
|
|
||||||
```go
|
|
||||||
import github.com/blang/semver
|
|
||||||
v1, err := semver.Make("1.0.0-beta")
|
|
||||||
v2, err := semver.Make("2.0.0-beta")
|
|
||||||
v1.Compare(v2)
|
|
||||||
```
|
|
||||||
|
|
||||||
Also check the [GoDocs](http://godoc.org/github.com/blang/semver).
|
|
||||||
|
|
||||||
Why should I use this lib?
|
|
||||||
-----
|
|
||||||
|
|
||||||
- Fully spec compatible
|
|
||||||
- No reflection
|
|
||||||
- No regex
|
|
||||||
- Fully tested (Coverage >99%)
|
|
||||||
- Readable parsing/validation errors
|
|
||||||
- Fast (See [Benchmarks](#benchmarks))
|
|
||||||
- Only Stdlib
|
|
||||||
- Uses values instead of pointers
|
|
||||||
- Many features, see below
|
|
||||||
|
|
||||||
|
|
||||||
Features
|
|
||||||
-----
|
|
||||||
|
|
||||||
- Parsing and validation at all levels
|
|
||||||
- Comparator-like comparisons
|
|
||||||
- Compare Helper Methods
|
|
||||||
- InPlace manipulation
|
|
||||||
- Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1`
|
|
||||||
- Wildcards `>=1.x`, `<=2.5.x`
|
|
||||||
- Sortable (implements sort.Interface)
|
|
||||||
- database/sql compatible (sql.Scanner/Valuer)
|
|
||||||
- encoding/json compatible (json.Marshaler/Unmarshaler)
|
|
||||||
|
|
||||||
Ranges
|
|
||||||
------
|
|
||||||
|
|
||||||
A `Range` is a set of conditions which specify which versions satisfy the range.
|
|
||||||
|
|
||||||
A condition is composed of an operator and a version. The supported operators are:
|
|
||||||
|
|
||||||
- `<1.0.0` Less than `1.0.0`
|
|
||||||
- `<=1.0.0` Less than or equal to `1.0.0`
|
|
||||||
- `>1.0.0` Greater than `1.0.0`
|
|
||||||
- `>=1.0.0` Greater than or equal to `1.0.0`
|
|
||||||
- `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0`
|
|
||||||
- `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`.
|
|
||||||
|
|
||||||
Note that spaces between the operator and the version will be gracefully tolerated.
|
|
||||||
|
|
||||||
A `Range` can link multiple `Ranges` separated by space:
|
|
||||||
|
|
||||||
Ranges can be linked by logical AND:
|
|
||||||
|
|
||||||
- `>1.0.0 <2.0.0` would match between both ranges, so `1.1.1` and `1.8.7` but not `1.0.0` or `2.0.0`
|
|
||||||
- `>1.0.0 <3.0.0 !2.0.3-beta.2` would match every version between `1.0.0` and `3.0.0` except `2.0.3-beta.2`
|
|
||||||
|
|
||||||
Ranges can also be linked by logical OR:
|
|
||||||
|
|
||||||
- `<2.0.0 || >=3.0.0` would match `1.x.x` and `3.x.x` but not `2.x.x`
|
|
||||||
|
|
||||||
AND has a higher precedence than OR. It's not possible to use brackets.
|
|
||||||
|
|
||||||
Ranges can be combined by both AND and OR
|
|
||||||
|
|
||||||
- `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
|
|
||||||
|
|
||||||
Range usage:
|
|
||||||
|
|
||||||
```
|
|
||||||
v, err := semver.Parse("1.2.3")
|
|
||||||
range, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0")
|
|
||||||
if range(v) {
|
|
||||||
//valid
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Example
|
|
||||||
-----
|
|
||||||
|
|
||||||
Have a look at full examples in [examples/main.go](examples/main.go)
|
|
||||||
|
|
||||||
```go
|
|
||||||
import github.com/blang/semver
|
|
||||||
|
|
||||||
v, err := semver.Make("0.0.1-alpha.preview+123.github")
|
|
||||||
fmt.Printf("Major: %d\n", v.Major)
|
|
||||||
fmt.Printf("Minor: %d\n", v.Minor)
|
|
||||||
fmt.Printf("Patch: %d\n", v.Patch)
|
|
||||||
fmt.Printf("Pre: %s\n", v.Pre)
|
|
||||||
fmt.Printf("Build: %s\n", v.Build)
|
|
||||||
|
|
||||||
// Prerelease versions array
|
|
||||||
if len(v.Pre) > 0 {
|
|
||||||
fmt.Println("Prerelease versions:")
|
|
||||||
for i, pre := range v.Pre {
|
|
||||||
fmt.Printf("%d: %q\n", i, pre)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build meta data array
|
|
||||||
if len(v.Build) > 0 {
|
|
||||||
fmt.Println("Build meta data:")
|
|
||||||
for i, build := range v.Build {
|
|
||||||
fmt.Printf("%d: %q\n", i, build)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
v001, err := semver.Make("0.0.1")
|
|
||||||
// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE
|
|
||||||
v001.GT(v) == true
|
|
||||||
v.LT(v001) == true
|
|
||||||
v.GTE(v) == true
|
|
||||||
v.LTE(v) == true
|
|
||||||
|
|
||||||
// Or use v.Compare(v2) for comparisons (-1, 0, 1):
|
|
||||||
v001.Compare(v) == 1
|
|
||||||
v.Compare(v001) == -1
|
|
||||||
v.Compare(v) == 0
|
|
||||||
|
|
||||||
// Manipulate Version in place:
|
|
||||||
v.Pre[0], err = semver.NewPRVersion("beta")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error parsing pre release version: %q", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("\nValidate versions:")
|
|
||||||
v.Build[0] = "?"
|
|
||||||
|
|
||||||
err = v.Validate()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Validation failed: %s\n", err)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Benchmarks
|
|
||||||
-----
|
|
||||||
|
|
||||||
BenchmarkParseSimple-4 5000000 390 ns/op 48 B/op 1 allocs/op
|
|
||||||
BenchmarkParseComplex-4 1000000 1813 ns/op 256 B/op 7 allocs/op
|
|
||||||
BenchmarkParseAverage-4 1000000 1171 ns/op 163 B/op 4 allocs/op
|
|
||||||
BenchmarkStringSimple-4 20000000 119 ns/op 16 B/op 1 allocs/op
|
|
||||||
BenchmarkStringLarger-4 10000000 206 ns/op 32 B/op 2 allocs/op
|
|
||||||
BenchmarkStringComplex-4 5000000 324 ns/op 80 B/op 3 allocs/op
|
|
||||||
BenchmarkStringAverage-4 5000000 273 ns/op 53 B/op 2 allocs/op
|
|
||||||
BenchmarkValidateSimple-4 200000000 9.33 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkValidateComplex-4 3000000 469 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkValidateAverage-4 5000000 256 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkCompareSimple-4 100000000 11.8 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkCompareComplex-4 50000000 30.8 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkCompareAverage-4 30000000 41.5 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkSort-4 3000000 419 ns/op 256 B/op 2 allocs/op
|
|
||||||
BenchmarkRangeParseSimple-4 2000000 850 ns/op 192 B/op 5 allocs/op
|
|
||||||
BenchmarkRangeParseAverage-4 1000000 1677 ns/op 400 B/op 10 allocs/op
|
|
||||||
BenchmarkRangeParseComplex-4 300000 5214 ns/op 1440 B/op 30 allocs/op
|
|
||||||
BenchmarkRangeMatchSimple-4 50000000 25.6 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkRangeMatchAverage-4 30000000 56.4 ns/op 0 B/op 0 allocs/op
|
|
||||||
BenchmarkRangeMatchComplex-4 10000000 153 ns/op 0 B/op 0 allocs/op
|
|
||||||
|
|
||||||
See benchmark cases at [semver_test.go](semver_test.go)
|
|
||||||
|
|
||||||
|
|
||||||
Motivation
|
|
||||||
-----
|
|
||||||
|
|
||||||
I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like.
|
|
||||||
|
|
||||||
|
|
||||||
Contribution
|
|
||||||
-----
|
|
||||||
|
|
||||||
Feel free to make a pull request. For bigger changes create a issue first to discuss about it.
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
-----
|
|
||||||
|
|
||||||
See [LICENSE](LICENSE) file.
|
|
23
vendor/github.com/blang/semver/json.go
generated
vendored
23
vendor/github.com/blang/semver/json.go
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
package semver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MarshalJSON implements the encoding/json.Marshaler interface.
|
|
||||||
func (v Version) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(v.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements the encoding/json.Unmarshaler interface.
|
|
||||||
func (v *Version) UnmarshalJSON(data []byte) (err error) {
|
|
||||||
var versionString string
|
|
||||||
|
|
||||||
if err = json.Unmarshal(data, &versionString); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
*v, err = Parse(versionString)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
17
vendor/github.com/blang/semver/package.json
generated
vendored
17
vendor/github.com/blang/semver/package.json
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"author": "blang",
|
|
||||||
"bugs": {
|
|
||||||
"URL": "https://github.com/blang/semver/issues",
|
|
||||||
"url": "https://github.com/blang/semver/issues"
|
|
||||||
},
|
|
||||||
"gx": {
|
|
||||||
"dvcsimport": "github.com/blang/semver"
|
|
||||||
},
|
|
||||||
"gxVersion": "0.10.0",
|
|
||||||
"language": "go",
|
|
||||||
"license": "MIT",
|
|
||||||
"name": "semver",
|
|
||||||
"releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
|
|
||||||
"version": "3.5.1"
|
|
||||||
}
|
|
||||||
|
|
416
vendor/github.com/blang/semver/range.go
generated
vendored
416
vendor/github.com/blang/semver/range.go
generated
vendored
@ -1,416 +0,0 @@
|
|||||||
package semver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
|
||||||
)
|
|
||||||
|
|
||||||
type wildcardType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
noneWildcard wildcardType = iota
|
|
||||||
majorWildcard wildcardType = 1
|
|
||||||
minorWildcard wildcardType = 2
|
|
||||||
patchWildcard wildcardType = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
func wildcardTypefromInt(i int) wildcardType {
|
|
||||||
switch i {
|
|
||||||
case 1:
|
|
||||||
return majorWildcard
|
|
||||||
case 2:
|
|
||||||
return minorWildcard
|
|
||||||
case 3:
|
|
||||||
return patchWildcard
|
|
||||||
default:
|
|
||||||
return noneWildcard
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type comparator func(Version, Version) bool
|
|
||||||
|
|
||||||
var (
|
|
||||||
compEQ comparator = func(v1 Version, v2 Version) bool {
|
|
||||||
return v1.Compare(v2) == 0
|
|
||||||
}
|
|
||||||
compNE = func(v1 Version, v2 Version) bool {
|
|
||||||
return v1.Compare(v2) != 0
|
|
||||||
}
|
|
||||||
compGT = func(v1 Version, v2 Version) bool {
|
|
||||||
return v1.Compare(v2) == 1
|
|
||||||
}
|
|
||||||
compGE = func(v1 Version, v2 Version) bool {
|
|
||||||
return v1.Compare(v2) >= 0
|
|
||||||
}
|
|
||||||
compLT = func(v1 Version, v2 Version) bool {
|
|
||||||
return v1.Compare(v2) == -1
|
|
||||||
}
|
|
||||||
compLE = func(v1 Version, v2 Version) bool {
|
|
||||||
return v1.Compare(v2) <= 0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
type versionRange struct {
|
|
||||||
v Version
|
|
||||||
c comparator
|
|
||||||
}
|
|
||||||
|
|
||||||
// rangeFunc creates a Range from the given versionRange.
|
|
||||||
func (vr *versionRange) rangeFunc() Range {
|
|
||||||
return Range(func(v Version) bool {
|
|
||||||
return vr.c(v, vr.v)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Range represents a range of versions.
|
|
||||||
// A Range can be used to check if a Version satisfies it:
|
|
||||||
//
|
|
||||||
// range, err := semver.ParseRange(">1.0.0 <2.0.0")
|
|
||||||
// range(semver.MustParse("1.1.1") // returns true
|
|
||||||
type Range func(Version) bool
|
|
||||||
|
|
||||||
// OR combines the existing Range with another Range using logical OR.
|
|
||||||
func (rf Range) OR(f Range) Range {
|
|
||||||
return Range(func(v Version) bool {
|
|
||||||
return rf(v) || f(v)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// AND combines the existing Range with another Range using logical AND.
|
|
||||||
func (rf Range) AND(f Range) Range {
|
|
||||||
return Range(func(v Version) bool {
|
|
||||||
return rf(v) && f(v)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseRange parses a range and returns a Range.
|
|
||||||
// If the range could not be parsed an error is returned.
|
|
||||||
//
|
|
||||||
// Valid ranges are:
|
|
||||||
// - "<1.0.0"
|
|
||||||
// - "<=1.0.0"
|
|
||||||
// - ">1.0.0"
|
|
||||||
// - ">=1.0.0"
|
|
||||||
// - "1.0.0", "=1.0.0", "==1.0.0"
|
|
||||||
// - "!1.0.0", "!=1.0.0"
|
|
||||||
//
|
|
||||||
// A Range can consist of multiple ranges separated by space:
|
|
||||||
// Ranges can be linked by logical AND:
|
|
||||||
// - ">1.0.0 <2.0.0" would match between both ranges, so "1.1.1" and "1.8.7" but not "1.0.0" or "2.0.0"
|
|
||||||
// - ">1.0.0 <3.0.0 !2.0.3-beta.2" would match every version between 1.0.0 and 3.0.0 except 2.0.3-beta.2
|
|
||||||
//
|
|
||||||
// Ranges can also be linked by logical OR:
|
|
||||||
// - "<2.0.0 || >=3.0.0" would match "1.x.x" and "3.x.x" but not "2.x.x"
|
|
||||||
//
|
|
||||||
// AND has a higher precedence than OR. It's not possible to use brackets.
|
|
||||||
//
|
|
||||||
// Ranges can be combined by both AND and OR
|
|
||||||
//
|
|
||||||
// - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
|
|
||||||
func ParseRange(s string) (Range, error) {
|
|
||||||
parts := splitAndTrim(s)
|
|
||||||
orParts, err := splitORParts(parts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
expandedParts, err := expandWildcardVersion(orParts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var orFn Range
|
|
||||||
for _, p := range expandedParts {
|
|
||||||
var andFn Range
|
|
||||||
for _, ap := range p {
|
|
||||||
opStr, vStr, err := splitComparatorVersion(ap)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
vr, err := buildVersionRange(opStr, vStr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Could not parse Range %q: %s", ap, err)
|
|
||||||
}
|
|
||||||
rf := vr.rangeFunc()
|
|
||||||
|
|
||||||
// Set function
|
|
||||||
if andFn == nil {
|
|
||||||
andFn = rf
|
|
||||||
} else { // Combine with existing function
|
|
||||||
andFn = andFn.AND(rf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if orFn == nil {
|
|
||||||
orFn = andFn
|
|
||||||
} else {
|
|
||||||
orFn = orFn.OR(andFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return orFn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// splitORParts splits the already cleaned parts by '||'.
|
|
||||||
// Checks for invalid positions of the operator and returns an
|
|
||||||
// error if found.
|
|
||||||
func splitORParts(parts []string) ([][]string, error) {
|
|
||||||
var ORparts [][]string
|
|
||||||
last := 0
|
|
||||||
for i, p := range parts {
|
|
||||||
if p == "||" {
|
|
||||||
if i == 0 {
|
|
||||||
return nil, fmt.Errorf("First element in range is '||'")
|
|
||||||
}
|
|
||||||
ORparts = append(ORparts, parts[last:i])
|
|
||||||
last = i + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if last == len(parts) {
|
|
||||||
return nil, fmt.Errorf("Last element in range is '||'")
|
|
||||||
}
|
|
||||||
ORparts = append(ORparts, parts[last:])
|
|
||||||
return ORparts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildVersionRange takes a slice of 2: operator and version
|
|
||||||
// and builds a versionRange, otherwise an error.
|
|
||||||
func buildVersionRange(opStr, vStr string) (*versionRange, error) {
|
|
||||||
c := parseComparator(opStr)
|
|
||||||
if c == nil {
|
|
||||||
return nil, fmt.Errorf("Could not parse comparator %q in %q", opStr, strings.Join([]string{opStr, vStr}, ""))
|
|
||||||
}
|
|
||||||
v, err := Parse(vStr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Could not parse version %q in %q: %s", vStr, strings.Join([]string{opStr, vStr}, ""), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &versionRange{
|
|
||||||
v: v,
|
|
||||||
c: c,
|
|
||||||
}, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// inArray checks if a byte is contained in an array of bytes
|
|
||||||
func inArray(s byte, list []byte) bool {
|
|
||||||
for _, el := range list {
|
|
||||||
if el == s {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// splitAndTrim splits a range string by spaces and cleans whitespaces
|
|
||||||
func splitAndTrim(s string) (result []string) {
|
|
||||||
last := 0
|
|
||||||
var lastChar byte
|
|
||||||
excludeFromSplit := []byte{'>', '<', '='}
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
if s[i] == ' ' && !inArray(lastChar, excludeFromSplit) {
|
|
||||||
if last < i-1 {
|
|
||||||
result = append(result, s[last:i])
|
|
||||||
}
|
|
||||||
last = i + 1
|
|
||||||
} else if s[i] != ' ' {
|
|
||||||
lastChar = s[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if last < len(s)-1 {
|
|
||||||
result = append(result, s[last:])
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, v := range result {
|
|
||||||
result[i] = strings.Replace(v, " ", "", -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parts := strings.Split(s, " ")
|
|
||||||
// for _, x := range parts {
|
|
||||||
// if s := strings.TrimSpace(x); len(s) != 0 {
|
|
||||||
// result = append(result, s)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// splitComparatorVersion splits the comparator from the version.
|
|
||||||
// Input must be free of leading or trailing spaces.
|
|
||||||
func splitComparatorVersion(s string) (string, string, error) {
|
|
||||||
i := strings.IndexFunc(s, unicode.IsDigit)
|
|
||||||
if i == -1 {
|
|
||||||
return "", "", fmt.Errorf("Could not get version from string: %q", s)
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(s[0:i]), s[i:], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getWildcardType will return the type of wildcard that the
|
|
||||||
// passed version contains
|
|
||||||
func getWildcardType(vStr string) wildcardType {
|
|
||||||
parts := strings.Split(vStr, ".")
|
|
||||||
nparts := len(parts)
|
|
||||||
wildcard := parts[nparts-1]
|
|
||||||
|
|
||||||
possibleWildcardType := wildcardTypefromInt(nparts)
|
|
||||||
if wildcard == "x" {
|
|
||||||
return possibleWildcardType
|
|
||||||
}
|
|
||||||
|
|
||||||
return noneWildcard
|
|
||||||
}
|
|
||||||
|
|
||||||
// createVersionFromWildcard will convert a wildcard version
|
|
||||||
// into a regular version, replacing 'x's with '0's, handling
|
|
||||||
// special cases like '1.x.x' and '1.x'
|
|
||||||
func createVersionFromWildcard(vStr string) string {
|
|
||||||
// handle 1.x.x
|
|
||||||
vStr2 := strings.Replace(vStr, ".x.x", ".x", 1)
|
|
||||||
vStr2 = strings.Replace(vStr2, ".x", ".0", 1)
|
|
||||||
parts := strings.Split(vStr2, ".")
|
|
||||||
|
|
||||||
// handle 1.x
|
|
||||||
if len(parts) == 2 {
|
|
||||||
return vStr2 + ".0"
|
|
||||||
}
|
|
||||||
|
|
||||||
return vStr2
|
|
||||||
}
|
|
||||||
|
|
||||||
// incrementMajorVersion will increment the major version
|
|
||||||
// of the passed version
|
|
||||||
func incrementMajorVersion(vStr string) (string, error) {
|
|
||||||
parts := strings.Split(vStr, ".")
|
|
||||||
i, err := strconv.Atoi(parts[0])
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
parts[0] = strconv.Itoa(i + 1)
|
|
||||||
|
|
||||||
return strings.Join(parts, "."), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// incrementMajorVersion will increment the minor version
|
|
||||||
// of the passed version
|
|
||||||
func incrementMinorVersion(vStr string) (string, error) {
|
|
||||||
parts := strings.Split(vStr, ".")
|
|
||||||
i, err := strconv.Atoi(parts[1])
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
parts[1] = strconv.Itoa(i + 1)
|
|
||||||
|
|
||||||
return strings.Join(parts, "."), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// expandWildcardVersion will expand wildcards inside versions
|
|
||||||
// following these rules:
|
|
||||||
//
|
|
||||||
// * when dealing with patch wildcards:
|
|
||||||
// >= 1.2.x will become >= 1.2.0
|
|
||||||
// <= 1.2.x will become < 1.3.0
|
|
||||||
// > 1.2.x will become >= 1.3.0
|
|
||||||
// < 1.2.x will become < 1.2.0
|
|
||||||
// != 1.2.x will become < 1.2.0 >= 1.3.0
|
|
||||||
//
|
|
||||||
// * when dealing with minor wildcards:
|
|
||||||
// >= 1.x will become >= 1.0.0
|
|
||||||
// <= 1.x will become < 2.0.0
|
|
||||||
// > 1.x will become >= 2.0.0
|
|
||||||
// < 1.0 will become < 1.0.0
|
|
||||||
// != 1.x will become < 1.0.0 >= 2.0.0
|
|
||||||
//
|
|
||||||
// * when dealing with wildcards without
|
|
||||||
// version operator:
|
|
||||||
// 1.2.x will become >= 1.2.0 < 1.3.0
|
|
||||||
// 1.x will become >= 1.0.0 < 2.0.0
|
|
||||||
func expandWildcardVersion(parts [][]string) ([][]string, error) {
|
|
||||||
var expandedParts [][]string
|
|
||||||
for _, p := range parts {
|
|
||||||
var newParts []string
|
|
||||||
for _, ap := range p {
|
|
||||||
if strings.Index(ap, "x") != -1 {
|
|
||||||
opStr, vStr, err := splitComparatorVersion(ap)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
versionWildcardType := getWildcardType(vStr)
|
|
||||||
flatVersion := createVersionFromWildcard(vStr)
|
|
||||||
|
|
||||||
var resultOperator string
|
|
||||||
var shouldIncrementVersion bool
|
|
||||||
switch opStr {
|
|
||||||
case ">":
|
|
||||||
resultOperator = ">="
|
|
||||||
shouldIncrementVersion = true
|
|
||||||
case ">=":
|
|
||||||
resultOperator = ">="
|
|
||||||
case "<":
|
|
||||||
resultOperator = "<"
|
|
||||||
case "<=":
|
|
||||||
resultOperator = "<"
|
|
||||||
shouldIncrementVersion = true
|
|
||||||
case "", "=", "==":
|
|
||||||
newParts = append(newParts, ">="+flatVersion)
|
|
||||||
resultOperator = "<"
|
|
||||||
shouldIncrementVersion = true
|
|
||||||
case "!=", "!":
|
|
||||||
newParts = append(newParts, "<"+flatVersion)
|
|
||||||
resultOperator = ">="
|
|
||||||
shouldIncrementVersion = true
|
|
||||||
}
|
|
||||||
|
|
||||||
var resultVersion string
|
|
||||||
if shouldIncrementVersion {
|
|
||||||
switch versionWildcardType {
|
|
||||||
case patchWildcard:
|
|
||||||
resultVersion, _ = incrementMinorVersion(flatVersion)
|
|
||||||
case minorWildcard:
|
|
||||||
resultVersion, _ = incrementMajorVersion(flatVersion)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
resultVersion = flatVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
ap = resultOperator + resultVersion
|
|
||||||
}
|
|
||||||
newParts = append(newParts, ap)
|
|
||||||
}
|
|
||||||
expandedParts = append(expandedParts, newParts)
|
|
||||||
}
|
|
||||||
|
|
||||||
return expandedParts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseComparator(s string) comparator {
|
|
||||||
switch s {
|
|
||||||
case "==":
|
|
||||||
fallthrough
|
|
||||||
case "":
|
|
||||||
fallthrough
|
|
||||||
case "=":
|
|
||||||
return compEQ
|
|
||||||
case ">":
|
|
||||||
return compGT
|
|
||||||
case ">=":
|
|
||||||
return compGE
|
|
||||||
case "<":
|
|
||||||
return compLT
|
|
||||||
case "<=":
|
|
||||||
return compLE
|
|
||||||
case "!":
|
|
||||||
fallthrough
|
|
||||||
case "!=":
|
|
||||||
return compNE
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustParseRange is like ParseRange but panics if the range cannot be parsed.
|
|
||||||
func MustParseRange(s string) Range {
|
|
||||||
r, err := ParseRange(s)
|
|
||||||
if err != nil {
|
|
||||||
panic(`semver: ParseRange(` + s + `): ` + err.Error())
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
418
vendor/github.com/blang/semver/semver.go
generated
vendored
418
vendor/github.com/blang/semver/semver.go
generated
vendored
@ -1,418 +0,0 @@
|
|||||||
package semver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
numbers string = "0123456789"
|
|
||||||
alphas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-"
|
|
||||||
alphanum = alphas + numbers
|
|
||||||
)
|
|
||||||
|
|
||||||
// SpecVersion is the latest fully supported spec version of semver
|
|
||||||
var SpecVersion = Version{
|
|
||||||
Major: 2,
|
|
||||||
Minor: 0,
|
|
||||||
Patch: 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version represents a semver compatible version
|
|
||||||
type Version struct {
|
|
||||||
Major uint64
|
|
||||||
Minor uint64
|
|
||||||
Patch uint64
|
|
||||||
Pre []PRVersion
|
|
||||||
Build []string //No Precendence
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version to string
|
|
||||||
func (v Version) String() string {
|
|
||||||
b := make([]byte, 0, 5)
|
|
||||||
b = strconv.AppendUint(b, v.Major, 10)
|
|
||||||
b = append(b, '.')
|
|
||||||
b = strconv.AppendUint(b, v.Minor, 10)
|
|
||||||
b = append(b, '.')
|
|
||||||
b = strconv.AppendUint(b, v.Patch, 10)
|
|
||||||
|
|
||||||
if len(v.Pre) > 0 {
|
|
||||||
b = append(b, '-')
|
|
||||||
b = append(b, v.Pre[0].String()...)
|
|
||||||
|
|
||||||
for _, pre := range v.Pre[1:] {
|
|
||||||
b = append(b, '.')
|
|
||||||
b = append(b, pre.String()...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(v.Build) > 0 {
|
|
||||||
b = append(b, '+')
|
|
||||||
b = append(b, v.Build[0]...)
|
|
||||||
|
|
||||||
for _, build := range v.Build[1:] {
|
|
||||||
b = append(b, '.')
|
|
||||||
b = append(b, build...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Equals checks if v is equal to o.
|
|
||||||
func (v Version) Equals(o Version) bool {
|
|
||||||
return (v.Compare(o) == 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EQ checks if v is equal to o.
|
|
||||||
func (v Version) EQ(o Version) bool {
|
|
||||||
return (v.Compare(o) == 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NE checks if v is not equal to o.
|
|
||||||
func (v Version) NE(o Version) bool {
|
|
||||||
return (v.Compare(o) != 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GT checks if v is greater than o.
|
|
||||||
func (v Version) GT(o Version) bool {
|
|
||||||
return (v.Compare(o) == 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GTE checks if v is greater than or equal to o.
|
|
||||||
func (v Version) GTE(o Version) bool {
|
|
||||||
return (v.Compare(o) >= 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GE checks if v is greater than or equal to o.
|
|
||||||
func (v Version) GE(o Version) bool {
|
|
||||||
return (v.Compare(o) >= 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LT checks if v is less than o.
|
|
||||||
func (v Version) LT(o Version) bool {
|
|
||||||
return (v.Compare(o) == -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LTE checks if v is less than or equal to o.
|
|
||||||
func (v Version) LTE(o Version) bool {
|
|
||||||
return (v.Compare(o) <= 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LE checks if v is less than or equal to o.
|
|
||||||
func (v Version) LE(o Version) bool {
|
|
||||||
return (v.Compare(o) <= 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare compares Versions v to o:
|
|
||||||
// -1 == v is less than o
|
|
||||||
// 0 == v is equal to o
|
|
||||||
// 1 == v is greater than o
|
|
||||||
func (v Version) Compare(o Version) int {
|
|
||||||
if v.Major != o.Major {
|
|
||||||
if v.Major > o.Major {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if v.Minor != o.Minor {
|
|
||||||
if v.Minor > o.Minor {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if v.Patch != o.Patch {
|
|
||||||
if v.Patch > o.Patch {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Quick comparison if a version has no prerelease versions
|
|
||||||
if len(v.Pre) == 0 && len(o.Pre) == 0 {
|
|
||||||
return 0
|
|
||||||
} else if len(v.Pre) == 0 && len(o.Pre) > 0 {
|
|
||||||
return 1
|
|
||||||
} else if len(v.Pre) > 0 && len(o.Pre) == 0 {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for ; i < len(v.Pre) && i < len(o.Pre); i++ {
|
|
||||||
if comp := v.Pre[i].Compare(o.Pre[i]); comp == 0 {
|
|
||||||
continue
|
|
||||||
} else if comp == 1 {
|
|
||||||
return 1
|
|
||||||
} else {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If all pr versions are the equal but one has further prversion, this one greater
|
|
||||||
if i == len(v.Pre) && i == len(o.Pre) {
|
|
||||||
return 0
|
|
||||||
} else if i == len(v.Pre) && i < len(o.Pre) {
|
|
||||||
return -1
|
|
||||||
} else {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate validates v and returns error in case
|
|
||||||
func (v Version) Validate() error {
|
|
||||||
// Major, Minor, Patch already validated using uint64
|
|
||||||
|
|
||||||
for _, pre := range v.Pre {
|
|
||||||
if !pre.IsNum { //Numeric prerelease versions already uint64
|
|
||||||
if len(pre.VersionStr) == 0 {
|
|
||||||
return fmt.Errorf("Prerelease can not be empty %q", pre.VersionStr)
|
|
||||||
}
|
|
||||||
if !containsOnly(pre.VersionStr, alphanum) {
|
|
||||||
return fmt.Errorf("Invalid character(s) found in prerelease %q", pre.VersionStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, build := range v.Build {
|
|
||||||
if len(build) == 0 {
|
|
||||||
return fmt.Errorf("Build meta data can not be empty %q", build)
|
|
||||||
}
|
|
||||||
if !containsOnly(build, alphanum) {
|
|
||||||
return fmt.Errorf("Invalid character(s) found in build meta data %q", build)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error
|
|
||||||
func New(s string) (vp *Version, err error) {
|
|
||||||
v, err := Parse(s)
|
|
||||||
vp = &v
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make is an alias for Parse, parses version string and returns a validated Version or error
|
|
||||||
func Make(s string) (Version, error) {
|
|
||||||
return Parse(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseTolerant allows for certain version specifications that do not strictly adhere to semver
|
|
||||||
// specs to be parsed by this library. It does so by normalizing versions before passing them to
|
|
||||||
// Parse(). It currently trims spaces, removes a "v" prefix, and adds a 0 patch number to versions
|
|
||||||
// with only major and minor components specified
|
|
||||||
func ParseTolerant(s string) (Version, error) {
|
|
||||||
s = strings.TrimSpace(s)
|
|
||||||
s = strings.TrimPrefix(s, "v")
|
|
||||||
|
|
||||||
// Split into major.minor.(patch+pr+meta)
|
|
||||||
parts := strings.SplitN(s, ".", 3)
|
|
||||||
if len(parts) < 3 {
|
|
||||||
if strings.ContainsAny(parts[len(parts)-1], "+-") {
|
|
||||||
return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data")
|
|
||||||
}
|
|
||||||
for len(parts) < 3 {
|
|
||||||
parts = append(parts, "0")
|
|
||||||
}
|
|
||||||
s = strings.Join(parts, ".")
|
|
||||||
}
|
|
||||||
|
|
||||||
return Parse(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse parses version string and returns a validated Version or error
|
|
||||||
func Parse(s string) (Version, error) {
|
|
||||||
if len(s) == 0 {
|
|
||||||
return Version{}, errors.New("Version string empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split into major.minor.(patch+pr+meta)
|
|
||||||
parts := strings.SplitN(s, ".", 3)
|
|
||||||
if len(parts) != 3 {
|
|
||||||
return Version{}, errors.New("No Major.Minor.Patch elements found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Major
|
|
||||||
if !containsOnly(parts[0], numbers) {
|
|
||||||
return Version{}, fmt.Errorf("Invalid character(s) found in major number %q", parts[0])
|
|
||||||
}
|
|
||||||
if hasLeadingZeroes(parts[0]) {
|
|
||||||
return Version{}, fmt.Errorf("Major number must not contain leading zeroes %q", parts[0])
|
|
||||||
}
|
|
||||||
major, err := strconv.ParseUint(parts[0], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return Version{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Minor
|
|
||||||
if !containsOnly(parts[1], numbers) {
|
|
||||||
return Version{}, fmt.Errorf("Invalid character(s) found in minor number %q", parts[1])
|
|
||||||
}
|
|
||||||
if hasLeadingZeroes(parts[1]) {
|
|
||||||
return Version{}, fmt.Errorf("Minor number must not contain leading zeroes %q", parts[1])
|
|
||||||
}
|
|
||||||
minor, err := strconv.ParseUint(parts[1], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return Version{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
v := Version{}
|
|
||||||
v.Major = major
|
|
||||||
v.Minor = minor
|
|
||||||
|
|
||||||
var build, prerelease []string
|
|
||||||
patchStr := parts[2]
|
|
||||||
|
|
||||||
if buildIndex := strings.IndexRune(patchStr, '+'); buildIndex != -1 {
|
|
||||||
build = strings.Split(patchStr[buildIndex+1:], ".")
|
|
||||||
patchStr = patchStr[:buildIndex]
|
|
||||||
}
|
|
||||||
|
|
||||||
if preIndex := strings.IndexRune(patchStr, '-'); preIndex != -1 {
|
|
||||||
prerelease = strings.Split(patchStr[preIndex+1:], ".")
|
|
||||||
patchStr = patchStr[:preIndex]
|
|
||||||
}
|
|
||||||
|
|
||||||
if !containsOnly(patchStr, numbers) {
|
|
||||||
return Version{}, fmt.Errorf("Invalid character(s) found in patch number %q", patchStr)
|
|
||||||
}
|
|
||||||
if hasLeadingZeroes(patchStr) {
|
|
||||||
return Version{}, fmt.Errorf("Patch number must not contain leading zeroes %q", patchStr)
|
|
||||||
}
|
|
||||||
patch, err := strconv.ParseUint(patchStr, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return Version{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
v.Patch = patch
|
|
||||||
|
|
||||||
// Prerelease
|
|
||||||
for _, prstr := range prerelease {
|
|
||||||
parsedPR, err := NewPRVersion(prstr)
|
|
||||||
if err != nil {
|
|
||||||
return Version{}, err
|
|
||||||
}
|
|
||||||
v.Pre = append(v.Pre, parsedPR)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build meta data
|
|
||||||
for _, str := range build {
|
|
||||||
if len(str) == 0 {
|
|
||||||
return Version{}, errors.New("Build meta data is empty")
|
|
||||||
}
|
|
||||||
if !containsOnly(str, alphanum) {
|
|
||||||
return Version{}, fmt.Errorf("Invalid character(s) found in build meta data %q", str)
|
|
||||||
}
|
|
||||||
v.Build = append(v.Build, str)
|
|
||||||
}
|
|
||||||
|
|
||||||
return v, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustParse is like Parse but panics if the version cannot be parsed.
|
|
||||||
func MustParse(s string) Version {
|
|
||||||
v, err := Parse(s)
|
|
||||||
if err != nil {
|
|
||||||
panic(`semver: Parse(` + s + `): ` + err.Error())
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// PRVersion represents a PreRelease Version
|
|
||||||
type PRVersion struct {
|
|
||||||
VersionStr string
|
|
||||||
VersionNum uint64
|
|
||||||
IsNum bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPRVersion creates a new valid prerelease version
|
|
||||||
func NewPRVersion(s string) (PRVersion, error) {
|
|
||||||
if len(s) == 0 {
|
|
||||||
return PRVersion{}, errors.New("Prerelease is empty")
|
|
||||||
}
|
|
||||||
v := PRVersion{}
|
|
||||||
if containsOnly(s, numbers) {
|
|
||||||
if hasLeadingZeroes(s) {
|
|
||||||
return PRVersion{}, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s)
|
|
||||||
}
|
|
||||||
num, err := strconv.ParseUint(s, 10, 64)
|
|
||||||
|
|
||||||
// Might never be hit, but just in case
|
|
||||||
if err != nil {
|
|
||||||
return PRVersion{}, err
|
|
||||||
}
|
|
||||||
v.VersionNum = num
|
|
||||||
v.IsNum = true
|
|
||||||
} else if containsOnly(s, alphanum) {
|
|
||||||
v.VersionStr = s
|
|
||||||
v.IsNum = false
|
|
||||||
} else {
|
|
||||||
return PRVersion{}, fmt.Errorf("Invalid character(s) found in prerelease %q", s)
|
|
||||||
}
|
|
||||||
return v, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNumeric checks if prerelease-version is numeric
|
|
||||||
func (v PRVersion) IsNumeric() bool {
|
|
||||||
return v.IsNum
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare compares two PreRelease Versions v and o:
|
|
||||||
// -1 == v is less than o
|
|
||||||
// 0 == v is equal to o
|
|
||||||
// 1 == v is greater than o
|
|
||||||
func (v PRVersion) Compare(o PRVersion) int {
|
|
||||||
if v.IsNum && !o.IsNum {
|
|
||||||
return -1
|
|
||||||
} else if !v.IsNum && o.IsNum {
|
|
||||||
return 1
|
|
||||||
} else if v.IsNum && o.IsNum {
|
|
||||||
if v.VersionNum == o.VersionNum {
|
|
||||||
return 0
|
|
||||||
} else if v.VersionNum > o.VersionNum {
|
|
||||||
return 1
|
|
||||||
} else {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
} else { // both are Alphas
|
|
||||||
if v.VersionStr == o.VersionStr {
|
|
||||||
return 0
|
|
||||||
} else if v.VersionStr > o.VersionStr {
|
|
||||||
return 1
|
|
||||||
} else {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PreRelease version to string
|
|
||||||
func (v PRVersion) String() string {
|
|
||||||
if v.IsNum {
|
|
||||||
return strconv.FormatUint(v.VersionNum, 10)
|
|
||||||
}
|
|
||||||
return v.VersionStr
|
|
||||||
}
|
|
||||||
|
|
||||||
func containsOnly(s string, set string) bool {
|
|
||||||
return strings.IndexFunc(s, func(r rune) bool {
|
|
||||||
return !strings.ContainsRune(set, r)
|
|
||||||
}) == -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasLeadingZeroes(s string) bool {
|
|
||||||
return len(s) > 1 && s[0] == '0'
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBuildVersion creates a new valid build version
|
|
||||||
func NewBuildVersion(s string) (string, error) {
|
|
||||||
if len(s) == 0 {
|
|
||||||
return "", errors.New("Buildversion is empty")
|
|
||||||
}
|
|
||||||
if !containsOnly(s, alphanum) {
|
|
||||||
return "", fmt.Errorf("Invalid character(s) found in build meta data %q", s)
|
|
||||||
}
|
|
||||||
return s, nil
|
|
||||||
}
|
|
28
vendor/github.com/blang/semver/sort.go
generated
vendored
28
vendor/github.com/blang/semver/sort.go
generated
vendored
@ -1,28 +0,0 @@
|
|||||||
package semver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Versions represents multiple versions.
|
|
||||||
type Versions []Version
|
|
||||||
|
|
||||||
// Len returns length of version collection
|
|
||||||
func (s Versions) Len() int {
|
|
||||||
return len(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap swaps two versions inside the collection by its indices
|
|
||||||
func (s Versions) Swap(i, j int) {
|
|
||||||
s[i], s[j] = s[j], s[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Less checks if version at index i is less than version at index j
|
|
||||||
func (s Versions) Less(i, j int) bool {
|
|
||||||
return s[i].LT(s[j])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort sorts a slice of versions
|
|
||||||
func Sort(versions []Version) {
|
|
||||||
sort.Sort(Versions(versions))
|
|
||||||
}
|
|
30
vendor/github.com/blang/semver/sql.go
generated
vendored
30
vendor/github.com/blang/semver/sql.go
generated
vendored
@ -1,30 +0,0 @@
|
|||||||
package semver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql/driver"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Scan implements the database/sql.Scanner interface.
|
|
||||||
func (v *Version) Scan(src interface{}) (err error) {
|
|
||||||
var str string
|
|
||||||
switch src := src.(type) {
|
|
||||||
case string:
|
|
||||||
str = src
|
|
||||||
case []byte:
|
|
||||||
str = string(src)
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Version.Scan: cannot convert %T to string.", src)
|
|
||||||
}
|
|
||||||
|
|
||||||
if t, err := Parse(str); err == nil {
|
|
||||||
*v = t
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value implements the database/sql/driver.Valuer interface.
|
|
||||||
func (v Version) Value() (driver.Value, error) {
|
|
||||||
return v.String(), nil
|
|
||||||
}
|
|
25
vendor/github.com/containerd/nri/.golangci.yml
generated
vendored
25
vendor/github.com/containerd/nri/.golangci.yml
generated
vendored
@ -1,22 +1,41 @@
|
|||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
- structcheck
|
|
||||||
- varcheck
|
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- unconvert
|
- unconvert
|
||||||
- gofmt
|
- gofmt
|
||||||
- goimports
|
- goimports
|
||||||
- golint
|
|
||||||
- ineffassign
|
- ineffassign
|
||||||
- vet
|
- vet
|
||||||
- unused
|
- unused
|
||||||
- misspell
|
- misspell
|
||||||
|
- revive
|
||||||
disable:
|
disable:
|
||||||
- errcheck
|
- errcheck
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
include:
|
include:
|
||||||
- EXC0002
|
- EXC0002
|
||||||
|
exclude-rules:
|
||||||
|
# We have protoc-generated ttRPC/gRPC code. When adding extra functions
|
||||||
|
# for generated types we want to consistently violate golint's semantic
|
||||||
|
# function name spelling rules, instead of inconsistently doing so only
|
||||||
|
# from automatically generated files. These rules are for that.
|
||||||
|
- path: pkg/adaptation/result.go
|
||||||
|
linters:
|
||||||
|
- golint
|
||||||
|
- revive
|
||||||
|
text: "should be claim"
|
||||||
|
# Ignore naming violation in the test suite as well.
|
||||||
|
- path: pkg/adaptation/adaptation_suite_test.go
|
||||||
|
linters:
|
||||||
|
- golint
|
||||||
|
- revive
|
||||||
|
text: "should be strip"
|
||||||
|
# Differ copies pods and containers with Mutexes for diffing. Should be harmless.
|
||||||
|
- path: plugins/differ/nri-differ.go
|
||||||
|
linters:
|
||||||
|
- govet
|
||||||
|
text: "copylocks: .*protobuf/internal/impl.MessageState.*"
|
||||||
|
|
||||||
run:
|
run:
|
||||||
timeout: 2m
|
timeout: 2m
|
||||||
|
165
vendor/github.com/containerd/nri/Makefile
generated
vendored
165
vendor/github.com/containerd/nri/Makefile
generated
vendored
@ -12,5 +12,166 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
all:
|
PROTO_SOURCES = $(shell find . -name '*.proto' | grep -v /vendor/)
|
||||||
go build -v
|
PROTO_GOFILES = $(patsubst %.proto,%.pb.go,$(PROTO_SOURCES))
|
||||||
|
PROTO_INCLUDE = -I$(PWD):/usr/local/include:/usr/include
|
||||||
|
PROTO_OPTIONS = --proto_path=. $(PROTO_INCLUDE) \
|
||||||
|
--go_opt=paths=source_relative --go_out=. \
|
||||||
|
--go-ttrpc_opt=paths=source_relative --go-ttrpc_out=.
|
||||||
|
PROTO_COMPILE = PATH=$(PATH):$(shell go env GOPATH)/bin; protoc $(PROTO_OPTIONS)
|
||||||
|
|
||||||
|
GO_CMD := go
|
||||||
|
GO_BUILD := $(GO_CMD) build
|
||||||
|
GO_INSTALL := $(GO_CMD) install
|
||||||
|
GO_TEST := $(GO_CMD) test
|
||||||
|
GO_LINT := golint -set_exit_status
|
||||||
|
GO_FMT := gofmt
|
||||||
|
GO_VET := $(GO_CMD) vet
|
||||||
|
|
||||||
|
GO_MODULES := $(shell $(GO_CMD) list ./...)
|
||||||
|
|
||||||
|
GOLANG_CILINT := golangci-lint
|
||||||
|
GINKGO := ginkgo
|
||||||
|
|
||||||
|
BUILD_PATH := $(shell pwd)/build
|
||||||
|
BIN_PATH := $(BUILD_PATH)/bin
|
||||||
|
COVERAGE_PATH := $(BUILD_PATH)/coverage
|
||||||
|
|
||||||
|
PLUGINS := \
|
||||||
|
$(BIN_PATH)/logger \
|
||||||
|
$(BIN_PATH)/device-injector \
|
||||||
|
$(BIN_PATH)/hook-injector \
|
||||||
|
$(BIN_PATH)/differ \
|
||||||
|
$(BIN_PATH)/v010-adapter \
|
||||||
|
$(BIN_PATH)/template
|
||||||
|
|
||||||
|
|
||||||
|
ifneq ($(V),1)
|
||||||
|
Q := @
|
||||||
|
endif
|
||||||
|
|
||||||
|
#
|
||||||
|
# top-level targets
|
||||||
|
#
|
||||||
|
|
||||||
|
all: build build-plugins
|
||||||
|
|
||||||
|
build: build-proto build-check
|
||||||
|
|
||||||
|
clean: clean-plugins
|
||||||
|
|
||||||
|
allclean: clean clean-cache
|
||||||
|
|
||||||
|
test: test-gopkgs
|
||||||
|
|
||||||
|
#
|
||||||
|
# build targets
|
||||||
|
#
|
||||||
|
|
||||||
|
build-proto: $(PROTO_GOFILES)
|
||||||
|
|
||||||
|
build-plugins: $(PLUGINS)
|
||||||
|
|
||||||
|
build-check:
|
||||||
|
$(Q)$(GO_BUILD) -v $(GO_MODULES)
|
||||||
|
|
||||||
|
#
|
||||||
|
# clean targets
|
||||||
|
#
|
||||||
|
|
||||||
|
clean-plugins:
|
||||||
|
$(Q)rm -f $(PLUGINS)
|
||||||
|
|
||||||
|
clean-cache:
|
||||||
|
$(Q)$(GO_CMD) clean -cache -testcache
|
||||||
|
|
||||||
|
#
|
||||||
|
# plugins build targets
|
||||||
|
#
|
||||||
|
|
||||||
|
$(BIN_PATH)/logger: $(wildcard plugins/logger/*.go)
|
||||||
|
$(Q)echo "Building $@..."; \
|
||||||
|
cd $(dir $<) && $(GO_BUILD) -o $@ .
|
||||||
|
|
||||||
|
$(BIN_PATH)/device-injector: $(wildcard plugins/device-injector/*.go)
|
||||||
|
$(Q)echo "Building $@..."; \
|
||||||
|
cd $(dir $<) && $(GO_BUILD) -o $@ .
|
||||||
|
|
||||||
|
$(BIN_PATH)/hook-injector: $(wildcard plugins/hook-injector/*.go)
|
||||||
|
$(Q)echo "Building $@..."; \
|
||||||
|
cd $(dir $<) && $(GO_BUILD) -o $@ .
|
||||||
|
|
||||||
|
$(BIN_PATH)/differ: $(wildcard plugins/differ/*.go)
|
||||||
|
$(Q)echo "Building $@..."; \
|
||||||
|
cd $(dir $<) && $(GO_BUILD) -o $@ .
|
||||||
|
|
||||||
|
$(BIN_PATH)/v010-adapter: $(wildcard plugins/v010-adapter/*.go)
|
||||||
|
$(Q)echo "Building $@..."; \
|
||||||
|
cd $(dir $<) && $(GO_BUILD) -o $@ .
|
||||||
|
|
||||||
|
$(BIN_PATH)/template: $(wildcard plugins/template/*.go)
|
||||||
|
$(Q)echo "Building $@..."; \
|
||||||
|
cd $(dir $<) && $(GO_BUILD) -o $@ .
|
||||||
|
|
||||||
|
#
|
||||||
|
# test targets
|
||||||
|
#
|
||||||
|
|
||||||
|
test-gopkgs: ginkgo-tests
|
||||||
|
|
||||||
|
ginkgo-tests:
|
||||||
|
$(Q)$(GINKGO) run \
|
||||||
|
--race \
|
||||||
|
--trace \
|
||||||
|
--cover \
|
||||||
|
--covermode atomic \
|
||||||
|
--output-dir $(COVERAGE_PATH) \
|
||||||
|
--junit-report junit.xml \
|
||||||
|
--coverprofile coverprofile \
|
||||||
|
--succinct \
|
||||||
|
-r .; \
|
||||||
|
$(GO_CMD) tool cover -html=$(COVERAGE_PATH)/coverprofile -o $(COVERAGE_PATH)/coverage.html
|
||||||
|
|
||||||
|
codecov: SHELL := $(shell which bash)
|
||||||
|
codecov:
|
||||||
|
bash <(curl -s https://codecov.io/bash) -f $(COVERAGE_PATH)/coverprofile
|
||||||
|
|
||||||
|
#
|
||||||
|
# other validation targets
|
||||||
|
#
|
||||||
|
|
||||||
|
fmt format:
|
||||||
|
$(Q)$(GO_FMT) -s -d -e .
|
||||||
|
|
||||||
|
lint:
|
||||||
|
$(Q)$(GO_LINT) -set_exit_status ./...
|
||||||
|
|
||||||
|
vet:
|
||||||
|
$(Q)$(GO_VET) ./...
|
||||||
|
|
||||||
|
golangci-lint:
|
||||||
|
$(Q)$(GOLANG_CILINT) run
|
||||||
|
|
||||||
|
#
|
||||||
|
# proto generation targets
|
||||||
|
#
|
||||||
|
|
||||||
|
%.pb.go: %.proto
|
||||||
|
$(Q)echo "Generating $@..."; \
|
||||||
|
$(PROTO_COMPILE) $<
|
||||||
|
|
||||||
|
#
|
||||||
|
# targets for installing dependencies
|
||||||
|
#
|
||||||
|
|
||||||
|
install-protoc install-protobuf:
|
||||||
|
$(Q)./scripts/install-protobuf && \
|
||||||
|
|
||||||
|
install-ttrpc-plugin:
|
||||||
|
$(Q)$(GO_INSTALL) github.com/containerd/ttrpc/cmd/protoc-gen-go-ttrpc@74421d10189e8c118870d294c9f7f62db2d33ec1
|
||||||
|
|
||||||
|
install-protoc-dependencies:
|
||||||
|
$(Q)$(GO_INSTALL) google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.0
|
||||||
|
|
||||||
|
install-ginkgo:
|
||||||
|
$(Q)$(GO_INSTALL) -mod=mod github.com/onsi/ginkgo/v2/ginkgo
|
||||||
|
115
vendor/github.com/containerd/nri/README-v0.1.0.md
generated
vendored
Normal file
115
vendor/github.com/containerd/nri/README-v0.1.0.md
generated
vendored
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
# nri - Node Resource Interface
|
||||||
|
|
||||||
|
[](https://pkg.go.dev/github.com/containerd/nri)
|
||||||
|
[](https://github.com/containerd/nri/actions?query=workflow%3ACI)
|
||||||
|
[](https://codecov.io/gh/containerd/nri)
|
||||||
|
[](https://goreportcard.com/report/github.com/containerd/nri)
|
||||||
|
|
||||||
|
*This project is currently in DRAFT status*
|
||||||
|
|
||||||
|
This project is a WIP for a new, CNI like, interface for managing resources on a node for Pods and Containers.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
The basic interface, concepts and plugin design of the Container Network Interface (CNI) is an elegant way to handle multiple implementations of the network stack for containers.
|
||||||
|
This concept can be used for additional interfaces to customize a container's runtime environment.
|
||||||
|
This proposal covers a new interface for resource management on a node with a structured API and plugin design for containers.
|
||||||
|
|
||||||
|
## Lifecycle
|
||||||
|
|
||||||
|
The big selling point for CNI is that it has a structured interface for modifying the network namespace for a container.
|
||||||
|
This is different from generic hooks as they lack a type safe API injected into the lifecycle of a container.
|
||||||
|
The lifecycle point that CNI and NRI plugins will be injected into is the point between `Create` and `Start` of the container's init process.
|
||||||
|
|
||||||
|
`Create->NRI->Start`
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Configuration is split into two parts. One is the payload that is specific to a plugin invocation while the second is the host level configuration and options that specify what plugins to run and provide additional configuration to a plugin.
|
||||||
|
|
||||||
|
### Filepath and Binaries
|
||||||
|
|
||||||
|
Plugin binary paths can be configured via the consumer but will default to `/opt/nri/bin`.
|
||||||
|
Binaries are named with their type as the binary name, same as the CNI plugin naming scheme.
|
||||||
|
|
||||||
|
### Host Level Config
|
||||||
|
|
||||||
|
The config's default location will be `/etc/nri/resource.d/*.conf`.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": "0.1",
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"type": "konfine",
|
||||||
|
"conf": {
|
||||||
|
"systemReserved": [0, 1]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "clearcfs"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Input
|
||||||
|
|
||||||
|
Input to a plugin is provided via `STDIN` as a `json` payload.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": "0.1",
|
||||||
|
"state": "create",
|
||||||
|
"id": "redis",
|
||||||
|
"pid": 1234,
|
||||||
|
"spec": {
|
||||||
|
"resources": {},
|
||||||
|
"cgroupsPath": "default/redis",
|
||||||
|
"namespaces": {
|
||||||
|
"pid": "/proc/44/ns/pid",
|
||||||
|
"mount": "/proc/44/ns/mnt",
|
||||||
|
"net": "/proc/44/ns/net"
|
||||||
|
},
|
||||||
|
"annotations": {
|
||||||
|
"qos.class": "ls"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Output
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": "0.1",
|
||||||
|
"state": "create",
|
||||||
|
"id": "redis",
|
||||||
|
"pid": 1234,
|
||||||
|
"cgroupsPath": "qos-ls/default/redis"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
* Invoke - provides invocations into different lifecycle changes of a container
|
||||||
|
- states: `setup|pause|resume|update|delete`
|
||||||
|
|
||||||
|
## Packages
|
||||||
|
|
||||||
|
A Go based API and client package will be created for both producers of plugins and consumers, commonly being the container runtime (containerd).
|
||||||
|
|
||||||
|
### Sample Plugin
|
||||||
|
|
||||||
|
* [clearcfs](examples/clearcfs/main.go)
|
||||||
|
|
||||||
|
## Project details
|
||||||
|
|
||||||
|
nri is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
|
||||||
|
As a containerd sub-project, you will find the:
|
||||||
|
|
||||||
|
* [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md),
|
||||||
|
* [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS),
|
||||||
|
* and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md)
|
||||||
|
|
||||||
|
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
395
vendor/github.com/containerd/nri/README.md
generated
vendored
395
vendor/github.com/containerd/nri/README.md
generated
vendored
@ -1,167 +1,306 @@
|
|||||||
# nri - Node Resource Interface
|
## Node Resource Interface, Revisited
|
||||||
|
|
||||||
[](https://pkg.go.dev/github.com/containerd/nri)
|
### Goal
|
||||||
[](https://github.com/containerd/nri/actions?query=workflow%3ACI)
|
|
||||||
[](https://codecov.io/gh/containerd/nri)
|
|
||||||
[](https://goreportcard.com/report/github.com/containerd/nri)
|
|
||||||
|
|
||||||
*This project is currently in DRAFT status*
|
NRI allows plugging domain- or vendor-specific custom logic into OCI-
|
||||||
|
compatible runtimes. This logic can make controlled changes to containers
|
||||||
|
or perform extra actions outside the scope of OCI at certain points in a
|
||||||
|
containers lifecycle. This can be used, for instance, for improved allocation
|
||||||
|
and management of devices and other container resources.
|
||||||
|
|
||||||
This project is a WIP for a new, CNI like, interface for managing resources on a node for Pods and Containers.
|
NRI defines the interfaces and implements the common infrastructure for
|
||||||
|
enabling such pluggable runtime extensions, NRI plugins. This also keeps
|
||||||
|
the plugins themselves runtime-agnostic.
|
||||||
|
|
||||||
## Documentation
|
The goal is to enable NRI support in the most commonly used OCI runtimes,
|
||||||
|
[containerd](https://github.com/containerd/containerd) and
|
||||||
|
[CRI-O](https://github.com/cri-o/cri-o).
|
||||||
|
|
||||||
The basic interface, concepts and plugin design of the Container Network Interface (CNI) is an elegant way to handle multiple implementations of the network stack for containers.
|
### Background
|
||||||
This concept can be used for additional interfaces to customize a container's runtime environment.
|
|
||||||
This proposal covers a new interface for resource management on a node with a structured API and plugin design for containers.
|
|
||||||
|
|
||||||
## Lifecycle
|
The revisited API is a major rewrite of NRI. It changes the scope of NRI
|
||||||
|
and how it gets integrated into runtimes. It reworks how plugins are
|
||||||
|
implemented, how they communicate with the runtime, and what kind of
|
||||||
|
changes they can make to containers.
|
||||||
|
|
||||||
The big selling point for CNI is that it has a structured interface for modifying the network namespace for a container.
|
[NRI v0.1.0](README-v0.1.0.md) used an OCI hook-like one-shot plugin invocation
|
||||||
This is different from generic hooks as they lack a type safe API injected into the lifecycle of a container.
|
mechanism where a separate instance of a plugin was spawned for every NRI
|
||||||
The lifecycle point that CNI and NRI plugins will be injected into is the point between `Create` and `Start` of the container's init process.
|
event. This instance then used its standard input and output to receive a
|
||||||
|
request and provide a response, both as JSON data.
|
||||||
|
|
||||||
`Create->NRI->Start`
|
Plugins in NRI are daemon-like entities. A single instance of a plugin is
|
||||||
|
now responsible for handling the full stream of NRI events and requests. A
|
||||||
|
unix-domain socket is used as the transport for communication. Instead of
|
||||||
|
JSON requests and responses NRI is defined as a formal, protobuf-based
|
||||||
|
'NRI plugin protocol' which is compiled into ttRPC bindings. This should
|
||||||
|
result in improved communication efficiency with lower per-message overhead,
|
||||||
|
and enable straightforward implementation of stateful NRI plugins.
|
||||||
|
|
||||||
## Configuration
|
### Components
|
||||||
|
|
||||||
Configuration is split into two parts. One is the payload that is specific to a plugin invocation while the second is the host level configuration and options that specify what plugins to run and provide additional configuration to a plugin.
|
The NRI implementation consists of a number of components. The core of
|
||||||
|
these are essential for implementing working end-to-end NRI support in
|
||||||
|
runtimes. These core components are the actual [NRI protocol](pkg/api),
|
||||||
|
and the [NRI runtime adaptation](pkg/adaptation).
|
||||||
|
|
||||||
### Filepath and Binaries
|
Together these establish the model of how a runtime interacts with NRI and
|
||||||
|
how plugins interact with containers in the runtime through NRI. They also
|
||||||
|
define under which conditions plugins can make changes to containers and
|
||||||
|
the extent of these changes.
|
||||||
|
|
||||||
Plugin binary paths can be configured via the consumer but will default to `/opt/nri/bin`.
|
The rest of the components are the [NRI plugin stub library](pkg/stub)
|
||||||
Binaries are named with their type as the binary name, same as the CNI plugin naming scheme.
|
and [some sample NRI plugins](plugins). [Some plugins](plugins/hook-injector)
|
||||||
|
implement useful functionality in real world scenarios. [A few](plugins/differ)
|
||||||
|
[others](plugins/logger) are useful for debugging. All of the sample plugins
|
||||||
|
serve as practical examples of how the stub library can be used to implement
|
||||||
|
NRI plugins.
|
||||||
|
|
||||||
### Host Level Config
|
### Protocol, Plugin API
|
||||||
|
|
||||||
The config's default location will be `/etc/nri/resource.d/*.conf`.
|
The core of NRI is defined by a protobuf [protocol definition](pkg/api/api.proto)
|
||||||
|
of the low-level plugin API. The API defines two services, Runtime and Plugin.
|
||||||
|
|
||||||
```json
|
The Runtime service is the public interface runtimes expose for NRI plugins. All
|
||||||
{
|
requests on this interface are initiated by the plugin. The interface provides
|
||||||
"version": "0.1",
|
functions for
|
||||||
"plugins": [
|
|
||||||
{
|
|
||||||
"type": "konfine",
|
|
||||||
"conf": {
|
|
||||||
"systemReserved": [0, 1]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "clearcfs"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Input
|
- initiating plugin registration
|
||||||
|
- requesting unsolicited updates to containers
|
||||||
|
|
||||||
Input to a plugin is provided via `STDIN` as a `json` payload.
|
The Plugin service is the public interface NRI uses to interact with plugins.
|
||||||
|
All requests on this interface are initiated by NRI/the runtime. The interface
|
||||||
|
provides functions for
|
||||||
|
|
||||||
```json
|
- configuring the plugin
|
||||||
{
|
- getting initial list of already existing pods and containers
|
||||||
"version": "0.1",
|
- hooking the plugin into pod/container lifecycle events
|
||||||
"state": "create",
|
- shutting down the plugin
|
||||||
"id": "redis",
|
|
||||||
"pid": 1234,
|
|
||||||
"spec": {
|
|
||||||
"resources": {},
|
|
||||||
"cgroupsPath": "default/redis",
|
|
||||||
"namespaces": {
|
|
||||||
"pid": "/proc/44/ns/pid",
|
|
||||||
"mount": "/proc/44/ns/mnt",
|
|
||||||
"net": "/proc/44/ns/net"
|
|
||||||
},
|
|
||||||
"annotations": {
|
|
||||||
"qos.class": "ls"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Output
|
#### Plugin Registration
|
||||||
|
|
||||||
```json
|
Before a plugin can start receiving and processing container events, it needs
|
||||||
{
|
to register itself with NRI. During registration the plugin and NRI perform a
|
||||||
"version": "0.1",
|
handshake sequence which consists of the following steps:
|
||||||
"state": "create",
|
|
||||||
"id": "redis",
|
|
||||||
"pid": 1234,
|
|
||||||
"cgroupsPath": "qos-ls/default/redis"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Commands
|
1. the plugin identifies itself to the runtime
|
||||||
|
2. NRI provides plugin-specific configuration data to the plugin
|
||||||
|
3. the plugin subscribes to pod and container lifecycle events of interest
|
||||||
|
4. NRI sends list of existing pods and containers to plugin
|
||||||
|
5. the plugin requests any updates deemed necessary to existing containers
|
||||||
|
|
||||||
* Invoke - provides invocations into different lifecycle changes of a container
|
The plugin identifies itself to NRI by a plugin name and a plugin index. The
|
||||||
- states: `setup|pause|resume|update|delete`
|
plugin index is used by NRI to determine in which order the plugin is hooked
|
||||||
|
into pod and container lifecycle event processing with respect to any other
|
||||||
|
plugins.
|
||||||
|
|
||||||
## Packages
|
The plugin name is used to pick plugin-specific data to send to the plugin
|
||||||
|
as configuration. This data is only present if the plugin has been launched
|
||||||
|
by NRI. If the plugin has been externally started it is expected to acquire
|
||||||
|
its configuration also by external means. The plugin subscribes to pod and
|
||||||
|
container lifecycle events of interest in its response to configuration.
|
||||||
|
|
||||||
A Go based API and client package will be created for both producers of plugins and consumers, commonly being the container runtime (containerd).
|
As the last step in the registration and handshaking process, NRI sends the
|
||||||
|
full set of pods and containers known to the runtime. The plugin can request
|
||||||
|
updates it considers necessary to any of the known containers in response.
|
||||||
|
|
||||||
### Sample Plugin
|
Once the handshake sequence is over and the plugin has registered with NRI,
|
||||||
|
it will start receiving pod and container lifecycle events according to its
|
||||||
|
subscription.
|
||||||
|
|
||||||
**clearcfs**
|
#### Pod Data and Available Lifecycle Events
|
||||||
|
|
||||||
Clear the cfs quotas for `ls` services.
|
<details>
|
||||||
|
<summary>NRI Pod Lifecycle Events</summary>
|
||||||
|
<p align="center">
|
||||||
|
<img src="./docs/nri-pod-lifecycle.svg" title="NRI Pod Lifecycle Events">
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
NRI plugins can subscribe to the following pod lifecycle events:
|
||||||
|
|
||||||
|
- creation
|
||||||
|
- stopping
|
||||||
|
- removal
|
||||||
|
|
||||||
|
The following pieces of pod metadata are available to plugins in NRI:
|
||||||
|
|
||||||
|
- ID
|
||||||
|
- name
|
||||||
|
- UID
|
||||||
|
- namespace
|
||||||
|
- labels
|
||||||
|
- annotations
|
||||||
|
- cgroup parent directory
|
||||||
|
- runtime handler name
|
||||||
|
|
||||||
|
#### Container Data and Available Lifecycle Events
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>NRI Container Lifecycle Events</summary>
|
||||||
|
<p align="center">
|
||||||
|
<img src="./docs/nri-container-lifecycle.svg" title="NRI Container Lifecycle Events">
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
NRI plugins can subscribe to the following container lifecycle events:
|
||||||
|
|
||||||
|
- creation (*)
|
||||||
|
- post-creation
|
||||||
|
- starting
|
||||||
|
- post-start
|
||||||
|
- updating (*)
|
||||||
|
- post-update
|
||||||
|
- stopping (*)
|
||||||
|
- removal
|
||||||
|
|
||||||
|
*) Plugins can request adjustment or updates to containers in response to
|
||||||
|
these events.
|
||||||
|
|
||||||
|
The following pieces of container metadata are available to plugins in NRI:
|
||||||
|
|
||||||
|
- ID
|
||||||
|
- pod ID
|
||||||
|
- name
|
||||||
|
- state
|
||||||
|
- labels
|
||||||
|
- annotations
|
||||||
|
- command line arguments
|
||||||
|
- environment variables
|
||||||
|
- mounts
|
||||||
|
- OCI hooks
|
||||||
|
- linux
|
||||||
|
- namespace IDs
|
||||||
|
- devices
|
||||||
|
- resources
|
||||||
|
- memory
|
||||||
|
- limit
|
||||||
|
- reservation
|
||||||
|
- swap limit
|
||||||
|
- kernel limit
|
||||||
|
- kernel TCP limit
|
||||||
|
- swappiness
|
||||||
|
- OOM disabled flag
|
||||||
|
- hierarchical accounting flag
|
||||||
|
- hugepage limits
|
||||||
|
- CPU
|
||||||
|
- shares
|
||||||
|
- quota
|
||||||
|
- period
|
||||||
|
- realtime runtime
|
||||||
|
- realtime period
|
||||||
|
- cpuset CPUs
|
||||||
|
- cpuset memory
|
||||||
|
- Block I/O class
|
||||||
|
- RDT class
|
||||||
|
|
||||||
|
Apart from data identifying the container, these pieces of information
|
||||||
|
represent the corresponding data in the container's OCI Spec.
|
||||||
|
|
||||||
|
#### Container Adjustment
|
||||||
|
|
||||||
|
During container creation plugins can request changes to the following
|
||||||
|
container parameters:
|
||||||
|
|
||||||
|
- annotations
|
||||||
|
- mounts
|
||||||
|
- environment variables
|
||||||
|
- OCI hooks
|
||||||
|
- linux
|
||||||
|
- devices
|
||||||
|
- resources
|
||||||
|
- memory
|
||||||
|
- limit
|
||||||
|
- reservation
|
||||||
|
- swap limit
|
||||||
|
- kernel limit
|
||||||
|
- kernel TCP limit
|
||||||
|
- swappiness
|
||||||
|
- OOM disabled flag
|
||||||
|
- hierarchical accounting flag
|
||||||
|
- hugepage limits
|
||||||
|
- CPU
|
||||||
|
- shares
|
||||||
|
- quota
|
||||||
|
- period
|
||||||
|
- realtime runtime
|
||||||
|
- realtime period
|
||||||
|
- cpuset CPUs
|
||||||
|
- cpuset memory
|
||||||
|
- Block I/O class
|
||||||
|
- RDT class
|
||||||
|
|
||||||
|
#### Container Updates
|
||||||
|
|
||||||
|
Once a container has been created plugins can request updates to them.
|
||||||
|
These updates can be requested in response to another containers creation
|
||||||
|
request, in response to any containers update request, in response to any
|
||||||
|
containers stop request, or they can be requested as part of a separate
|
||||||
|
unsolicited container update request. The following container parameters
|
||||||
|
can be updated this way:
|
||||||
|
|
||||||
|
- resources
|
||||||
|
- memory
|
||||||
|
- limit
|
||||||
|
- reservation
|
||||||
|
- swap limit
|
||||||
|
- kernel limit
|
||||||
|
- kernel TCP limit
|
||||||
|
- swappiness
|
||||||
|
- OOM disabled flag
|
||||||
|
- hierarchical accounting flag
|
||||||
|
- hugepage limits
|
||||||
|
- CPU
|
||||||
|
- shares
|
||||||
|
- quota
|
||||||
|
- period
|
||||||
|
- realtime runtime
|
||||||
|
- realtime period
|
||||||
|
- cpuset CPUs
|
||||||
|
- cpuset memory
|
||||||
|
- Block I/O class
|
||||||
|
- RDT class
|
||||||
|
|
||||||
|
|
||||||
```go
|
### Runtime Adaptation
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
The NRI [runtime adaptation](pkg/adaptation) package is the interface
|
||||||
"context"
|
runtimes use to integrate to NRI and interact with NRI plugins. It
|
||||||
"fmt"
|
implements basic plugin discovery, startup and configuration. It also
|
||||||
"os"
|
provides the functions necessary to hook NRI plugins into lifecycle
|
||||||
|
events of pods and containers from the runtime.
|
||||||
|
|
||||||
"github.com/containerd/containerd/pkg/nri/skel"
|
The package hides the fact that multiple NRI plugins might be processing
|
||||||
"github.com/containerd/containerd/pkg/nri/types"
|
any single pod or container lifecycle event. It takes care of invoking
|
||||||
"github.com/sirupsen/logrus"
|
plugins in the correct order and combining responses by multiple plugins
|
||||||
)
|
into a single one. While combining responses, the package detects any
|
||||||
|
unintentional conflicting changes made by multiple plugins to a single
|
||||||
|
container and flags such an event as an error to the runtime.
|
||||||
|
|
||||||
var max = []byte("max")
|
### Wrapped OCI Spec Generator
|
||||||
|
|
||||||
// clearCFS clears any cfs quotas for the containers
|
The [OCI Spec generator](pkg/runtime-tools/generate) package wraps the
|
||||||
type clearCFS struct {
|
[corresponding package](https://github.com/opencontainers/runtime-tools/tree/master/generate)
|
||||||
}
|
and adds functions for applying NRI container adjustments and updates to
|
||||||
|
OCI Specs. This package can be used by runtime NRI integration code to
|
||||||
|
apply NRI responses to containers.
|
||||||
|
|
||||||
func (c *clearCFS) Type() string {
|
### Plugin Stub Library
|
||||||
return "clearcfs"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *clearCFS) Invoke(ctx context.Context, r *types.Request) (*types.Result, error) {
|
The plugin stub hides many of the low-level details of implementing an NRI
|
||||||
result := r.NewResult()
|
plugin. It takes care of connection establishment, plugin registration,
|
||||||
if r.State != types.Create {
|
configuration, and event subscription. All [sample plugins](pkg/plugins)
|
||||||
return result, nil
|
are implemented using the stub. Any of these can be used as a tutorial on
|
||||||
}
|
how the stub library should be used.
|
||||||
switch r.Spec.Annotations["qos.class"] {
|
|
||||||
case "ls":
|
|
||||||
logrus.Debugf("clearing cfs for %s", r.ID)
|
|
||||||
group, err := cg.Load(r.Spec.CgroupsPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return result, group.Write(cg.CFSMax)
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
### Sample Plugins
|
||||||
ctx := context.Background()
|
|
||||||
if err := skel.Run(ctx, &clearCFS{}); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "%s", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Project details
|
The following sample plugins exist for NRI:
|
||||||
|
|
||||||
nri is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
|
- [logger](plugins/logger)
|
||||||
As a containerd sub-project, you will find the:
|
- [differ](plugins/differ)
|
||||||
|
- [device injector](plugins/device-injector)
|
||||||
|
- [OCI hook injector](plugins/hook-injector)
|
||||||
|
- [NRI v0.1.0 plugin adapter](plugins/v010-adapter)
|
||||||
|
|
||||||
* [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md),
|
Please see the documentation of these plugins for further details
|
||||||
* [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS),
|
about what and how each of these plugins can be used for.
|
||||||
* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
|
|
||||||
|
|
||||||
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
|
||||||
|
5
vendor/github.com/containerd/nri/client.go
generated
vendored
5
vendor/github.com/containerd/nri/client.go
generated
vendored
@ -28,7 +28,6 @@ import (
|
|||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
types "github.com/containerd/nri/types/v1"
|
types "github.com/containerd/nri/types/v1"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -107,7 +106,7 @@ func (c *Client) InvokeWithSandbox(ctx context.Context, task containerd.Task, st
|
|||||||
r.Conf = p.Conf
|
r.Conf = p.Conf
|
||||||
result, err := c.invokePlugin(ctx, p.Type, r)
|
result, err := c.invokePlugin(ctx, p.Type, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "plugin: %s", p.Type)
|
return nil, fmt.Errorf("plugin: %s: %w", p.Type, err)
|
||||||
}
|
}
|
||||||
r.Results = append(r.Results, result)
|
r.Results = append(r.Results, result)
|
||||||
}
|
}
|
||||||
@ -141,7 +140,7 @@ func (c *Client) invokePlugin(ctx context.Context, name string, r *types.Request
|
|||||||
}
|
}
|
||||||
var result types.Result
|
var result types.Result
|
||||||
if err := json.Unmarshal(out, &result); err != nil {
|
if err := json.Unmarshal(out, &result); err != nil {
|
||||||
return nil, errors.Errorf("failed to unmarshal plugin output: %s: %s", err.Error(), msg)
|
return nil, fmt.Errorf("failed to unmarshal plugin output %s: %w", msg, err)
|
||||||
}
|
}
|
||||||
if result.Err() != nil {
|
if result.Err() != nil {
|
||||||
return nil, result.Err()
|
return nil, result.Err()
|
||||||
|
504
vendor/github.com/containerd/nri/pkg/adaptation/adaptation.go
generated
vendored
Normal file
504
vendor/github.com/containerd/nri/pkg/adaptation/adaptation.go
generated
vendored
Normal file
@ -0,0 +1,504 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package adaptation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/containerd/nri/pkg/api"
|
||||||
|
"github.com/containerd/nri/pkg/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultConfigPath is the default path to the NRI configuration.
|
||||||
|
DefaultConfigPath = "/etc/nri/nri.conf"
|
||||||
|
// DefaultPluginPath is the default path to search for NRI plugins.
|
||||||
|
DefaultPluginPath = "/opt/nri/plugins"
|
||||||
|
// DefaultSocketPath is the default socket path for external plugins.
|
||||||
|
DefaultSocketPath = api.DefaultSocketPath
|
||||||
|
)
|
||||||
|
|
||||||
|
// SyncFn is a container runtime function for state synchronization.
|
||||||
|
type SyncFn func(context.Context, SyncCB) error
|
||||||
|
|
||||||
|
// SyncCB is an NRI function used to synchronize plugins with the runtime.
|
||||||
|
type SyncCB func(context.Context, []*PodSandbox, []*Container) ([]*ContainerUpdate, error)
|
||||||
|
|
||||||
|
// UpdateFn is a container runtime function for unsolicited container updates.
|
||||||
|
type UpdateFn func(context.Context, []*ContainerUpdate) ([]*ContainerUpdate, error)
|
||||||
|
|
||||||
|
// Adaptation is the NRI abstraction for container runtime NRI adaptation/integration.
|
||||||
|
type Adaptation struct {
|
||||||
|
sync.Mutex
|
||||||
|
name string
|
||||||
|
version string
|
||||||
|
configPath string
|
||||||
|
pluginPath string
|
||||||
|
socketPath string
|
||||||
|
syncFn SyncFn
|
||||||
|
updateFn UpdateFn
|
||||||
|
cfg *Config
|
||||||
|
listener net.Listener
|
||||||
|
plugins []*plugin
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Used instead of nil Context in logging.
|
||||||
|
noCtx = context.TODO()
|
||||||
|
)
|
||||||
|
|
||||||
|
// Option to apply to the NRI runtime.
|
||||||
|
type Option func(*Adaptation) error
|
||||||
|
|
||||||
|
// WithConfigPath returns an option to override the default NRI config path.
|
||||||
|
func WithConfigPath(path string) Option {
|
||||||
|
return func(r *Adaptation) error {
|
||||||
|
r.configPath = path
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithConfig returns an option to provide a pre-parsed NRI configuration.
|
||||||
|
func WithConfig(cfg *Config) Option {
|
||||||
|
return func(r *Adaptation) error {
|
||||||
|
r.cfg = cfg
|
||||||
|
r.configPath = cfg.path
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithPluginPath returns an option to override the default NRI plugin path.
|
||||||
|
func WithPluginPath(path string) Option {
|
||||||
|
return func(r *Adaptation) error {
|
||||||
|
r.pluginPath = path
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSocketPath returns an option to override the default NRI socket path.
|
||||||
|
func WithSocketPath(path string) Option {
|
||||||
|
return func(r *Adaptation) error {
|
||||||
|
r.socketPath = path
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new NRI Runtime.
|
||||||
|
func New(name, version string, syncFn SyncFn, updateFn UpdateFn, opts ...Option) (*Adaptation, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
r := &Adaptation{
|
||||||
|
name: name,
|
||||||
|
version: version,
|
||||||
|
syncFn: syncFn,
|
||||||
|
updateFn: updateFn,
|
||||||
|
configPath: DefaultConfigPath,
|
||||||
|
pluginPath: DefaultPluginPath,
|
||||||
|
socketPath: DefaultSocketPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o := range opts {
|
||||||
|
if err = o(r); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to apply option: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.cfg == nil {
|
||||||
|
if r.cfg, err = ReadConfig(r.configPath); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof(noCtx, "runtime interface created")
|
||||||
|
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start up the NRI runtime.
|
||||||
|
func (r *Adaptation) Start() error {
|
||||||
|
log.Infof(noCtx, "runtime interface starting up...")
|
||||||
|
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
|
||||||
|
if err := r.startPlugins(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.startListener(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the NRI runtime.
|
||||||
|
func (r *Adaptation) Stop() {
|
||||||
|
log.Infof(noCtx, "runtime interface shutting down...")
|
||||||
|
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
|
||||||
|
r.stopListener()
|
||||||
|
r.stopPlugins()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunPodSandbox relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) RunPodSandbox(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_RUN_POD_SANDBOX
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopPodSandbox relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) StopPodSandbox(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_STOP_POD_SANDBOX
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemovePodSandbox relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) RemovePodSandbox(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_REMOVE_POD_SANDBOX
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateContainer relays the corresponding CRI request to plugins.
|
||||||
|
func (r *Adaptation) CreateContainer(ctx context.Context, req *CreateContainerRequest) (*CreateContainerResponse, error) {
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
defer r.removeClosedPlugins()
|
||||||
|
|
||||||
|
result := collectCreateContainerResult(req)
|
||||||
|
for _, plugin := range r.plugins {
|
||||||
|
rpl, err := plugin.createContainer(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = result.apply(rpl, plugin.name())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.createContainerResponse(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostCreateContainer relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) PostCreateContainer(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_POST_CREATE_CONTAINER
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartContainer relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) StartContainer(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_START_CONTAINER
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostStartContainer relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) PostStartContainer(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_POST_START_CONTAINER
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateContainer relays the corresponding CRI request to plugins.
|
||||||
|
func (r *Adaptation) UpdateContainer(ctx context.Context, req *UpdateContainerRequest) (*UpdateContainerResponse, error) {
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
defer r.removeClosedPlugins()
|
||||||
|
|
||||||
|
result := collectUpdateContainerResult(req)
|
||||||
|
for _, plugin := range r.plugins {
|
||||||
|
rpl, err := plugin.updateContainer(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = result.apply(rpl, plugin.name())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.updateContainerResponse(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostUpdateContainer relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) PostUpdateContainer(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_POST_UPDATE_CONTAINER
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopContainer relays the corresponding CRI request to plugins.
|
||||||
|
func (r *Adaptation) StopContainer(ctx context.Context, req *StopContainerRequest) (*StopContainerResponse, error) {
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
defer r.removeClosedPlugins()
|
||||||
|
|
||||||
|
result := collectStopContainerResult()
|
||||||
|
for _, plugin := range r.plugins {
|
||||||
|
rpl, err := plugin.stopContainer(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = result.apply(rpl, plugin.name())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.stopContainerResponse(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveContainer relays the corresponding CRI event to plugins.
|
||||||
|
func (r *Adaptation) RemoveContainer(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
evt.Event = Event_REMOVE_CONTAINER
|
||||||
|
return r.StateChange(ctx, evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StateChange relays pod- or container events to plugins.
|
||||||
|
func (r *Adaptation) StateChange(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
if evt.Event == Event_UNKNOWN {
|
||||||
|
return errors.New("invalid (unset) event in state change notification")
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
defer r.removeClosedPlugins()
|
||||||
|
|
||||||
|
for _, plugin := range r.plugins {
|
||||||
|
err := plugin.StateChange(ctx, evt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform a set of unsolicited container updates requested by a plugin.
|
||||||
|
func (r *Adaptation) updateContainers(ctx context.Context, req []*ContainerUpdate) ([]*ContainerUpdate, error) {
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
|
||||||
|
return r.updateFn(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start up pre-installed plugins.
|
||||||
|
func (r *Adaptation) startPlugins() (retErr error) {
|
||||||
|
var plugins []*plugin
|
||||||
|
|
||||||
|
log.Infof(noCtx, "starting plugins...")
|
||||||
|
|
||||||
|
ids, names, configs, err := r.discoverPlugins()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
for _, p := range plugins {
|
||||||
|
p.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for i, name := range names {
|
||||||
|
log.Infof(noCtx, "starting plugin %q...", name)
|
||||||
|
|
||||||
|
id := ids[i]
|
||||||
|
|
||||||
|
p, err := newLaunchedPlugin(r.pluginPath, id, name, configs[i])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to start NRI plugin %q: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := p.start(r.name, r.version); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins = append(plugins, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.plugins = plugins
|
||||||
|
r.sortPlugins()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop plugins.
|
||||||
|
func (r *Adaptation) stopPlugins() {
|
||||||
|
log.Infof(noCtx, "stopping plugins...")
|
||||||
|
|
||||||
|
for _, p := range r.plugins {
|
||||||
|
p.stop()
|
||||||
|
}
|
||||||
|
r.plugins = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Adaptation) removeClosedPlugins() {
|
||||||
|
active := []*plugin{}
|
||||||
|
for _, p := range r.plugins {
|
||||||
|
if !p.isClosed() {
|
||||||
|
active = append(active, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.plugins = active
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Adaptation) startListener() error {
|
||||||
|
if r.cfg.DisableConnections {
|
||||||
|
log.Infof(noCtx, "connection from external plugins disabled")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Remove(r.socketPath)
|
||||||
|
if err := os.MkdirAll(filepath.Dir(r.socketPath), 0755); err != nil {
|
||||||
|
return fmt.Errorf("failed to create socket %q: %w", r.socketPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := net.ListenUnix("unix", &net.UnixAddr{
|
||||||
|
Name: r.socketPath,
|
||||||
|
Net: "unix",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create socket %q: %w", r.socketPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.acceptPluginConnections(l)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Adaptation) stopListener() {
|
||||||
|
if r.listener != nil {
|
||||||
|
r.listener.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Adaptation) acceptPluginConnections(l net.Listener) error {
|
||||||
|
r.listener = l
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
conn, err := l.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.Infof(ctx, "stopped accepting plugin connections (%v)", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p, err := newExternalPlugin(conn)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf(ctx, "failed to create external plugin: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := p.start(r.name, r.version); err != nil {
|
||||||
|
log.Errorf(ctx, "failed to start external plugin: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Lock()
|
||||||
|
|
||||||
|
err = r.syncFn(ctx, p.synchronize)
|
||||||
|
if err != nil {
|
||||||
|
log.Infof(ctx, "failed to synchronize plugin: %v", err)
|
||||||
|
} else {
|
||||||
|
r.plugins = append(r.plugins, p)
|
||||||
|
r.sortPlugins()
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Unlock()
|
||||||
|
|
||||||
|
log.Infof(ctx, "plugin %q connected", p.name())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Adaptation) discoverPlugins() ([]string, []string, []string, error) {
|
||||||
|
var (
|
||||||
|
plugins []string
|
||||||
|
indices []string
|
||||||
|
configs []string
|
||||||
|
entries []os.DirEntry
|
||||||
|
info fs.FileInfo
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if entries, err = os.ReadDir(r.pluginPath); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil, nil, nil, nil
|
||||||
|
}
|
||||||
|
return nil, nil, nil, fmt.Errorf("failed to discover plugins in %s: %w",
|
||||||
|
r.pluginPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, e := range entries {
|
||||||
|
if e.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if info, err = e.Info(); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if info.Mode()&fs.FileMode(0o111) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
name := e.Name()
|
||||||
|
idx, base, err := api.ParsePluginName(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, fmt.Errorf("failed to discover plugins in %s: %w",
|
||||||
|
r.pluginPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, err := r.cfg.getPluginConfig(idx, base)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, fmt.Errorf("failed to discover plugins in %s: %w",
|
||||||
|
r.pluginPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof(noCtx, "discovered plugin %s", name)
|
||||||
|
|
||||||
|
indices = append(indices, idx)
|
||||||
|
plugins = append(plugins, base)
|
||||||
|
configs = append(configs, cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return indices, plugins, configs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Adaptation) sortPlugins() {
|
||||||
|
r.removeClosedPlugins()
|
||||||
|
sort.Slice(r.plugins, func(i, j int) bool {
|
||||||
|
return r.plugins[i].idx < r.plugins[j].idx
|
||||||
|
})
|
||||||
|
if len(r.plugins) > 0 {
|
||||||
|
log.Infof(noCtx, "plugin invocation order")
|
||||||
|
for i, p := range r.plugins {
|
||||||
|
log.Infof(noCtx, " #%d: %q (%s)", i+1, p.name(), p.qualifiedName())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
151
vendor/github.com/containerd/nri/pkg/adaptation/api.go
generated
vendored
Normal file
151
vendor/github.com/containerd/nri/pkg/adaptation/api.go
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package adaptation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containerd/nri/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Alias types, consts and functions from api for the runtime.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Aliased request/response/event types for api/api.proto.
|
||||||
|
// nolint
|
||||||
|
type (
|
||||||
|
RegisterPluginRequest = api.RegisterPluginRequest
|
||||||
|
RegisterPluginResponse = api.Empty
|
||||||
|
UpdateContainersRequest = api.UpdateContainersRequest
|
||||||
|
UpdateContainersResponse = api.UpdateContainersResponse
|
||||||
|
|
||||||
|
ConfigureRequest = api.ConfigureRequest
|
||||||
|
ConfigureResponse = api.ConfigureResponse
|
||||||
|
SynchronizeRequest = api.SynchronizeRequest
|
||||||
|
SynchronizeResponse = api.SynchronizeResponse
|
||||||
|
|
||||||
|
CreateContainerRequest = api.CreateContainerRequest
|
||||||
|
CreateContainerResponse = api.CreateContainerResponse
|
||||||
|
UpdateContainerRequest = api.UpdateContainerRequest
|
||||||
|
UpdateContainerResponse = api.UpdateContainerResponse
|
||||||
|
StopContainerRequest = api.StopContainerRequest
|
||||||
|
StopContainerResponse = api.StopContainerResponse
|
||||||
|
|
||||||
|
StateChangeEvent = api.StateChangeEvent
|
||||||
|
StateChangeResponse = api.StateChangeResponse
|
||||||
|
RunPodSandboxRequest = api.RunPodSandboxRequest
|
||||||
|
StopPodSandboxRequest = api.StopPodSandboxRequest
|
||||||
|
RemovePodSandboxRequest = api.RemovePodSandboxRequest
|
||||||
|
StartContainerRequest = api.StartContainerRequest
|
||||||
|
StartContainerResponse = api.StartContainerResponse
|
||||||
|
RemoveContainerRequest = api.RemoveContainerRequest
|
||||||
|
RemoveContainerResponse = api.RemoveContainerResponse
|
||||||
|
PostCreateContainerRequest = api.PostCreateContainerRequest
|
||||||
|
PostCreateContainerResponse = api.PostCreateContainerResponse
|
||||||
|
PostStartContainerRequest = api.PostStartContainerRequest
|
||||||
|
PostStartContainerResponse = api.PostStartContainerResponse
|
||||||
|
PostUpdateContainerRequest = api.PostUpdateContainerRequest
|
||||||
|
PostUpdateContainerResponse = api.PostUpdateContainerResponse
|
||||||
|
|
||||||
|
PodSandbox = api.PodSandbox
|
||||||
|
LinuxPodSandbox = api.LinuxPodSandbox
|
||||||
|
Container = api.Container
|
||||||
|
ContainerAdjustment = api.ContainerAdjustment
|
||||||
|
LinuxContainerAdjustment = api.LinuxContainerAdjustment
|
||||||
|
ContainerUpdate = api.ContainerUpdate
|
||||||
|
LinuxContainerUpdate = api.LinuxContainerUpdate
|
||||||
|
ContainerEviction = api.ContainerEviction
|
||||||
|
ContainerState = api.ContainerState
|
||||||
|
KeyValue = api.KeyValue
|
||||||
|
Mount = api.Mount
|
||||||
|
LinuxContainer = api.LinuxContainer
|
||||||
|
LinuxNamespace = api.LinuxNamespace
|
||||||
|
LinuxResources = api.LinuxResources
|
||||||
|
LinuxCPU = api.LinuxCPU
|
||||||
|
LinuxMemory = api.LinuxMemory
|
||||||
|
LinuxDevice = api.LinuxDevice
|
||||||
|
LinuxDeviceCgroup = api.LinuxDeviceCgroup
|
||||||
|
HugepageLimit = api.HugepageLimit
|
||||||
|
Hooks = api.Hooks
|
||||||
|
Hook = api.Hook
|
||||||
|
|
||||||
|
EventMask = api.EventMask
|
||||||
|
)
|
||||||
|
|
||||||
|
// Aliased consts for api/api.proto.
|
||||||
|
// nolint
|
||||||
|
const (
|
||||||
|
Event_UNKNOWN = api.Event_UNKNOWN
|
||||||
|
Event_RUN_POD_SANDBOX = api.Event_RUN_POD_SANDBOX
|
||||||
|
Event_STOP_POD_SANDBOX = api.Event_STOP_POD_SANDBOX
|
||||||
|
Event_REMOVE_POD_SANDBOX = api.Event_REMOVE_POD_SANDBOX
|
||||||
|
Event_CREATE_CONTAINER = api.Event_CREATE_CONTAINER
|
||||||
|
Event_POST_CREATE_CONTAINER = api.Event_POST_CREATE_CONTAINER
|
||||||
|
Event_START_CONTAINER = api.Event_START_CONTAINER
|
||||||
|
Event_POST_START_CONTAINER = api.Event_POST_START_CONTAINER
|
||||||
|
Event_UPDATE_CONTAINER = api.Event_UPDATE_CONTAINER
|
||||||
|
Event_POST_UPDATE_CONTAINER = api.Event_POST_UPDATE_CONTAINER
|
||||||
|
Event_STOP_CONTAINER = api.Event_STOP_CONTAINER
|
||||||
|
Event_REMOVE_CONTAINER = api.Event_REMOVE_CONTAINER
|
||||||
|
ValidEvents = api.ValidEvents
|
||||||
|
|
||||||
|
ContainerState_CONTAINER_UNKNOWN = api.ContainerState_CONTAINER_UNKNOWN
|
||||||
|
ContainerState_CONTAINER_CREATED = api.ContainerState_CONTAINER_CREATED
|
||||||
|
ContainerState_CONTAINER_PAUSED = api.ContainerState_CONTAINER_PAUSED
|
||||||
|
ContainerState_CONTAINER_RUNNING = api.ContainerState_CONTAINER_RUNNING
|
||||||
|
ContainerState_CONTAINER_STOPPED = api.ContainerState_CONTAINER_STOPPED
|
||||||
|
ContainerState_CONTAINER_EXITED = api.ContainerState_CONTAINER_STOPPED
|
||||||
|
)
|
||||||
|
|
||||||
|
// Aliased types for api/optional.go.
|
||||||
|
// nolint
|
||||||
|
type (
|
||||||
|
OptionalString = api.OptionalString
|
||||||
|
OptionalInt = api.OptionalInt
|
||||||
|
OptionalInt32 = api.OptionalInt32
|
||||||
|
OptionalUInt32 = api.OptionalUInt32
|
||||||
|
OptionalInt64 = api.OptionalInt64
|
||||||
|
OptionalUInt64 = api.OptionalUInt64
|
||||||
|
OptionalBool = api.OptionalBool
|
||||||
|
OptionalFileMode = api.OptionalFileMode
|
||||||
|
)
|
||||||
|
|
||||||
|
// Aliased functions for api/optional.go.
|
||||||
|
// nolint
|
||||||
|
var (
|
||||||
|
String = api.String
|
||||||
|
Int = api.Int
|
||||||
|
Int32 = api.Int32
|
||||||
|
UInt32 = api.UInt32
|
||||||
|
Int64 = api.Int64
|
||||||
|
UInt64 = api.UInt64
|
||||||
|
Bool = api.Bool
|
||||||
|
FileMode = api.FileMode
|
||||||
|
)
|
||||||
|
|
||||||
|
// Aliased functions for api/types.go.
|
||||||
|
// nolint
|
||||||
|
var (
|
||||||
|
FromOCIMounts = api.FromOCIMounts
|
||||||
|
FromOCIHooks = api.FromOCIHooks
|
||||||
|
FromOCILinuxNamespaces = api.FromOCILinuxNamespaces
|
||||||
|
FromOCILinuxDevices = api.FromOCILinuxDevices
|
||||||
|
FromOCILinuxResources = api.FromOCILinuxResources
|
||||||
|
DupStringSlice = api.DupStringSlice
|
||||||
|
DupStringMap = api.DupStringMap
|
||||||
|
IsMarkedForRemoval = api.IsMarkedForRemoval
|
||||||
|
MarkForRemoval = api.MarkForRemoval
|
||||||
|
)
|
95
vendor/github.com/containerd/nri/pkg/adaptation/config.go
generated
vendored
Normal file
95
vendor/github.com/containerd/nri/pkg/adaptation/config.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package adaptation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"sigs.k8s.io/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// PluginConfigSubdir is the drop-in directory for plugin configuration.
|
||||||
|
PluginConfigSubdir = "conf.d"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config is the runtime configuration for NRI.
|
||||||
|
type Config struct {
|
||||||
|
// DisableConnections disables plugin-initiated connections.
|
||||||
|
DisableConnections bool `json:"disableConnections"`
|
||||||
|
|
||||||
|
path string
|
||||||
|
dropIn string
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultConfig returns the default NRI configuration for a given path.
|
||||||
|
// This configuration should be identical to what ReadConfig would return
|
||||||
|
// for an empty file at the given location. If the given path is empty,
|
||||||
|
// DefaultConfigPath is used instead.
|
||||||
|
func DefaultConfig(path string) *Config {
|
||||||
|
if path == "" {
|
||||||
|
path = DefaultConfigPath
|
||||||
|
}
|
||||||
|
return &Config{
|
||||||
|
path: path,
|
||||||
|
dropIn: filepath.Join(filepath.Dir(path), PluginConfigSubdir),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadConfig reads the NRI runtime configuration from a file.
|
||||||
|
func ReadConfig(path string) (*Config, error) {
|
||||||
|
buf, err := os.ReadFile(path)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read file %q: %w", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := &Config{}
|
||||||
|
err = yaml.UnmarshalStrict(buf, cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse file %q: %w", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.path = path
|
||||||
|
cfg.dropIn = filepath.Join(filepath.Dir(path), PluginConfigSubdir)
|
||||||
|
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cfg *Config) getPluginConfig(id, base string) (string, error) {
|
||||||
|
name := id + "-" + base
|
||||||
|
dropIns := []string{
|
||||||
|
filepath.Join(cfg.dropIn, name+".conf"),
|
||||||
|
filepath.Join(cfg.dropIn, base+".conf"),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, path := range dropIns {
|
||||||
|
buf, err := os.ReadFile(path)
|
||||||
|
if err == nil {
|
||||||
|
return string(buf), nil
|
||||||
|
}
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return "", fmt.Errorf("failed to read configuration for plugin %q: %w", name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
}
|
468
vendor/github.com/containerd/nri/pkg/adaptation/plugin.go
generated
vendored
Normal file
468
vendor/github.com/containerd/nri/pkg/adaptation/plugin.go
generated
vendored
Normal file
@ -0,0 +1,468 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package adaptation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
stdnet "net"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/nri/pkg/api"
|
||||||
|
"github.com/containerd/nri/pkg/log"
|
||||||
|
"github.com/containerd/nri/pkg/net"
|
||||||
|
"github.com/containerd/nri/pkg/net/multiplex"
|
||||||
|
"github.com/containerd/ttrpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
pluginRegistrationTimeout = 2 * time.Second
|
||||||
|
pluginRequestTimeout = 2 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
|
type plugin struct {
|
||||||
|
sync.Mutex
|
||||||
|
idx string
|
||||||
|
base string
|
||||||
|
cfg string
|
||||||
|
pid int
|
||||||
|
cmd *exec.Cmd
|
||||||
|
mux multiplex.Mux
|
||||||
|
rpcc *ttrpc.Client
|
||||||
|
rpcl stdnet.Listener
|
||||||
|
rpcs *ttrpc.Server
|
||||||
|
events EventMask
|
||||||
|
closed bool
|
||||||
|
stub api.PluginService
|
||||||
|
regC chan error
|
||||||
|
closeC chan struct{}
|
||||||
|
r *Adaptation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Launch a pre-installed plugin with a pre-connected socketpair.
|
||||||
|
func newLaunchedPlugin(dir, idx, base, cfg string) (p *plugin, retErr error) {
|
||||||
|
name := idx + "-" + base
|
||||||
|
|
||||||
|
sockets, err := net.NewSocketPair()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create plugin connection for plugin %q: %w", name, err)
|
||||||
|
}
|
||||||
|
defer sockets.Close()
|
||||||
|
|
||||||
|
conn, err := sockets.LocalConn()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to set up local connection for plugin %q: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
peerFile := sockets.PeerFile()
|
||||||
|
defer func() {
|
||||||
|
peerFile.Close()
|
||||||
|
if retErr != nil {
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
cmd := exec.Command(filepath.Join(dir, name))
|
||||||
|
cmd.ExtraFiles = []*os.File{peerFile}
|
||||||
|
cmd.Env = []string{
|
||||||
|
api.PluginNameEnvVar + "=" + name,
|
||||||
|
api.PluginIdxEnvVar + "=" + idx,
|
||||||
|
api.PluginSocketEnvVar + "=3",
|
||||||
|
}
|
||||||
|
|
||||||
|
p = &plugin{
|
||||||
|
cfg: cfg,
|
||||||
|
cmd: cmd,
|
||||||
|
idx: idx,
|
||||||
|
base: base,
|
||||||
|
regC: make(chan error, 1),
|
||||||
|
closeC: make(chan struct{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = p.cmd.Start(); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed launch plugin %q: %w", p.name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = p.connect(conn); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a plugin (stub) for an accepted external plugin connection.
|
||||||
|
func newExternalPlugin(conn stdnet.Conn) (p *plugin, retErr error) {
|
||||||
|
p = &plugin{
|
||||||
|
regC: make(chan error, 1),
|
||||||
|
closeC: make(chan struct{}),
|
||||||
|
}
|
||||||
|
if err := p.connect(conn); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the plugin is external (was not launched by us).
|
||||||
|
func (p *plugin) isExternal() bool {
|
||||||
|
return p.cmd == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'connect' a plugin, setting up multiplexing on its socket.
|
||||||
|
func (p *plugin) connect(conn stdnet.Conn) (retErr error) {
|
||||||
|
mux := multiplex.Multiplex(conn, multiplex.WithBlockedRead())
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
mux.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
pconn, err := mux.Open(multiplex.PluginServiceConn)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to mux plugin connection for plugin %q: %w", p.name(), err)
|
||||||
|
}
|
||||||
|
rpcc := ttrpc.NewClient(pconn, ttrpc.WithOnClose(
|
||||||
|
func() {
|
||||||
|
log.Infof(noCtx, "connection to plugin %q closed", p.name())
|
||||||
|
close(p.closeC)
|
||||||
|
p.close()
|
||||||
|
}))
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
rpcc.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
stub := api.NewPluginClient(rpcc)
|
||||||
|
|
||||||
|
rpcs, err := ttrpc.NewServer()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create ttrpc server for plugin %q: %w", p.name(), err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
rpcs.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
rpcl, err := mux.Listen(multiplex.RuntimeServiceConn)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create mux runtime listener for plugin %q: %w", p.name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.mux = mux
|
||||||
|
p.rpcc = rpcc
|
||||||
|
p.rpcl = rpcl
|
||||||
|
p.rpcs = rpcs
|
||||||
|
p.stub = stub
|
||||||
|
|
||||||
|
p.pid, err = getPeerPid(p.mux.Trunk())
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf(noCtx, "failed to determine plugin pid pid: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
api.RegisterRuntimeService(p.rpcs, p)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start Runtime service, wait for plugin to register, then configure it.
|
||||||
|
func (p *plugin) start(name, version string) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err := p.rpcs.Serve(context.Background(), p.rpcl)
|
||||||
|
if err != ttrpc.ErrServerClosed {
|
||||||
|
log.Infof(noCtx, "ttrpc server for plugin %q closed (%v)", p.name(), err)
|
||||||
|
}
|
||||||
|
p.close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
p.mux.Unblock()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case err = <-p.regC:
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to register plugin: %w", err)
|
||||||
|
}
|
||||||
|
case <-p.closeC:
|
||||||
|
return fmt.Errorf("failed to register plugin, connection closed: %w", err)
|
||||||
|
case <-time.After(pluginRegistrationTimeout):
|
||||||
|
p.close()
|
||||||
|
p.stop()
|
||||||
|
return errors.New("plugin registration timed out")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = p.configure(context.Background(), name, version, p.cfg)
|
||||||
|
if err != nil {
|
||||||
|
p.close()
|
||||||
|
p.stop()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// close a plugin shutting down its multiplexed ttrpc connections.
|
||||||
|
func (p *plugin) close() {
|
||||||
|
p.Lock()
|
||||||
|
defer p.Unlock()
|
||||||
|
if p.closed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p.closed = true
|
||||||
|
p.mux.Close()
|
||||||
|
p.rpcc.Close()
|
||||||
|
p.rpcs.Close()
|
||||||
|
p.rpcl.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *plugin) isClosed() bool {
|
||||||
|
p.Lock()
|
||||||
|
defer p.Unlock()
|
||||||
|
return p.closed
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop a plugin (if it was launched by us)
|
||||||
|
func (p *plugin) stop() error {
|
||||||
|
if p.isExternal() || p.cmd.Process == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(klihub):
|
||||||
|
// We should attempt a graceful shutdown of the process here...
|
||||||
|
// - send it SIGINT
|
||||||
|
// - give the it some slack waiting with a timeout
|
||||||
|
// - butcher it with SIGKILL after the timeout
|
||||||
|
|
||||||
|
p.cmd.Process.Kill()
|
||||||
|
p.cmd.Process.Wait()
|
||||||
|
p.cmd.Process.Release()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns a string indentication for the plugin.
|
||||||
|
func (p *plugin) name() string {
|
||||||
|
return p.idx + "-" + p.base
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *plugin) qualifiedName() string {
|
||||||
|
var kind, idx, base string
|
||||||
|
if p.isExternal() {
|
||||||
|
kind = "external"
|
||||||
|
} else {
|
||||||
|
kind = "pre-connected"
|
||||||
|
}
|
||||||
|
if idx = p.idx; idx == "" {
|
||||||
|
idx = "??"
|
||||||
|
}
|
||||||
|
if base = p.base; base == "" {
|
||||||
|
base = "plugin"
|
||||||
|
}
|
||||||
|
return kind + ":" + idx + "-" + base + "[" + strconv.Itoa(p.pid) + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterPlugin handles the plugin's registration request.
|
||||||
|
func (p *plugin) RegisterPlugin(ctx context.Context, req *RegisterPluginRequest) (*RegisterPluginResponse, error) {
|
||||||
|
if p.isExternal() {
|
||||||
|
if req.PluginName == "" {
|
||||||
|
p.regC <- fmt.Errorf("plugin %q registered empty name", p.qualifiedName())
|
||||||
|
return &RegisterPluginResponse{}, errors.New("invalid (empty) plugin name")
|
||||||
|
}
|
||||||
|
if err := api.CheckPluginIndex(req.PluginIdx); err != nil {
|
||||||
|
p.regC <- fmt.Errorf("plugin %q registered invalid index: %w", req.PluginName, err)
|
||||||
|
return &RegisterPluginResponse{}, fmt.Errorf("invalid plugin index: %w", err)
|
||||||
|
}
|
||||||
|
p.base = req.PluginName
|
||||||
|
p.idx = req.PluginIdx
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof(ctx, "plugin %q registered as %q", p.qualifiedName(), p.name())
|
||||||
|
|
||||||
|
p.regC <- nil
|
||||||
|
return &RegisterPluginResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateContainers relays container update request to the runtime.
|
||||||
|
func (p *plugin) UpdateContainers(ctx context.Context, req *UpdateContainersRequest) (*UpdateContainersResponse, error) {
|
||||||
|
log.Infof(ctx, "plugin %q requested container updates", p.name())
|
||||||
|
|
||||||
|
failed, err := p.r.updateContainers(ctx, req.Update)
|
||||||
|
return &UpdateContainersResponse{
|
||||||
|
Failed: failed,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure the plugin and subscribe it for the events it requested.
|
||||||
|
func (p *plugin) configure(ctx context.Context, name, version, config string) error {
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
rpl, err := p.stub.Configure(ctx, &ConfigureRequest{
|
||||||
|
Config: config,
|
||||||
|
RuntimeName: name,
|
||||||
|
RuntimeVersion: version,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to configure plugin: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
events := EventMask(rpl.Events)
|
||||||
|
if events != 0 {
|
||||||
|
if extra := events &^ ValidEvents; extra != 0 {
|
||||||
|
return fmt.Errorf("invalid plugin events: 0x%x", extra)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
events = ValidEvents
|
||||||
|
}
|
||||||
|
p.events = events
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// synchronize the plugin with the current state of the runtime.
|
||||||
|
func (p *plugin) synchronize(ctx context.Context, pods []*PodSandbox, containers []*Container) ([]*ContainerUpdate, error) {
|
||||||
|
log.Infof(ctx, "synchronizing plugin %s", p.name())
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
req := &SynchronizeRequest{
|
||||||
|
Pods: pods,
|
||||||
|
Containers: containers,
|
||||||
|
}
|
||||||
|
rpl, err := p.stub.Synchronize(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rpl.Update, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relay CreateContainer request to plugin.
|
||||||
|
func (p *plugin) createContainer(ctx context.Context, req *CreateContainerRequest) (*CreateContainerResponse, error) {
|
||||||
|
if !p.events.IsSet(Event_CREATE_CONTAINER) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
rpl, err := p.stub.CreateContainer(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
if isFatalError(err) {
|
||||||
|
log.Errorf(ctx, "closing plugin %s, failed to handle CreateContainer request: %w",
|
||||||
|
p.name(), err)
|
||||||
|
p.close()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rpl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relay UpdateContainer request to plugin.
|
||||||
|
func (p *plugin) updateContainer(ctx context.Context, req *UpdateContainerRequest) (*UpdateContainerResponse, error) {
|
||||||
|
if !p.events.IsSet(Event_UPDATE_CONTAINER) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
rpl, err := p.stub.UpdateContainer(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
if isFatalError(err) {
|
||||||
|
log.Errorf(ctx, "closing plugin %s, failed to handle UpdateContainer request: %w",
|
||||||
|
p.name(), err)
|
||||||
|
p.close()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rpl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relay StopContainer request to the plugin.
|
||||||
|
func (p *plugin) stopContainer(ctx context.Context, req *StopContainerRequest) (*StopContainerResponse, error) {
|
||||||
|
if !p.events.IsSet(Event_STOP_CONTAINER) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
rpl, err := p.stub.StopContainer(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
if isFatalError(err) {
|
||||||
|
log.Errorf(ctx, "closing plugin %s, failed to handle StopContainer request: %w",
|
||||||
|
p.name(), err)
|
||||||
|
p.close()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rpl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relay other pod or container state change events to the plugin.
|
||||||
|
func (p *plugin) StateChange(ctx context.Context, evt *StateChangeEvent) error {
|
||||||
|
if !p.events.IsSet(evt.Event) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, pluginRequestTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
_, err := p.stub.StateChange(ctx, evt)
|
||||||
|
if err != nil {
|
||||||
|
if isFatalError(err) {
|
||||||
|
log.Errorf(ctx, "closing plugin %s, failed to handle event %d: %w",
|
||||||
|
p.name(), evt.Event, err)
|
||||||
|
p.close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// isFatalError returns true if the error is fatal and the plugin connection shoudld be closed.
|
||||||
|
func isFatalError(err error) bool {
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, ttrpc.ErrClosed):
|
||||||
|
return true
|
||||||
|
case errors.Is(err, ttrpc.ErrServerClosed):
|
||||||
|
return true
|
||||||
|
case errors.Is(err, ttrpc.ErrProtocol):
|
||||||
|
return true
|
||||||
|
case errors.Is(err, context.DeadlineExceeded):
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
55
vendor/github.com/containerd/nri/pkg/adaptation/plugin_linux.go
generated
vendored
Normal file
55
vendor/github.com/containerd/nri/pkg/adaptation/plugin_linux.go
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package adaptation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
stdnet "net"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// getPeerPid returns the process id at the other end of the connection.
|
||||||
|
func getPeerPid(conn stdnet.Conn) (int, error) {
|
||||||
|
var cred *unix.Ucred
|
||||||
|
|
||||||
|
uc, ok := conn.(*stdnet.UnixConn)
|
||||||
|
if !ok {
|
||||||
|
return 0, errors.New("invalid connection, not *net.UnixConn")
|
||||||
|
}
|
||||||
|
|
||||||
|
raw, err := uc.SyscallConn()
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("failed get raw unix domain connection: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrlErr := raw.Control(func(fd uintptr) {
|
||||||
|
cred, err = unix.GetsockoptUcred(int(fd), unix.SOL_SOCKET, unix.SO_PEERCRED)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("failed to get process credentials: %w", err)
|
||||||
|
}
|
||||||
|
if ctrlErr != nil {
|
||||||
|
return 0, fmt.Errorf("uc.SyscallConn().Control() failed: %w", ctrlErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(cred.Pid), nil
|
||||||
|
}
|
31
vendor/github.com/containerd/nri/pkg/adaptation/plugin_other.go
generated
vendored
Normal file
31
vendor/github.com/containerd/nri/pkg/adaptation/plugin_other.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
//go:build !linux
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package adaptation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// getPeerPid returns the process id at the other end of the connection.
|
||||||
|
func getPeerPid(conn net.Conn) (int, error) {
|
||||||
|
return 0, fmt.Errorf("getPeerPid() unimplemented on %s", runtime.GOOS)
|
||||||
|
}
|
1245
vendor/github.com/containerd/nri/pkg/adaptation/result.go
generated
vendored
Normal file
1245
vendor/github.com/containerd/nri/pkg/adaptation/result.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
295
vendor/github.com/containerd/nri/pkg/api/adjustment.go
generated
vendored
Normal file
295
vendor/github.com/containerd/nri/pkg/api/adjustment.go
generated
vendored
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// Adjustment of metadata that is stored in maps (labels and annotations)
|
||||||
|
// currently assumes that a single plugin will never do an add prior to a
|
||||||
|
// delete for any key. IOW, it is always assumed that if both a deletion
|
||||||
|
// and an addition/setting was recorded for a key then the final desired
|
||||||
|
// state is the addition. This seems like a reasonably safe assumption. A
|
||||||
|
// removal is usually done only to protect against triggering the conflict
|
||||||
|
// in the runtime when a plugin intends to touch a key which is known to
|
||||||
|
// have been put there or already modified by another plugin.
|
||||||
|
//
|
||||||
|
// An alternative without this implicit ordering assumption would be to
|
||||||
|
// store the adjustment for such data as a sequence of add/del operations
|
||||||
|
// in a slice. At the moment that does not seem to be necessary.
|
||||||
|
//
|
||||||
|
|
||||||
|
// AddAnnotation records the addition of the annotation key=value.
|
||||||
|
func (a *ContainerAdjustment) AddAnnotation(key, value string) {
|
||||||
|
a.initAnnotations()
|
||||||
|
a.Annotations[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAnnotation records the removal of the annotation for the given key.
|
||||||
|
// Normally it is an error for a plugin to try and alter an annotation
|
||||||
|
// touched by another plugin. However, this is not an error if the plugin
|
||||||
|
// removes that annotation prior to touching it.
|
||||||
|
func (a *ContainerAdjustment) RemoveAnnotation(key string) {
|
||||||
|
a.initAnnotations()
|
||||||
|
a.Annotations[MarkForRemoval(key)] = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddMount records the addition of a mount to a container.
|
||||||
|
func (a *ContainerAdjustment) AddMount(m *Mount) {
|
||||||
|
a.Mounts = append(a.Mounts, m) // TODO: should we dup m here ?
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveMount records the removal of a mount from a container.
|
||||||
|
// Normally it is an error for a plugin to try and alter a mount
|
||||||
|
// touched by another plugin. However, this is not an error if the
|
||||||
|
// plugin removes that mount prior to touching it.
|
||||||
|
func (a *ContainerAdjustment) RemoveMount(ContainerPath string) {
|
||||||
|
a.Mounts = append(a.Mounts, &Mount{
|
||||||
|
Destination: MarkForRemoval(ContainerPath),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEnv records the addition of an environment variable to a container.
|
||||||
|
func (a *ContainerAdjustment) AddEnv(key, value string) {
|
||||||
|
a.Env = append(a.Env, &KeyValue{
|
||||||
|
Key: key,
|
||||||
|
Value: value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveEnv records the removal of an environment variable from a container.
|
||||||
|
// Normally it is an error for a plugin to try and alter an environment
|
||||||
|
// variable touched by another container. However, this is not an error if
|
||||||
|
// the plugin removes that variable prior to touching it.
|
||||||
|
func (a *ContainerAdjustment) RemoveEnv(key string) {
|
||||||
|
a.Env = append(a.Env, &KeyValue{
|
||||||
|
Key: MarkForRemoval(key),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddHooks records the addition of the given hooks to a container.
|
||||||
|
func (a *ContainerAdjustment) AddHooks(h *Hooks) {
|
||||||
|
a.initHooks()
|
||||||
|
if h.Prestart != nil {
|
||||||
|
a.Hooks.Prestart = append(a.Hooks.Prestart, h.Prestart...)
|
||||||
|
}
|
||||||
|
if h.CreateRuntime != nil {
|
||||||
|
a.Hooks.CreateRuntime = append(a.Hooks.CreateRuntime, h.CreateRuntime...)
|
||||||
|
}
|
||||||
|
if h.CreateContainer != nil {
|
||||||
|
a.Hooks.CreateContainer = append(a.Hooks.CreateContainer, h.CreateContainer...)
|
||||||
|
}
|
||||||
|
if h.StartContainer != nil {
|
||||||
|
a.Hooks.StartContainer = append(a.Hooks.StartContainer, h.StartContainer...)
|
||||||
|
}
|
||||||
|
if h.Poststart != nil {
|
||||||
|
a.Hooks.Poststart = append(a.Hooks.Poststart, h.Poststart...)
|
||||||
|
}
|
||||||
|
if h.Poststop != nil {
|
||||||
|
a.Hooks.Poststop = append(a.Hooks.Poststop, h.Poststop...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddDevice records the addition of the given device to a container.
|
||||||
|
func (a *ContainerAdjustment) AddDevice(d *LinuxDevice) {
|
||||||
|
a.initLinux()
|
||||||
|
a.Linux.Devices = append(a.Linux.Devices, d) // TODO: should we dup d here ?
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveDevice records the removal of a device from a container.
|
||||||
|
// Normally it is an error for a plugin to try and alter an device
|
||||||
|
// touched by another container. However, this is not an error if
|
||||||
|
// the plugin removes that device prior to touching it.
|
||||||
|
func (a *ContainerAdjustment) RemoveDevice(path string) {
|
||||||
|
a.initLinux()
|
||||||
|
a.Linux.Devices = append(a.Linux.Devices, &LinuxDevice{
|
||||||
|
Path: MarkForRemoval(path),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryLimit records setting the memory limit for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemoryLimit(value int64) {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.Limit = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryReservation records setting the memory reservation for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemoryReservation(value int64) {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.Reservation = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemorySwap records records setting the memory swap limit for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemorySwap(value int64) {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.Swap = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryKernel records setting the memory kernel limit for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemoryKernel(value int64) {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.Kernel = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryKernelTCP records setting the memory kernel TCP limit for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemoryKernelTCP(value int64) {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.KernelTcp = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemorySwappiness records setting the memory swappiness for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemorySwappiness(value uint64) {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.Swappiness = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryDisableOomKiller records disabling the OOM killer for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemoryDisableOomKiller() {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.DisableOomKiller = Bool(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryUseHierarchy records enabling hierarchical memory accounting for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxMemoryUseHierarchy() {
|
||||||
|
a.initLinuxResourcesMemory()
|
||||||
|
a.Linux.Resources.Memory.UseHierarchy = Bool(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUShares records setting the scheduler's CPU shares for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPUShares(value uint64) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.Shares = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUQuota records setting the scheduler's CPU quota for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPUQuota(value int64) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.Quota = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUPeriod records setting the scheduler's CPU period for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPUPeriod(value int64) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.Period = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPURealtimeRuntime records setting the scheduler's realtime runtime for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPURealtimeRuntime(value int64) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.RealtimeRuntime = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPURealtimePeriod records setting the scheduler's realtime period for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPURealtimePeriod(value uint64) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.RealtimePeriod = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUSetCPUs records setting the cpuset CPUs for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPUSetCPUs(value string) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.Cpus = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUSetMems records setting the cpuset memory for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCPUSetMems(value string) {
|
||||||
|
a.initLinuxResourcesCPU()
|
||||||
|
a.Linux.Resources.Cpu.Mems = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLinuxHugepageLimit records adding a hugepage limit for a container.
|
||||||
|
func (a *ContainerAdjustment) AddLinuxHugepageLimit(pageSize string, value uint64) {
|
||||||
|
a.initLinuxResources()
|
||||||
|
a.Linux.Resources.HugepageLimits = append(a.Linux.Resources.HugepageLimits,
|
||||||
|
&HugepageLimit{
|
||||||
|
PageSize: pageSize,
|
||||||
|
Limit: value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxBlockIOClass records setting the Block I/O class for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxBlockIOClass(value string) {
|
||||||
|
a.initLinuxResources()
|
||||||
|
a.Linux.Resources.BlockioClass = String(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxRDTClass records setting the RDT class for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxRDTClass(value string) {
|
||||||
|
a.initLinuxResources()
|
||||||
|
a.Linux.Resources.RdtClass = String(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLinuxUnified sets a cgroupv2 unified resource.
|
||||||
|
func (a *ContainerAdjustment) AddLinuxUnified(key, value string) {
|
||||||
|
a.initLinuxResourcesUnified()
|
||||||
|
a.Linux.Resources.Unified[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCgroupsPath records setting the cgroups path for a container.
|
||||||
|
func (a *ContainerAdjustment) SetLinuxCgroupsPath(value string) {
|
||||||
|
a.initLinux()
|
||||||
|
a.Linux.CgroupsPath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initializing a container adjustment and container update.
|
||||||
|
//
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initAnnotations() {
|
||||||
|
if a.Annotations == nil {
|
||||||
|
a.Annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initHooks() {
|
||||||
|
if a.Hooks == nil {
|
||||||
|
a.Hooks = &Hooks{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initLinux() {
|
||||||
|
if a.Linux == nil {
|
||||||
|
a.Linux = &LinuxContainerAdjustment{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initLinuxResources() {
|
||||||
|
a.initLinux()
|
||||||
|
if a.Linux.Resources == nil {
|
||||||
|
a.Linux.Resources = &LinuxResources{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initLinuxResourcesMemory() {
|
||||||
|
a.initLinuxResources()
|
||||||
|
if a.Linux.Resources.Memory == nil {
|
||||||
|
a.Linux.Resources.Memory = &LinuxMemory{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initLinuxResourcesCPU() {
|
||||||
|
a.initLinuxResources()
|
||||||
|
if a.Linux.Resources.Cpu == nil {
|
||||||
|
a.Linux.Resources.Cpu = &LinuxCPU{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ContainerAdjustment) initLinuxResourcesUnified() {
|
||||||
|
a.initLinuxResources()
|
||||||
|
if a.Linux.Resources.Unified == nil {
|
||||||
|
a.Linux.Resources.Unified = make(map[string]string)
|
||||||
|
}
|
||||||
|
}
|
4295
vendor/github.com/containerd/nri/pkg/api/api.pb.go
generated
vendored
Normal file
4295
vendor/github.com/containerd/nri/pkg/api/api.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
441
vendor/github.com/containerd/nri/pkg/api/api.proto
generated
vendored
Normal file
441
vendor/github.com/containerd/nri/pkg/api/api.proto
generated
vendored
Normal file
@ -0,0 +1,441 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package nri.pkg.api.v1alpha1;
|
||||||
|
|
||||||
|
option go_package = "github.com/containerd/nri/pkg/api;api";
|
||||||
|
|
||||||
|
// Runtime service is the public API runtimes expose for NRI plugins.
|
||||||
|
// On this interface RPC requests are initiated by the plugin. This
|
||||||
|
// only covers plugin registration and unsolicited container updates.
|
||||||
|
// The rest of the API is defined by the Plugin service.
|
||||||
|
service Runtime {
|
||||||
|
// RegisterPlugin registers the plugin with the runtime.
|
||||||
|
rpc RegisterPlugin(RegisterPluginRequest) returns (Empty);
|
||||||
|
// UpdateContainers requests unsolicited updates to a set of containers.
|
||||||
|
rpc UpdateContainers(UpdateContainersRequest) returns (UpdateContainersResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
message RegisterPluginRequest {
|
||||||
|
// Name of the plugin to register.
|
||||||
|
string plugin_name = 1;
|
||||||
|
// Plugin invocation index. Plugins are called in ascending index order.
|
||||||
|
string plugin_idx = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateContainersRequest {
|
||||||
|
// List of containers to update.
|
||||||
|
repeated ContainerUpdate update = 1;
|
||||||
|
// List of containers to evict.
|
||||||
|
repeated ContainerEviction evict = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateContainersResponse {
|
||||||
|
// Containers that the runtime failed to udpate.
|
||||||
|
repeated ContainerUpdate failed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Plugin is the API NRI uses to interact with plugins. It is used to
|
||||||
|
// - configure a plugin and subscribe it for lifecycle events
|
||||||
|
// - synchronize the state of a plugin with that of the runtime
|
||||||
|
// - hook a plugin into the lifecycle events of its interest
|
||||||
|
//
|
||||||
|
// During configuration the plugin tells the runtime which lifecycle events
|
||||||
|
// it wishes to get hooked into. Once configured, the plugin is synchronized
|
||||||
|
// with the runtime by receiving the list of pods and containers known to
|
||||||
|
// the runtime. The plugin can request changes to any of the containers in
|
||||||
|
// response. After initial synchronization the plugin starts receiving the
|
||||||
|
// events it subscribed for as they occur in the runtime. For container
|
||||||
|
// creation, update, and stop events, the plugin can request changes, both
|
||||||
|
// to the container that triggered the event or any other existing container
|
||||||
|
// in the runtime.
|
||||||
|
//
|
||||||
|
// For a subset of the container lifecycle events, NRI defines an additional
|
||||||
|
// Post-variant of the event. These variants are defined for CreateContainer,
|
||||||
|
// StartContainer, and UpdateContainer. For creation and update, these events
|
||||||
|
// can be used by plugins to discover the full extent of changes applied to
|
||||||
|
// the container, including any changes made by other active plugins.
|
||||||
|
//
|
||||||
|
service Plugin {
|
||||||
|
// Configure the plugin and get its event subscription.
|
||||||
|
rpc Configure(ConfigureRequest) returns (ConfigureResponse);
|
||||||
|
|
||||||
|
// Synchronize the plugin with the state of the runtime.
|
||||||
|
rpc Synchronize(SynchronizeRequest) returns (SynchronizeResponse);
|
||||||
|
|
||||||
|
// Shutdown a plugin (let it know the runtime is going down).
|
||||||
|
rpc Shutdown(Empty) returns (Empty);
|
||||||
|
|
||||||
|
// CreateContainer relays the corresponding request to the plugin. In
|
||||||
|
// response, the plugin can adjust the container being created, and
|
||||||
|
// update other containers in the runtime. Container adjustment can
|
||||||
|
// alter labels, annotations, mounts, devices, environment variables,
|
||||||
|
// OCI hooks, and assigned container resources. Updates can alter
|
||||||
|
// assigned container resources.
|
||||||
|
rpc CreateContainer(CreateContainerRequest) returns (CreateContainerResponse);
|
||||||
|
|
||||||
|
// UpdateContainer relays the corresponding request to the plugin.
|
||||||
|
// The plugin can alter how the container is updated and request updates
|
||||||
|
// to additional containers in the runtime.
|
||||||
|
rpc UpdateContainer(UpdateContainerRequest) returns (UpdateContainerResponse);
|
||||||
|
|
||||||
|
// StopContainer relays the corresponding request to the plugin. The plugin
|
||||||
|
// can update any of the remaining containers in the runtime in response.
|
||||||
|
rpc StopContainer(StopContainerRequest) returns (StopContainerResponse);
|
||||||
|
|
||||||
|
// StateChange relays any remaining pod or container lifecycle/state change
|
||||||
|
// events the plugin has subscribed for. These can be used to trigger any
|
||||||
|
// plugin-specific processing which needs to occur in connection with any of
|
||||||
|
// these events.
|
||||||
|
rpc StateChange(StateChangeEvent) returns (Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
message ConfigureRequest {
|
||||||
|
// Any plugin-specific data, if present among the NRI configuration.
|
||||||
|
string config = 1;
|
||||||
|
// Name of the runtime NRI is running in.
|
||||||
|
string runtime_name = 2;
|
||||||
|
// Version of the runtime NRI is running in.
|
||||||
|
string runtime_version = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ConfigureResponse {
|
||||||
|
// Events to subscribe the plugin for. Each bit set corresponds to an
|
||||||
|
// enumerated Event.
|
||||||
|
int32 events = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SynchronizeRequest {
|
||||||
|
// Pods known to the runtime.
|
||||||
|
repeated PodSandbox pods = 1;
|
||||||
|
// Containers known to the runtime.
|
||||||
|
repeated Container containers = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SynchronizeResponse {
|
||||||
|
// Updates to containers requested by the plugin.
|
||||||
|
repeated ContainerUpdate update = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateContainerRequest {
|
||||||
|
// Pod of container being created.
|
||||||
|
PodSandbox pod = 1;
|
||||||
|
// Container being created.
|
||||||
|
Container container = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateContainerResponse {
|
||||||
|
// Requested adjustments to container being created.
|
||||||
|
ContainerAdjustment adjust = 1;
|
||||||
|
// Requested updates to other existing containers.
|
||||||
|
repeated ContainerUpdate update = 2;
|
||||||
|
// Requested eviction of existing containers.
|
||||||
|
repeated ContainerEviction evict = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateContainerRequest {
|
||||||
|
// Pod of container being updated.
|
||||||
|
PodSandbox pod = 1;
|
||||||
|
// Container being updated.
|
||||||
|
Container container = 2;
|
||||||
|
// Resources to update.
|
||||||
|
LinuxResources linux_resources = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateContainerResponse {
|
||||||
|
// Requested updates to containers.
|
||||||
|
repeated ContainerUpdate update = 1;
|
||||||
|
// Requested eviction of containers.
|
||||||
|
repeated ContainerEviction evict = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StopContainerRequest {
|
||||||
|
// Pod of container being stopped.
|
||||||
|
PodSandbox pod = 1;
|
||||||
|
// Container being stopped.
|
||||||
|
Container container = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StopContainerResponse {
|
||||||
|
// Requested updates to containers.
|
||||||
|
repeated ContainerUpdate update = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StateChangeEvent {
|
||||||
|
// Event type of notification.
|
||||||
|
Event event = 1;
|
||||||
|
// Pod this notification is sent for. If this event is related to a container,
|
||||||
|
// pod is set to the pod of the container.
|
||||||
|
PodSandbox pod = 2;
|
||||||
|
// Container this notification is sent for. If the event is related to a pod,
|
||||||
|
// container is nil.
|
||||||
|
Container container = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty response for those *Requests that are semantically events.
|
||||||
|
message Empty {}
|
||||||
|
|
||||||
|
// Events that plugins can subscribe to in ConfigureResponse.
|
||||||
|
enum Event {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
RUN_POD_SANDBOX = 1;
|
||||||
|
STOP_POD_SANDBOX = 2;
|
||||||
|
REMOVE_POD_SANDBOX = 3;
|
||||||
|
CREATE_CONTAINER = 4;
|
||||||
|
POST_CREATE_CONTAINER = 5;
|
||||||
|
START_CONTAINER = 6;
|
||||||
|
POST_START_CONTAINER = 7;
|
||||||
|
UPDATE_CONTAINER = 8;
|
||||||
|
POST_UPDATE_CONTAINER = 9;
|
||||||
|
STOP_CONTAINER = 10;
|
||||||
|
REMOVE_CONTAINER = 11;
|
||||||
|
LAST = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pod metadata that is considered relevant for a plugin.
|
||||||
|
message PodSandbox {
|
||||||
|
string id = 1;
|
||||||
|
string name = 2;
|
||||||
|
string uid = 3;
|
||||||
|
string namespace = 4;
|
||||||
|
map<string, string> labels = 5;
|
||||||
|
map<string, string> annotations = 6;
|
||||||
|
string runtime_handler = 7;
|
||||||
|
LinuxPodSandbox linux = 8;
|
||||||
|
uint32 pid = 9; // for NRI v1 emulation
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodSandbox linux-specific metadata
|
||||||
|
message LinuxPodSandbox {
|
||||||
|
LinuxResources pod_overhead = 1;
|
||||||
|
LinuxResources pod_resources = 2;
|
||||||
|
string cgroup_parent = 3;
|
||||||
|
string cgroups_path = 4; // for NRI v1 emulation
|
||||||
|
repeated LinuxNamespace namespaces = 5; // for NRI v1 emulation
|
||||||
|
LinuxResources resources = 6; // for NRI v1 emulation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container metadata that is considered relevant for a plugin.
|
||||||
|
message Container {
|
||||||
|
string id = 1;
|
||||||
|
string pod_sandbox_id = 2;
|
||||||
|
string name = 3;
|
||||||
|
ContainerState state = 4;
|
||||||
|
map<string, string> labels = 5;
|
||||||
|
map<string, string> annotations = 6;
|
||||||
|
repeated string args = 7;
|
||||||
|
repeated string env = 8;
|
||||||
|
repeated Mount mounts = 9;
|
||||||
|
Hooks hooks = 10;
|
||||||
|
LinuxContainer linux = 11;
|
||||||
|
uint32 pid = 12; // for NRI v1 emulation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Possible container states.
|
||||||
|
enum ContainerState {
|
||||||
|
CONTAINER_UNKNOWN = 0;
|
||||||
|
CONTAINER_CREATED = 1;
|
||||||
|
CONTAINER_PAUSED = 2; // is this useful/necessary ?
|
||||||
|
CONTAINER_RUNNING = 3;
|
||||||
|
CONTAINER_STOPPED = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A container mount.
|
||||||
|
message Mount {
|
||||||
|
string destination = 1;
|
||||||
|
string type = 2;
|
||||||
|
string source = 3;
|
||||||
|
repeated string options = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container OCI hooks.
|
||||||
|
message Hooks {
|
||||||
|
repeated Hook prestart = 1;
|
||||||
|
repeated Hook create_runtime = 2;
|
||||||
|
repeated Hook create_container = 3;
|
||||||
|
repeated Hook start_container = 4;
|
||||||
|
repeated Hook poststart = 5;
|
||||||
|
repeated Hook poststop = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// One OCI hook.
|
||||||
|
message Hook {
|
||||||
|
string path = 1;
|
||||||
|
repeated string args = 2;
|
||||||
|
repeated string env = 3;
|
||||||
|
OptionalInt timeout = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container (linux) metadata.
|
||||||
|
message LinuxContainer {
|
||||||
|
repeated LinuxNamespace namespaces = 1;
|
||||||
|
repeated LinuxDevice devices = 2;
|
||||||
|
LinuxResources resources = 3;
|
||||||
|
OptionalInt oom_score_adj = 4;
|
||||||
|
string cgroups_path = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A linux namespace.
|
||||||
|
message LinuxNamespace {
|
||||||
|
string type = 1;
|
||||||
|
string path = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A container (linux) device.
|
||||||
|
message LinuxDevice {
|
||||||
|
string path = 1;
|
||||||
|
string type = 2;
|
||||||
|
int64 major = 3;
|
||||||
|
int64 minor = 4;
|
||||||
|
OptionalFileMode file_mode = 5;
|
||||||
|
OptionalUInt32 uid = 6;
|
||||||
|
OptionalUInt32 gid = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A linux device cgroup controller rule.
|
||||||
|
message LinuxDeviceCgroup {
|
||||||
|
bool allow = 1;
|
||||||
|
string type = 2;
|
||||||
|
OptionalInt64 major = 3;
|
||||||
|
OptionalInt64 minor = 4;
|
||||||
|
string access = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container (linux) resources.
|
||||||
|
message LinuxResources {
|
||||||
|
LinuxMemory memory = 1;
|
||||||
|
LinuxCPU cpu = 2;
|
||||||
|
repeated HugepageLimit hugepage_limits = 3;
|
||||||
|
OptionalString blockio_class = 4;
|
||||||
|
OptionalString rdt_class = 5;
|
||||||
|
map<string, string> unified = 6;
|
||||||
|
repeated LinuxDeviceCgroup devices = 7; // for NRI v1 emulation
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory-related parts of (linux) resources.
|
||||||
|
message LinuxMemory {
|
||||||
|
OptionalInt64 limit = 1;
|
||||||
|
OptionalInt64 reservation = 2;
|
||||||
|
OptionalInt64 swap = 3;
|
||||||
|
OptionalInt64 kernel = 4;
|
||||||
|
OptionalInt64 kernel_tcp = 5;
|
||||||
|
OptionalUInt64 swappiness = 6;
|
||||||
|
OptionalBool disable_oom_killer = 7;
|
||||||
|
OptionalBool use_hierarchy = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CPU-related parts of (linux) resources.
|
||||||
|
message LinuxCPU {
|
||||||
|
OptionalUInt64 shares = 1;
|
||||||
|
OptionalInt64 quota = 2;
|
||||||
|
OptionalUInt64 period = 3;
|
||||||
|
OptionalInt64 realtime_runtime = 4;
|
||||||
|
OptionalUInt64 realtime_period = 5;
|
||||||
|
string cpus = 6;
|
||||||
|
string mems = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Container huge page limit.
|
||||||
|
message HugepageLimit {
|
||||||
|
string page_size = 1;
|
||||||
|
uint64 limit = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requested adjustments to a container being created.
|
||||||
|
message ContainerAdjustment {
|
||||||
|
map<string, string> annotations = 2;
|
||||||
|
repeated Mount mounts = 3;
|
||||||
|
repeated KeyValue env = 4;
|
||||||
|
Hooks hooks = 5;
|
||||||
|
LinuxContainerAdjustment linux = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjustments to (linux) resources.
|
||||||
|
message LinuxContainerAdjustment {
|
||||||
|
repeated LinuxDevice devices = 1;
|
||||||
|
LinuxResources resources = 2;
|
||||||
|
string cgroups_path = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requested update to an already created container.
|
||||||
|
message ContainerUpdate {
|
||||||
|
string container_id = 1;
|
||||||
|
LinuxContainerUpdate linux = 2;
|
||||||
|
bool ignore_failure = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates to (linux) resources.
|
||||||
|
message LinuxContainerUpdate {
|
||||||
|
LinuxResources resources = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request to evict (IOW unsolicitedly stop) a container.
|
||||||
|
message ContainerEviction {
|
||||||
|
// Container to evict.
|
||||||
|
string container_id = 1;
|
||||||
|
// Human-readable reason for eviction.
|
||||||
|
string reason = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyValue represents an environment variable.
|
||||||
|
message KeyValue {
|
||||||
|
string key = 1;
|
||||||
|
string value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional string value.
|
||||||
|
message OptionalString {
|
||||||
|
string value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional signed integer value.
|
||||||
|
message OptionalInt {
|
||||||
|
int64 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional 32-bit signed integer value.
|
||||||
|
message OptionalInt32 {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional 32-bit unsigned integer value.
|
||||||
|
message OptionalUInt32 {
|
||||||
|
uint32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional 64-bit signed integer value.
|
||||||
|
message OptionalInt64 {
|
||||||
|
int64 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional 64-bit unsigned integer value.
|
||||||
|
message OptionalUInt64 {
|
||||||
|
uint64 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional boolean value.
|
||||||
|
message OptionalBool {
|
||||||
|
bool value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An optional value of file permissions.
|
||||||
|
message OptionalFileMode {
|
||||||
|
uint32 value = 1;
|
||||||
|
}
|
179
vendor/github.com/containerd/nri/pkg/api/api_ttrpc.pb.go
generated
vendored
Normal file
179
vendor/github.com/containerd/nri/pkg/api/api_ttrpc.pb.go
generated
vendored
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
// Code generated by protoc-gen-go-ttrpc. DO NOT EDIT.
|
||||||
|
// source: pkg/api/api.proto
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
ttrpc "github.com/containerd/ttrpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RuntimeService interface {
|
||||||
|
RegisterPlugin(ctx context.Context, req *RegisterPluginRequest) (*Empty, error)
|
||||||
|
UpdateContainers(ctx context.Context, req *UpdateContainersRequest) (*UpdateContainersResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterRuntimeService(srv *ttrpc.Server, svc RuntimeService) {
|
||||||
|
srv.Register("nri.pkg.api.v1alpha1.Runtime", map[string]ttrpc.Method{
|
||||||
|
"RegisterPlugin": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req RegisterPluginRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.RegisterPlugin(ctx, &req)
|
||||||
|
},
|
||||||
|
"UpdateContainers": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req UpdateContainersRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.UpdateContainers(ctx, &req)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type runtimeClient struct {
|
||||||
|
client *ttrpc.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRuntimeClient(client *ttrpc.Client) RuntimeService {
|
||||||
|
return &runtimeClient{
|
||||||
|
client: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (c *runtimeClient) RegisterPlugin(ctx context.Context, req *RegisterPluginRequest) (*Empty, error) {
|
||||||
|
var resp Empty
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Runtime", "RegisterPlugin", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *runtimeClient) UpdateContainers(ctx context.Context, req *UpdateContainersRequest) (*UpdateContainersResponse, error) {
|
||||||
|
var resp UpdateContainersResponse
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Runtime", "UpdateContainers", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type PluginService interface {
|
||||||
|
Configure(ctx context.Context, req *ConfigureRequest) (*ConfigureResponse, error)
|
||||||
|
Synchronize(ctx context.Context, req *SynchronizeRequest) (*SynchronizeResponse, error)
|
||||||
|
Shutdown(ctx context.Context, req *Empty) (*Empty, error)
|
||||||
|
CreateContainer(ctx context.Context, req *CreateContainerRequest) (*CreateContainerResponse, error)
|
||||||
|
UpdateContainer(ctx context.Context, req *UpdateContainerRequest) (*UpdateContainerResponse, error)
|
||||||
|
StopContainer(ctx context.Context, req *StopContainerRequest) (*StopContainerResponse, error)
|
||||||
|
StateChange(ctx context.Context, req *StateChangeEvent) (*Empty, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterPluginService(srv *ttrpc.Server, svc PluginService) {
|
||||||
|
srv.Register("nri.pkg.api.v1alpha1.Plugin", map[string]ttrpc.Method{
|
||||||
|
"Configure": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req ConfigureRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.Configure(ctx, &req)
|
||||||
|
},
|
||||||
|
"Synchronize": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req SynchronizeRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.Synchronize(ctx, &req)
|
||||||
|
},
|
||||||
|
"Shutdown": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req Empty
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.Shutdown(ctx, &req)
|
||||||
|
},
|
||||||
|
"CreateContainer": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req CreateContainerRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.CreateContainer(ctx, &req)
|
||||||
|
},
|
||||||
|
"UpdateContainer": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req UpdateContainerRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.UpdateContainer(ctx, &req)
|
||||||
|
},
|
||||||
|
"StopContainer": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req StopContainerRequest
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.StopContainer(ctx, &req)
|
||||||
|
},
|
||||||
|
"StateChange": func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {
|
||||||
|
var req StateChangeEvent
|
||||||
|
if err := unmarshal(&req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return svc.StateChange(ctx, &req)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type pluginClient struct {
|
||||||
|
client *ttrpc.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPluginClient(client *ttrpc.Client) PluginService {
|
||||||
|
return &pluginClient{
|
||||||
|
client: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (c *pluginClient) Configure(ctx context.Context, req *ConfigureRequest) (*ConfigureResponse, error) {
|
||||||
|
var resp ConfigureResponse
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "Configure", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *pluginClient) Synchronize(ctx context.Context, req *SynchronizeRequest) (*SynchronizeResponse, error) {
|
||||||
|
var resp SynchronizeResponse
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "Synchronize", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *pluginClient) Shutdown(ctx context.Context, req *Empty) (*Empty, error) {
|
||||||
|
var resp Empty
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "Shutdown", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *pluginClient) CreateContainer(ctx context.Context, req *CreateContainerRequest) (*CreateContainerResponse, error) {
|
||||||
|
var resp CreateContainerResponse
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "CreateContainer", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *pluginClient) UpdateContainer(ctx context.Context, req *UpdateContainerRequest) (*UpdateContainerResponse, error) {
|
||||||
|
var resp UpdateContainerResponse
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "UpdateContainer", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *pluginClient) StopContainer(ctx context.Context, req *StopContainerRequest) (*StopContainerResponse, error) {
|
||||||
|
var resp StopContainerResponse
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "StopContainer", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
||||||
|
func (c *pluginClient) StateChange(ctx context.Context, req *StateChangeEvent) (*Empty, error) {
|
||||||
|
var resp Empty
|
||||||
|
if err := c.client.Call(ctx, "nri.pkg.api.v1alpha1.Plugin", "StateChange", req, &resp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &resp, nil
|
||||||
|
}
|
89
vendor/github.com/containerd/nri/pkg/api/device.go
generated
vendored
Normal file
89
vendor/github.com/containerd/nri/pkg/api/device.go
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FromOCILinuxDevices returns a device slice from an OCI runtime Spec.
|
||||||
|
func FromOCILinuxDevices(o []rspec.LinuxDevice) []*LinuxDevice {
|
||||||
|
var devices []*LinuxDevice
|
||||||
|
for _, d := range o {
|
||||||
|
devices = append(devices, &LinuxDevice{
|
||||||
|
Path: d.Path,
|
||||||
|
Type: d.Type,
|
||||||
|
Major: d.Major,
|
||||||
|
Minor: d.Minor,
|
||||||
|
FileMode: FileMode(d.FileMode),
|
||||||
|
Uid: UInt32(d.UID),
|
||||||
|
Gid: UInt32(d.GID),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return devices
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToOCI returns the linux devices for an OCI runtime Spec.
|
||||||
|
func (d *LinuxDevice) ToOCI() rspec.LinuxDevice {
|
||||||
|
if d == nil {
|
||||||
|
return rspec.LinuxDevice{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rspec.LinuxDevice{
|
||||||
|
Path: d.Path,
|
||||||
|
Type: d.Type,
|
||||||
|
Major: d.Major,
|
||||||
|
Minor: d.Minor,
|
||||||
|
FileMode: d.FileMode.Get(),
|
||||||
|
UID: d.Uid.Get(),
|
||||||
|
GID: d.Gid.Get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccessString returns an OCI access string for the device.
|
||||||
|
func (d *LinuxDevice) AccessString() string {
|
||||||
|
r, w, m := "r", "w", ""
|
||||||
|
|
||||||
|
if mode := d.FileMode.Get(); mode != nil {
|
||||||
|
perm := mode.Perm()
|
||||||
|
if (perm & 0444) != 0 {
|
||||||
|
r = "r"
|
||||||
|
}
|
||||||
|
if (perm & 0222) != 0 {
|
||||||
|
w = "w"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if d.Type == "b" {
|
||||||
|
m = "m"
|
||||||
|
}
|
||||||
|
|
||||||
|
return r + w + m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cmp returns true if the devices are equal.
|
||||||
|
func (d *LinuxDevice) Cmp(v *LinuxDevice) bool {
|
||||||
|
if v == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return d.Major != v.Major || d.Minor != v.Minor
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMarkedForRemoval checks if a LinuxDevice is marked for removal.
|
||||||
|
func (d *LinuxDevice) IsMarkedForRemoval() (string, bool) {
|
||||||
|
key, marked := IsMarkedForRemoval(d.Path)
|
||||||
|
return key, marked
|
||||||
|
}
|
17
vendor/github.com/containerd/nri/pkg/api/doc.go
generated
vendored
Normal file
17
vendor/github.com/containerd/nri/pkg/api/doc.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
60
vendor/github.com/containerd/nri/pkg/api/env.go
generated
vendored
Normal file
60
vendor/github.com/containerd/nri/pkg/api/env.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ToOCI returns an OCI Env entry for the KeyValue.
|
||||||
|
func (e *KeyValue) ToOCI() string {
|
||||||
|
return e.Key + "=" + e.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromOCIEnv returns KeyValues from an OCI runtime Spec environment.
|
||||||
|
func FromOCIEnv(in []string) []*KeyValue {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := []*KeyValue{}
|
||||||
|
for _, keyval := range in {
|
||||||
|
var key, val string
|
||||||
|
split := strings.SplitN(keyval, "=", 2)
|
||||||
|
switch len(split) {
|
||||||
|
case 0:
|
||||||
|
continue
|
||||||
|
case 1:
|
||||||
|
key = split[0]
|
||||||
|
case 2:
|
||||||
|
key = split[0]
|
||||||
|
val = split[1]
|
||||||
|
default:
|
||||||
|
val = strings.Join(split[1:], "=")
|
||||||
|
}
|
||||||
|
out = append(out, &KeyValue{
|
||||||
|
Key: key,
|
||||||
|
Value: val,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMarkedForRemoval checks if an environment variable is marked for removal.
|
||||||
|
func (e *KeyValue) IsMarkedForRemoval() (string, bool) {
|
||||||
|
key, marked := IsMarkedForRemoval(e.Key)
|
||||||
|
return key, marked
|
||||||
|
}
|
172
vendor/github.com/containerd/nri/pkg/api/event.go
generated
vendored
Normal file
172
vendor/github.com/containerd/nri/pkg/api/event.go
generated
vendored
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ValidEvents is the event mask of all valid events.
|
||||||
|
ValidEvents = EventMask((1 << (Event_LAST - 1)) - 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
// nolint
|
||||||
|
type (
|
||||||
|
// Define *Request/*Response type aliases for *Event/Empty pairs.
|
||||||
|
|
||||||
|
StateChangeResponse = Empty
|
||||||
|
RunPodSandboxRequest = StateChangeEvent
|
||||||
|
RunPodSandboxResponse = Empty
|
||||||
|
StopPodSandboxRequest = StateChangeEvent
|
||||||
|
StopPodSandboxResponse = Empty
|
||||||
|
RemovePodSandboxRequest = StateChangeEvent
|
||||||
|
RemovePodSandboxResponse = Empty
|
||||||
|
StartContainerRequest = StateChangeEvent
|
||||||
|
StartContainerResponse = Empty
|
||||||
|
RemoveContainerRequest = StateChangeEvent
|
||||||
|
RemoveContainerResponse = Empty
|
||||||
|
PostCreateContainerRequest = StateChangeEvent
|
||||||
|
PostCreateContainerResponse = Empty
|
||||||
|
PostStartContainerRequest = StateChangeEvent
|
||||||
|
PostStartContainerResponse = Empty
|
||||||
|
PostUpdateContainerRequest = StateChangeEvent
|
||||||
|
PostUpdateContainerResponse = Empty
|
||||||
|
|
||||||
|
ShutdownRequest = Empty
|
||||||
|
ShutdownResponse = Empty
|
||||||
|
)
|
||||||
|
|
||||||
|
// EventMask corresponds to a set of enumerated Events.
|
||||||
|
type EventMask int32
|
||||||
|
|
||||||
|
// ParseEventMask parses a string representation into an EventMask.
|
||||||
|
func ParseEventMask(events ...string) (EventMask, error) {
|
||||||
|
var mask EventMask
|
||||||
|
|
||||||
|
bits := map[string]Event{
|
||||||
|
"runpodsandbox": Event_RUN_POD_SANDBOX,
|
||||||
|
"stoppodsandbox": Event_STOP_POD_SANDBOX,
|
||||||
|
"removepodsandbox": Event_REMOVE_POD_SANDBOX,
|
||||||
|
"createcontainer": Event_CREATE_CONTAINER,
|
||||||
|
"postcreatecontainer": Event_POST_CREATE_CONTAINER,
|
||||||
|
"startcontainer": Event_START_CONTAINER,
|
||||||
|
"poststartcontainer": Event_POST_START_CONTAINER,
|
||||||
|
"updatecontainer": Event_UPDATE_CONTAINER,
|
||||||
|
"postupdatecontainer": Event_POST_UPDATE_CONTAINER,
|
||||||
|
"stopcontainer": Event_STOP_CONTAINER,
|
||||||
|
"removecontainer": Event_REMOVE_CONTAINER,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, event := range events {
|
||||||
|
lcEvents := strings.ToLower(event)
|
||||||
|
for _, name := range strings.Split(lcEvents, ",") {
|
||||||
|
switch name {
|
||||||
|
case "all":
|
||||||
|
mask |= ValidEvents
|
||||||
|
continue
|
||||||
|
case "pod", "podsandbox":
|
||||||
|
for name, bit := range bits {
|
||||||
|
if strings.Contains(name, "Pod") {
|
||||||
|
mask.Set(bit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
case "container":
|
||||||
|
for name, bit := range bits {
|
||||||
|
if strings.Contains(name, "Container") {
|
||||||
|
mask.Set(bit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
bit, ok := bits[strings.TrimSpace(name)]
|
||||||
|
if !ok {
|
||||||
|
return 0, fmt.Errorf("unknown event %q", name)
|
||||||
|
}
|
||||||
|
mask.Set(bit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mask, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustParseEventMask parses the given events, panic()ing on errors.
|
||||||
|
func MustParseEventMask(events ...string) EventMask {
|
||||||
|
mask, err := ParseEventMask(events...)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to parse events %s", strings.Join(events, " ")))
|
||||||
|
}
|
||||||
|
return mask
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrettyString returns a human-readable string representation of an EventMask.
|
||||||
|
func (m *EventMask) PrettyString() string {
|
||||||
|
names := map[Event]string{
|
||||||
|
Event_RUN_POD_SANDBOX: "RunPodSandbox",
|
||||||
|
Event_STOP_POD_SANDBOX: "StopPodSandbox",
|
||||||
|
Event_REMOVE_POD_SANDBOX: "RemovePodSandbox",
|
||||||
|
Event_CREATE_CONTAINER: "CreateContainer",
|
||||||
|
Event_POST_CREATE_CONTAINER: "PostCreateContainer",
|
||||||
|
Event_START_CONTAINER: "StartContainer",
|
||||||
|
Event_POST_START_CONTAINER: "PostStartContainer",
|
||||||
|
Event_UPDATE_CONTAINER: "UpdateContainer",
|
||||||
|
Event_POST_UPDATE_CONTAINER: "PostUpdateContainer",
|
||||||
|
Event_STOP_CONTAINER: "StopContainer",
|
||||||
|
Event_REMOVE_CONTAINER: "RemoveContainer",
|
||||||
|
}
|
||||||
|
|
||||||
|
mask := *m
|
||||||
|
events, sep := "", ""
|
||||||
|
|
||||||
|
for bit := Event_UNKNOWN + 1; bit <= Event_LAST; bit++ {
|
||||||
|
if mask.IsSet(bit) {
|
||||||
|
events += sep + names[bit]
|
||||||
|
sep = ","
|
||||||
|
mask.Clear(bit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if mask != 0 {
|
||||||
|
events += sep + fmt.Sprintf("unknown(0x%x)", mask)
|
||||||
|
}
|
||||||
|
|
||||||
|
return events
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the given Events in the mask.
|
||||||
|
func (m *EventMask) Set(events ...Event) *EventMask {
|
||||||
|
for _, e := range events {
|
||||||
|
*m |= (1 << (e - 1))
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear clears the given Events in the mask.
|
||||||
|
func (m *EventMask) Clear(events ...Event) *EventMask {
|
||||||
|
for _, e := range events {
|
||||||
|
*m &^= (1 << (e - 1))
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSet check if the given Event is set in the mask.
|
||||||
|
func (m *EventMask) IsSet(e Event) bool {
|
||||||
|
return *m&(1<<(e-1)) != 0
|
||||||
|
}
|
59
vendor/github.com/containerd/nri/pkg/api/helpers.go
generated
vendored
Normal file
59
vendor/github.com/containerd/nri/pkg/api/helpers.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
// DupStringSlice creates a copy of a string slice.
|
||||||
|
func DupStringSlice(in []string) []string {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := make([]string, len(in))
|
||||||
|
copy(out, in)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DupStringMap creates a copy of a map with string keys and values.
|
||||||
|
func DupStringMap(in map[string]string) map[string]string {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := map[string]string{}
|
||||||
|
for k, v := range in {
|
||||||
|
out[k] = v
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMarkedForRemoval checks if a key is marked for removal.
|
||||||
|
//
|
||||||
|
// The key can be an annotation name, a mount container path, a device path,
|
||||||
|
// or an environment variable name. These are all marked for removal in
|
||||||
|
// adjustments by preceding their corresponding key with a '-'.
|
||||||
|
func IsMarkedForRemoval(key string) (string, bool) {
|
||||||
|
if key == "" {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
if key[0] != '-' {
|
||||||
|
return key, false
|
||||||
|
}
|
||||||
|
return key[1:], true
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarkForRemoval returns a key marked for removal.
|
||||||
|
func MarkForRemoval(key string) string {
|
||||||
|
return "-" + key
|
||||||
|
}
|
103
vendor/github.com/containerd/nri/pkg/api/hooks.go
generated
vendored
Normal file
103
vendor/github.com/containerd/nri/pkg/api/hooks.go
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Append appends the given hooks to the existing ones.
|
||||||
|
func (hooks *Hooks) Append(h *Hooks) *Hooks {
|
||||||
|
if h == nil {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
hooks.Prestart = append(hooks.Prestart, h.Prestart...)
|
||||||
|
hooks.CreateRuntime = append(hooks.CreateRuntime, h.CreateRuntime...)
|
||||||
|
hooks.CreateContainer = append(hooks.CreateContainer, h.CreateContainer...)
|
||||||
|
hooks.StartContainer = append(hooks.StartContainer, h.StartContainer...)
|
||||||
|
hooks.Poststart = append(hooks.Poststart, h.Poststart...)
|
||||||
|
hooks.Poststop = append(hooks.Poststop, h.Poststop...)
|
||||||
|
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hooks returns itself it any of its hooks is set. Otherwise it returns nil.
|
||||||
|
func (hooks *Hooks) Hooks() *Hooks {
|
||||||
|
if hooks == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(hooks.Prestart) > 0 {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
if len(hooks.CreateRuntime) > 0 {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
if len(hooks.CreateContainer) > 0 {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
if len(hooks.StartContainer) > 0 {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
if len(hooks.Poststart) > 0 {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
if len(hooks.Poststop) > 0 {
|
||||||
|
return hooks
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToOCI returns the hook for an OCI runtime Spec.
|
||||||
|
func (h *Hook) ToOCI() rspec.Hook {
|
||||||
|
return rspec.Hook{
|
||||||
|
Path: h.Path,
|
||||||
|
Args: DupStringSlice(h.Args),
|
||||||
|
Env: DupStringSlice(h.Env),
|
||||||
|
Timeout: h.Timeout.Get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromOCIHooks returns hooks from an OCI runtime Spec.
|
||||||
|
func FromOCIHooks(o *rspec.Hooks) *Hooks {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &Hooks{
|
||||||
|
Prestart: FromOCIHookSlice(o.Prestart),
|
||||||
|
CreateRuntime: FromOCIHookSlice(o.CreateRuntime),
|
||||||
|
CreateContainer: FromOCIHookSlice(o.CreateContainer),
|
||||||
|
StartContainer: FromOCIHookSlice(o.StartContainer),
|
||||||
|
Poststart: FromOCIHookSlice(o.Poststart),
|
||||||
|
Poststop: FromOCIHookSlice(o.Poststop),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromOCIHookSlice returns a hook slice from an OCI runtime Spec.
|
||||||
|
func FromOCIHookSlice(o []rspec.Hook) []*Hook {
|
||||||
|
var hooks []*Hook
|
||||||
|
for _, h := range o {
|
||||||
|
hooks = append(hooks, &Hook{
|
||||||
|
Path: h.Path,
|
||||||
|
Args: DupStringSlice(h.Args),
|
||||||
|
Env: DupStringSlice(h.Env),
|
||||||
|
Timeout: Int(h.Timeout),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return hooks
|
||||||
|
}
|
89
vendor/github.com/containerd/nri/pkg/api/mount.go
generated
vendored
Normal file
89
vendor/github.com/containerd/nri/pkg/api/mount.go
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SELinuxRelabel is a Mount pseudo-option to request relabeling.
|
||||||
|
SELinuxRelabel = "relabel"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FromOCIMounts returns a Mount slice for an OCI runtime Spec.
|
||||||
|
func FromOCIMounts(o []rspec.Mount) []*Mount {
|
||||||
|
var mounts []*Mount
|
||||||
|
for _, m := range o {
|
||||||
|
mounts = append(mounts, &Mount{
|
||||||
|
Destination: m.Destination,
|
||||||
|
Type: m.Type,
|
||||||
|
Source: m.Source,
|
||||||
|
Options: DupStringSlice(m.Options),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return mounts
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToOCI returns a Mount for an OCI runtime Spec.
|
||||||
|
func (m *Mount) ToOCI(propagationQuery *string) rspec.Mount {
|
||||||
|
o := rspec.Mount{
|
||||||
|
Destination: m.Destination,
|
||||||
|
Type: m.Type,
|
||||||
|
Source: m.Source,
|
||||||
|
Options: []string{},
|
||||||
|
}
|
||||||
|
for _, opt := range m.Options {
|
||||||
|
o.Options = append(o.Options, opt)
|
||||||
|
if propagationQuery != nil && (opt == "rprivate" || opt == "rshared" || opt == "rslave") {
|
||||||
|
*propagationQuery = opt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cmp returns true if the mounts are equal.
|
||||||
|
func (m *Mount) Cmp(v *Mount) bool {
|
||||||
|
if v == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if m.Destination != v.Destination || m.Type != v.Type || m.Source != v.Source ||
|
||||||
|
len(m.Options) != len(v.Options) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
mOpts := make([]string, len(m.Options))
|
||||||
|
vOpts := make([]string, len(m.Options))
|
||||||
|
sort.Strings(mOpts)
|
||||||
|
sort.Strings(vOpts)
|
||||||
|
|
||||||
|
for i, o := range mOpts {
|
||||||
|
if vOpts[i] != o {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMarkedForRemoval checks if a Mount is marked for removal.
|
||||||
|
func (m *Mount) IsMarkedForRemoval() (string, bool) {
|
||||||
|
key, marked := IsMarkedForRemoval(m.Destination)
|
||||||
|
return key, marked
|
||||||
|
}
|
33
vendor/github.com/containerd/nri/pkg/api/namespace.go
generated
vendored
Normal file
33
vendor/github.com/containerd/nri/pkg/api/namespace.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FromOCILinuxNamespaces returns a namespace slice from an OCI runtime Spec.
|
||||||
|
func FromOCILinuxNamespaces(o []rspec.LinuxNamespace) []*LinuxNamespace {
|
||||||
|
var namespaces []*LinuxNamespace
|
||||||
|
for _, ns := range o {
|
||||||
|
namespaces = append(namespaces, &LinuxNamespace{
|
||||||
|
Type: string(ns.Type),
|
||||||
|
Path: ns.Path,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return namespaces
|
||||||
|
}
|
341
vendor/github.com/containerd/nri/pkg/api/optional.go
generated
vendored
Normal file
341
vendor/github.com/containerd/nri/pkg/api/optional.go
generated
vendored
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
// XXX FIXME:
|
||||||
|
//
|
||||||
|
// The optional interface constructor should be updated/split up
|
||||||
|
// to avoid having to take an interface{} argument. Instead The
|
||||||
|
// optional types should have a
|
||||||
|
// - constructor taking the underlying native type
|
||||||
|
// - a Copy() function for copying them
|
||||||
|
// - a FromPointer constructor to create them from an optionally nil
|
||||||
|
// pointer to the underlying native type (to help constructing from
|
||||||
|
// structures that use a pointer to the native underlying type to
|
||||||
|
// denote optionality (OCI Spec mostly))
|
||||||
|
// Creating from any other type should use one of these with any explicit
|
||||||
|
// cast for the argument as necessary.
|
||||||
|
//
|
||||||
|
|
||||||
|
// String creates an Optional wrapper from its argument.
|
||||||
|
func String(v interface{}) *OptionalString {
|
||||||
|
var value string
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case string:
|
||||||
|
value = o
|
||||||
|
case *string:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case *OptionalString:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalString{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalString) Get() *string {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := o.Value
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int creates an Optional wrapper from its argument.
|
||||||
|
func Int(v interface{}) *OptionalInt {
|
||||||
|
var value int64
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case int:
|
||||||
|
value = int64(o)
|
||||||
|
case *int:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = int64(*o)
|
||||||
|
case *OptionalInt:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalInt{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalInt) Get() *int {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := int(o.Value)
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int32 creates an Optional wrapper from its argument.
|
||||||
|
func Int32(v interface{}) *OptionalInt32 {
|
||||||
|
var value int32
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case int32:
|
||||||
|
value = o
|
||||||
|
case *int32:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case *OptionalInt32:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalInt32{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalInt32) Get() *int32 {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := o.Value
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// UInt32 creates an Optional wrapper from its argument.
|
||||||
|
func UInt32(v interface{}) *OptionalUInt32 {
|
||||||
|
var value uint32
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case uint32:
|
||||||
|
value = o
|
||||||
|
case *uint32:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case *OptionalUInt32:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalUInt32{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalUInt32) Get() *uint32 {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := o.Value
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 creates an Optional wrapper from its argument.
|
||||||
|
func Int64(v interface{}) *OptionalInt64 {
|
||||||
|
var value int64
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case int:
|
||||||
|
value = int64(o)
|
||||||
|
case uint:
|
||||||
|
value = int64(o)
|
||||||
|
case uint64:
|
||||||
|
value = int64(o)
|
||||||
|
case int64:
|
||||||
|
value = o
|
||||||
|
case *int64:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case *uint64:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = int64(*o)
|
||||||
|
case *OptionalInt64:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalInt64{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalInt64) Get() *int64 {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := o.Value
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// UInt64 creates an Optional wrapper from its argument.
|
||||||
|
func UInt64(v interface{}) *OptionalUInt64 {
|
||||||
|
var value uint64
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case int:
|
||||||
|
value = uint64(o)
|
||||||
|
case uint:
|
||||||
|
value = uint64(o)
|
||||||
|
case int64:
|
||||||
|
value = uint64(o)
|
||||||
|
case uint64:
|
||||||
|
value = o
|
||||||
|
case *int64:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = uint64(*o)
|
||||||
|
case *uint64:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case *OptionalUInt64:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalUInt64{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalUInt64) Get() *uint64 {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := o.Value
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool creates an Optional wrapper from its argument.
|
||||||
|
func Bool(v interface{}) *OptionalBool {
|
||||||
|
var value bool
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case bool:
|
||||||
|
value = o
|
||||||
|
case *bool:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case *OptionalBool:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = o.Value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalBool{
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalBool) Get() *bool {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := o.Value
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileMode creates an Optional wrapper from its argument.
|
||||||
|
func FileMode(v interface{}) *OptionalFileMode {
|
||||||
|
var value os.FileMode
|
||||||
|
|
||||||
|
switch o := v.(type) {
|
||||||
|
case *os.FileMode:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = *o
|
||||||
|
case os.FileMode:
|
||||||
|
value = o
|
||||||
|
case *OptionalFileMode:
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
value = os.FileMode(o.Value)
|
||||||
|
case uint32:
|
||||||
|
value = os.FileMode(o)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OptionalFileMode{
|
||||||
|
Value: uint32(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns nil if its value is unset or a pointer to the value itself.
|
||||||
|
func (o *OptionalFileMode) Get() *os.FileMode {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
v := os.FileMode(o.Value)
|
||||||
|
return &v
|
||||||
|
}
|
58
vendor/github.com/containerd/nri/pkg/api/plugin.go
generated
vendored
Normal file
58
vendor/github.com/containerd/nri/pkg/api/plugin.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultSocketPath is the default socket path for external plugins.
|
||||||
|
DefaultSocketPath = "/var/run/nri.sock"
|
||||||
|
// PluginSocketEnvVar is used to inform plugins about pre-connected sockets.
|
||||||
|
PluginSocketEnvVar = "NRI_PLUGIN_SOCKET"
|
||||||
|
// PluginNameEnvVar is used to inform NRI-launched plugins about their name.
|
||||||
|
PluginNameEnvVar = "NRI_PLUGIN_NAME"
|
||||||
|
// PluginIdxEnvVar is used to inform NRI-launched plugins about their ID.
|
||||||
|
PluginIdxEnvVar = "NRI_PLUGIN_IDX"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParsePluginName parses the (file)name of a plugin into an index and a base.
|
||||||
|
func ParsePluginName(name string) (string, string, error) {
|
||||||
|
split := strings.SplitN(name, "-", 2)
|
||||||
|
if len(split) < 2 {
|
||||||
|
return "", "", fmt.Errorf("invalid plugin name %q, idx-pluginname expected", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := CheckPluginIndex(split[0]); err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return split[0], split[1], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckPluginIndex checks the validity of a plugin index.
|
||||||
|
func CheckPluginIndex(idx string) error {
|
||||||
|
if len(idx) != 2 {
|
||||||
|
return fmt.Errorf("invalid plugin index %q, must be 2 digits", idx)
|
||||||
|
}
|
||||||
|
if !('0' <= idx[0] && idx[0] <= '9') || !('0' <= idx[1] && idx[1] <= '9') {
|
||||||
|
return fmt.Errorf("invalid plugin index %q (not [0-9][0-9])", idx)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
230
vendor/github.com/containerd/nri/pkg/api/resources.go
generated
vendored
Normal file
230
vendor/github.com/containerd/nri/pkg/api/resources.go
generated
vendored
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
cri "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FromOCILinuxResources returns resources from an OCI runtime Spec.
|
||||||
|
func FromOCILinuxResources(o *rspec.LinuxResources, ann map[string]string) *LinuxResources {
|
||||||
|
if o == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
l := &LinuxResources{}
|
||||||
|
if m := o.Memory; m != nil {
|
||||||
|
l.Memory = &LinuxMemory{
|
||||||
|
Limit: Int64(m.Limit),
|
||||||
|
Reservation: Int64(m.Reservation),
|
||||||
|
Swap: Int64(m.Swap),
|
||||||
|
Kernel: Int64(m.Kernel),
|
||||||
|
KernelTcp: Int64(m.KernelTCP),
|
||||||
|
Swappiness: UInt64(m.Swappiness),
|
||||||
|
DisableOomKiller: Bool(m.DisableOOMKiller),
|
||||||
|
UseHierarchy: Bool(m.UseHierarchy),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c := o.CPU; c != nil {
|
||||||
|
l.Cpu = &LinuxCPU{
|
||||||
|
Shares: UInt64(c.Shares),
|
||||||
|
Quota: Int64(c.Quota),
|
||||||
|
Period: UInt64(c.Period),
|
||||||
|
RealtimeRuntime: Int64(c.RealtimeRuntime),
|
||||||
|
RealtimePeriod: UInt64(c.RealtimePeriod),
|
||||||
|
Cpus: c.Cpus,
|
||||||
|
Mems: c.Mems,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, h := range o.HugepageLimits {
|
||||||
|
l.HugepageLimits = append(l.HugepageLimits, &HugepageLimit{
|
||||||
|
PageSize: h.Pagesize,
|
||||||
|
Limit: h.Limit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for _, d := range o.Devices {
|
||||||
|
l.Devices = append(l.Devices, &LinuxDeviceCgroup{
|
||||||
|
Allow: d.Allow,
|
||||||
|
Type: d.Type,
|
||||||
|
Major: Int64(d.Major),
|
||||||
|
Minor: Int64(d.Minor),
|
||||||
|
Access: d.Access,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromCRILinuxResources(c *cri.LinuxContainerResources) *LinuxResources {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
shares, quota, period := uint64(c.CpuShares), c.CpuQuota, uint64(c.CpuPeriod)
|
||||||
|
r := &LinuxResources{
|
||||||
|
Cpu: &LinuxCPU{
|
||||||
|
Shares: UInt64(&shares),
|
||||||
|
Quota: Int64("a),
|
||||||
|
Period: UInt64(&period),
|
||||||
|
Cpus: c.CpusetCpus,
|
||||||
|
Mems: c.CpusetMems,
|
||||||
|
},
|
||||||
|
Memory: &LinuxMemory{
|
||||||
|
Limit: Int64(&c.MemoryLimitInBytes),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, l := range c.HugepageLimits {
|
||||||
|
r.HugepageLimits = append(r.HugepageLimits,
|
||||||
|
&HugepageLimit{
|
||||||
|
PageSize: l.PageSize,
|
||||||
|
Limit: l.Limit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToOCI returns resources for an OCI runtime Spec.
|
||||||
|
func (r *LinuxResources) ToOCI() *rspec.LinuxResources {
|
||||||
|
if r == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
o := &rspec.LinuxResources{}
|
||||||
|
if r.Memory != nil {
|
||||||
|
o.Memory = &rspec.LinuxMemory{
|
||||||
|
Limit: r.Memory.Limit.Get(),
|
||||||
|
Reservation: r.Memory.Reservation.Get(),
|
||||||
|
Swap: r.Memory.Swap.Get(),
|
||||||
|
Kernel: r.Memory.Kernel.Get(),
|
||||||
|
KernelTCP: r.Memory.KernelTcp.Get(),
|
||||||
|
Swappiness: r.Memory.Swappiness.Get(),
|
||||||
|
DisableOOMKiller: r.Memory.DisableOomKiller.Get(),
|
||||||
|
UseHierarchy: r.Memory.UseHierarchy.Get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if r.Cpu != nil {
|
||||||
|
o.CPU = &rspec.LinuxCPU{
|
||||||
|
Shares: r.Cpu.Shares.Get(),
|
||||||
|
Quota: r.Cpu.Quota.Get(),
|
||||||
|
Period: r.Cpu.Period.Get(),
|
||||||
|
RealtimeRuntime: r.Cpu.RealtimeRuntime.Get(),
|
||||||
|
RealtimePeriod: r.Cpu.RealtimePeriod.Get(),
|
||||||
|
Cpus: r.Cpu.Cpus,
|
||||||
|
Mems: r.Cpu.Mems,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, l := range r.HugepageLimits {
|
||||||
|
o.HugepageLimits = append(o.HugepageLimits, rspec.LinuxHugepageLimit{
|
||||||
|
Pagesize: l.PageSize,
|
||||||
|
Limit: l.Limit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(r.Unified) != 0 {
|
||||||
|
o.Unified = make(map[string]string)
|
||||||
|
for k, v := range r.Unified {
|
||||||
|
o.Unified[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, d := range r.Devices {
|
||||||
|
o.Devices = append(o.Devices, rspec.LinuxDeviceCgroup{
|
||||||
|
Allow: d.Allow,
|
||||||
|
Type: d.Type,
|
||||||
|
Major: d.Major.Get(),
|
||||||
|
Minor: d.Minor.Get(),
|
||||||
|
Access: d.Access,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToCRI returns resources for CRI.
|
||||||
|
func (r *LinuxResources) ToCRI(oomScoreAdj int64) *cri.LinuxContainerResources {
|
||||||
|
if r == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
o := &cri.LinuxContainerResources{}
|
||||||
|
if r.Memory != nil {
|
||||||
|
o.MemoryLimitInBytes = r.Memory.GetLimit().GetValue()
|
||||||
|
o.OomScoreAdj = oomScoreAdj
|
||||||
|
}
|
||||||
|
if r.Cpu != nil {
|
||||||
|
o.CpuShares = int64(r.Cpu.GetShares().GetValue())
|
||||||
|
o.CpuPeriod = int64(r.Cpu.GetPeriod().GetValue())
|
||||||
|
o.CpuQuota = r.Cpu.GetQuota().GetValue()
|
||||||
|
o.CpusetCpus = r.Cpu.Cpus
|
||||||
|
o.CpusetMems = r.Cpu.Mems
|
||||||
|
}
|
||||||
|
for _, l := range r.HugepageLimits {
|
||||||
|
o.HugepageLimits = append(o.HugepageLimits, &cri.HugepageLimit{
|
||||||
|
PageSize: l.PageSize,
|
||||||
|
Limit: l.Limit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(r.Unified) != 0 {
|
||||||
|
o.Unified = make(map[string]string)
|
||||||
|
for k, v := range r.Unified {
|
||||||
|
o.Unified[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy creates a copy of the resources.
|
||||||
|
func (r *LinuxResources) Copy() *LinuxResources {
|
||||||
|
if r == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
o := &LinuxResources{}
|
||||||
|
if r.Memory != nil {
|
||||||
|
o.Memory = &LinuxMemory{
|
||||||
|
Limit: Int64(r.Memory.GetLimit()),
|
||||||
|
Reservation: Int64(r.Memory.GetReservation()),
|
||||||
|
Swap: Int64(r.Memory.GetSwap()),
|
||||||
|
Kernel: Int64(r.Memory.GetKernel()),
|
||||||
|
KernelTcp: Int64(r.Memory.GetKernelTcp()),
|
||||||
|
Swappiness: UInt64(r.Memory.GetSwappiness()),
|
||||||
|
DisableOomKiller: Bool(r.Memory.GetDisableOomKiller()),
|
||||||
|
UseHierarchy: Bool(r.Memory.GetUseHierarchy()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if r.Cpu != nil {
|
||||||
|
o.Cpu = &LinuxCPU{
|
||||||
|
Shares: UInt64(r.Cpu.GetShares()),
|
||||||
|
Quota: Int64(r.Cpu.GetQuota()),
|
||||||
|
Period: UInt64(r.Cpu.GetPeriod()),
|
||||||
|
RealtimeRuntime: Int64(r.Cpu.GetRealtimeRuntime()),
|
||||||
|
RealtimePeriod: UInt64(r.Cpu.GetRealtimePeriod()),
|
||||||
|
Cpus: r.Cpu.GetCpus(),
|
||||||
|
Mems: r.Cpu.GetMems(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, l := range r.HugepageLimits {
|
||||||
|
o.HugepageLimits = append(o.HugepageLimits, &HugepageLimit{
|
||||||
|
PageSize: l.PageSize,
|
||||||
|
Limit: l.Limit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if len(r.Unified) != 0 {
|
||||||
|
o.Unified = make(map[string]string)
|
||||||
|
for k, v := range r.Unified {
|
||||||
|
o.Unified[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
o.BlockioClass = String(r.BlockioClass)
|
||||||
|
o.RdtClass = String(r.RdtClass)
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
186
vendor/github.com/containerd/nri/pkg/api/update.go
generated
vendored
Normal file
186
vendor/github.com/containerd/nri/pkg/api/update.go
generated
vendored
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
//nolint
|
||||||
|
// SetContainerId sets the id of the container to update.
|
||||||
|
func (u *ContainerUpdate) SetContainerId(id string) {
|
||||||
|
u.ContainerId = id
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryLimit records setting the memory limit for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemoryLimit(value int64) {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.Limit = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryReservation records setting the memory reservation for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemoryReservation(value int64) {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.Reservation = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemorySwap records records setting the memory swap limit for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemorySwap(value int64) {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.Swap = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryKernel records setting the memory kernel limit for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemoryKernel(value int64) {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.Kernel = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryKernelTCP records setting the memory kernel TCP limit for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemoryKernelTCP(value int64) {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.KernelTcp = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemorySwappiness records setting the memory swappiness for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemorySwappiness(value uint64) {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.Swappiness = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryDisableOomKiller records disabling the OOM killer for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemoryDisableOomKiller() {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.DisableOomKiller = Bool(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxMemoryUseHierarchy records enabling hierarchical memory accounting for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxMemoryUseHierarchy() {
|
||||||
|
u.initLinuxResourcesMemory()
|
||||||
|
u.Linux.Resources.Memory.UseHierarchy = Bool(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUShares records setting the scheduler's CPU shares for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPUShares(value uint64) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.Shares = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUQuota records setting the scheduler's CPU quota for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPUQuota(value int64) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.Quota = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUPeriod records setting the scheduler's CPU period for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPUPeriod(value int64) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.Period = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPURealtimeRuntime records setting the scheduler's realtime runtime for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPURealtimeRuntime(value int64) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.RealtimeRuntime = Int64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPURealtimePeriod records setting the scheduler's realtime period for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPURealtimePeriod(value uint64) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.RealtimePeriod = UInt64(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUSetCPUs records setting the cpuset CPUs for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPUSetCPUs(value string) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.Cpus = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxCPUSetMems records setting the cpuset memory for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxCPUSetMems(value string) {
|
||||||
|
u.initLinuxResourcesCPU()
|
||||||
|
u.Linux.Resources.Cpu.Mems = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLinuxHugepageLimit records adding a hugepage limit for a container.
|
||||||
|
func (u *ContainerUpdate) AddLinuxHugepageLimit(pageSize string, value uint64) {
|
||||||
|
u.initLinuxResources()
|
||||||
|
u.Linux.Resources.HugepageLimits = append(u.Linux.Resources.HugepageLimits,
|
||||||
|
&HugepageLimit{
|
||||||
|
PageSize: pageSize,
|
||||||
|
Limit: value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxBlockIOClass records setting the Block I/O class for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxBlockIOClass(value string) {
|
||||||
|
u.initLinuxResources()
|
||||||
|
u.Linux.Resources.BlockioClass = String(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLinuxRDTClass records setting the RDT class for a container.
|
||||||
|
func (u *ContainerUpdate) SetLinuxRDTClass(value string) {
|
||||||
|
u.initLinuxResources()
|
||||||
|
u.Linux.Resources.RdtClass = String(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLinuxUnified sets a cgroupv2 unified resource.
|
||||||
|
func (u *ContainerUpdate) AddLinuxUnified(key, value string) {
|
||||||
|
u.initLinuxResourcesUnified()
|
||||||
|
u.Linux.Resources.Unified[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIgnoreFailure marks an Update as ignored for failures.
|
||||||
|
// Such updates will not prevent the related container operation
|
||||||
|
// from succeeding if the update fails.
|
||||||
|
func (u *ContainerUpdate) SetIgnoreFailure() {
|
||||||
|
u.IgnoreFailure = true
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initializing a container update.
|
||||||
|
//
|
||||||
|
|
||||||
|
func (u *ContainerUpdate) initLinux() {
|
||||||
|
if u.Linux == nil {
|
||||||
|
u.Linux = &LinuxContainerUpdate{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *ContainerUpdate) initLinuxResources() {
|
||||||
|
u.initLinux()
|
||||||
|
if u.Linux.Resources == nil {
|
||||||
|
u.Linux.Resources = &LinuxResources{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *ContainerUpdate) initLinuxResourcesMemory() {
|
||||||
|
u.initLinuxResources()
|
||||||
|
if u.Linux.Resources.Memory == nil {
|
||||||
|
u.Linux.Resources.Memory = &LinuxMemory{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *ContainerUpdate) initLinuxResourcesCPU() {
|
||||||
|
u.initLinuxResources()
|
||||||
|
if u.Linux.Resources.Cpu == nil {
|
||||||
|
u.Linux.Resources.Cpu = &LinuxCPU{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *ContainerUpdate) initLinuxResourcesUnified() {
|
||||||
|
u.initLinuxResources()
|
||||||
|
if u.Linux.Resources.Unified == nil {
|
||||||
|
u.Linux.Resources.Unified = make(map[string]string)
|
||||||
|
}
|
||||||
|
}
|
87
vendor/github.com/containerd/nri/pkg/log/log.go
generated
vendored
Normal file
87
vendor/github.com/containerd/nri/pkg/log/log.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
log Logger = &fallbackLogger{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Logger is the interface NRI uses for logging.
|
||||||
|
type Logger interface {
|
||||||
|
Debugf(ctx context.Context, format string, args ...interface{})
|
||||||
|
Infof(ctx context.Context, format string, args ...interface{})
|
||||||
|
Warnf(ctx context.Context, format string, args ...interface{})
|
||||||
|
Errorf(ctx context.Context, format string, args ...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the logger used by NRI.
|
||||||
|
func Set(l Logger) {
|
||||||
|
log = l
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the logger used by NRI.
|
||||||
|
func Get() Logger {
|
||||||
|
return log
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf logs a formatted debug message.
|
||||||
|
func Debugf(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
log.Debugf(ctx, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof logs a formatted informational message.
|
||||||
|
func Infof(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
log.Infof(ctx, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warnf logs a formatted warning message.
|
||||||
|
func Warnf(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
log.Warnf(ctx, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf logs a formatted error message.
|
||||||
|
func Errorf(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
log.Errorf(ctx, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
type fallbackLogger struct{}
|
||||||
|
|
||||||
|
// Debugf logs a formatted debug message.
|
||||||
|
func (f *fallbackLogger) Debugf(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
logrus.WithContext(ctx).Debugf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof logs a formatted informational message.
|
||||||
|
func (f *fallbackLogger) Infof(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
logrus.WithContext(ctx).Infof(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warnf logs a formatted warning message.
|
||||||
|
func (f *fallbackLogger) Warnf(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
logrus.WithContext(ctx).Warnf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf logs a formatted error message.
|
||||||
|
func (f *fallbackLogger) Errorf(ctx context.Context, format string, args ...interface{}) {
|
||||||
|
logrus.WithContext(ctx).Errorf(format, args...)
|
||||||
|
}
|
93
vendor/github.com/containerd/nri/pkg/net/conn.go
generated
vendored
Normal file
93
vendor/github.com/containerd/nri/pkg/net/conn.go
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewFdConn creates a net.Conn for the given (socket) fd.
|
||||||
|
func NewFdConn(fd int) (net.Conn, error) {
|
||||||
|
f := os.NewFile(uintptr(fd), "fd #"+strconv.Itoa(fd))
|
||||||
|
|
||||||
|
conn, err := net.FileConn(f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create net.Conn for fd #%d: %w", fd, err)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// connListener wraps a pre-connected socket in a net.Listener.
|
||||||
|
type connListener struct {
|
||||||
|
next chan net.Conn
|
||||||
|
conn net.Conn
|
||||||
|
addr net.Addr
|
||||||
|
lock sync.RWMutex // for Close()
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewConnListener wraps an existing net.Conn in a net.Listener.
|
||||||
|
//
|
||||||
|
// The first call to Accept() on the listener will return the wrapped
|
||||||
|
// connection. Subsequent calls to Accept() block until the listener
|
||||||
|
// is closed, then return io.EOF. Close() closes the listener and the
|
||||||
|
// wrapped connection.
|
||||||
|
func NewConnListener(conn net.Conn) net.Listener {
|
||||||
|
next := make(chan net.Conn, 1)
|
||||||
|
next <- conn
|
||||||
|
|
||||||
|
return &connListener{
|
||||||
|
next: next,
|
||||||
|
conn: conn,
|
||||||
|
addr: conn.LocalAddr(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept returns the wrapped connection when it is called the first
|
||||||
|
// time. Later calls to Accept block until the listener is closed, then
|
||||||
|
// return io.EOF.
|
||||||
|
func (l *connListener) Accept() (net.Conn, error) {
|
||||||
|
conn := <-l.next
|
||||||
|
if conn == nil {
|
||||||
|
return nil, io.EOF
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the listener and the wrapped connection.
|
||||||
|
func (l *connListener) Close() error {
|
||||||
|
l.lock.Lock()
|
||||||
|
defer l.lock.Unlock()
|
||||||
|
if l.closed {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
close(l.next)
|
||||||
|
l.closed = true
|
||||||
|
return l.conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Addr returns the local address of the wrapped connection.
|
||||||
|
func (l *connListener) Addr() net.Addr {
|
||||||
|
return l.addr
|
||||||
|
}
|
444
vendor/github.com/containerd/nri/pkg/net/multiplex/mux.go
generated
vendored
Normal file
444
vendor/github.com/containerd/nri/pkg/net/multiplex/mux.go
generated
vendored
Normal file
@ -0,0 +1,444 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package multiplex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
nrinet "github.com/containerd/nri/pkg/net"
|
||||||
|
"github.com/containerd/ttrpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Mux multiplexes several logical connections over a single net.Conn.
|
||||||
|
//
|
||||||
|
// Connections are identified within a Mux by ConnIDs which are simple
|
||||||
|
// 32-bit unsigned integers. Opening a connection returns a net.Conn
|
||||||
|
// corrponding to the ConnID. This can then be used to write and read
|
||||||
|
// data through the connection with the Mux performing multiplexing
|
||||||
|
// and demultiplexing of data.
|
||||||
|
//
|
||||||
|
// Writing to a connection is fully synchronous. The caller can safely
|
||||||
|
// reuse the buffer once the call returns. Reading from a connection
|
||||||
|
// returns the oldest demultiplexed buffer for the connection, blocking
|
||||||
|
// if the connections incoming queue is empty. If any incoming queue is
|
||||||
|
// ever overflown the underlying trunk and all multiplexed connections
|
||||||
|
// are closed and an error is recorded. This error is later returned by
|
||||||
|
// any subsequent read from any connection. All connections of the Mux
|
||||||
|
// have the same fixed incoming queue length which can be configured
|
||||||
|
// using the WithReadQueueLength Option during Mux creation.
|
||||||
|
//
|
||||||
|
// The Mux interface also provides functions that emulate net.Dial and
|
||||||
|
// net.Listen for a connection. Usually these can be used for passing
|
||||||
|
// multiplexed connections to packages that insist to Dial or Accept
|
||||||
|
// themselves for connection establishment.
|
||||||
|
//
|
||||||
|
// Note that opening a connection is a virtual operation in the sense
|
||||||
|
// that it has no effects outside the Mux. It is performed without any
|
||||||
|
// signalling or other communication. It merely acquires the net.Conn
|
||||||
|
// corresponding to the connection and blindly assumes that the same
|
||||||
|
// ConnID is or will be opened at the other end of the Mux.
|
||||||
|
type Mux interface {
|
||||||
|
// Open the connection for the given ConnID.
|
||||||
|
Open(ConnID) (net.Conn, error)
|
||||||
|
|
||||||
|
// Close the Mux and all connections associated with it.
|
||||||
|
Close() error
|
||||||
|
|
||||||
|
// Dialer returns a net.Dial-like function for the connection.
|
||||||
|
//
|
||||||
|
// Calling the returned function (with arguments) will return a
|
||||||
|
// net.Conn for the connection.
|
||||||
|
Dialer(ConnID) func(string, string) (net.Conn, error)
|
||||||
|
|
||||||
|
// Listener returns a net.Listener for the connection. The first
|
||||||
|
// call to Accept() on the listener will return a net.Conn for the
|
||||||
|
// connection. Subsequent calls to Accept() will block until the
|
||||||
|
// connection is closed then return io.EOF.
|
||||||
|
Listen(ConnID) (net.Listener, error)
|
||||||
|
|
||||||
|
// Trunk returns the trunk connection for the Mux.
|
||||||
|
Trunk() net.Conn
|
||||||
|
|
||||||
|
// Unblock unblocks the Mux reader.
|
||||||
|
Unblock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnID uniquely identifies a logical connection within a Mux.
|
||||||
|
type ConnID uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ConnID 0 is reserved for future use.
|
||||||
|
reservedConnID ConnID = iota
|
||||||
|
// LowestConnID is the lowest externally usable ConnID.
|
||||||
|
LowestConnID
|
||||||
|
)
|
||||||
|
|
||||||
|
// Option to apply to a Mux.
|
||||||
|
type Option func(*mux)
|
||||||
|
|
||||||
|
// WithBlockedRead causes the Mux to be blocked for reading until gets Unblock()'ed.
|
||||||
|
func WithBlockedRead() Option {
|
||||||
|
return func(m *mux) {
|
||||||
|
if m.blockC == nil {
|
||||||
|
m.blockC = make(chan struct{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithReadQueueLength overrides the default read queue size.
|
||||||
|
func WithReadQueueLength(length int) Option {
|
||||||
|
return func(m *mux) {
|
||||||
|
m.qlen = length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiplex returns a multiplexer for the given connection.
|
||||||
|
func Multiplex(trunk net.Conn, options ...Option) Mux {
|
||||||
|
return newMux(trunk, options...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mux is our implementation of Mux.
|
||||||
|
type mux struct {
|
||||||
|
trunk net.Conn
|
||||||
|
writeLock sync.Mutex
|
||||||
|
conns map[ConnID]*conn
|
||||||
|
connLock sync.RWMutex
|
||||||
|
qlen int
|
||||||
|
errOnce sync.Once
|
||||||
|
err error
|
||||||
|
unblkOnce sync.Once
|
||||||
|
blockC chan struct{}
|
||||||
|
closeOnce sync.Once
|
||||||
|
doneC chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// default read queue length for a single connection
|
||||||
|
readQueueLen = 256
|
||||||
|
// length of frame header: 4-byte ConnID, 4-byte payload length
|
||||||
|
headerLen = 8
|
||||||
|
// max. allowed payload size
|
||||||
|
maxPayloadSize = 1 << 24
|
||||||
|
)
|
||||||
|
|
||||||
|
// conn represents a single multiplexed connection.
|
||||||
|
type conn struct {
|
||||||
|
id ConnID
|
||||||
|
mux *mux
|
||||||
|
readC chan []byte
|
||||||
|
closeOnce sync.Once
|
||||||
|
doneC chan error
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMux(trunk net.Conn, options ...Option) *mux {
|
||||||
|
m := &mux{
|
||||||
|
trunk: trunk,
|
||||||
|
conns: make(map[ConnID]*conn),
|
||||||
|
qlen: readQueueLen,
|
||||||
|
doneC: make(chan struct{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o := range options {
|
||||||
|
o(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.blockC == nil {
|
||||||
|
WithBlockedRead()(m)
|
||||||
|
m.Unblock()
|
||||||
|
}
|
||||||
|
|
||||||
|
go m.reader()
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) Trunk() net.Conn {
|
||||||
|
return m.trunk
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) Unblock() {
|
||||||
|
m.unblkOnce.Do(func() {
|
||||||
|
close(m.blockC)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) Open(id ConnID) (net.Conn, error) {
|
||||||
|
if id == reservedConnID {
|
||||||
|
return nil, fmt.Errorf("ConnID %d is reserved", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.connLock.Lock()
|
||||||
|
defer m.connLock.Unlock()
|
||||||
|
|
||||||
|
c, ok := m.conns[id]
|
||||||
|
if !ok {
|
||||||
|
c = &conn{
|
||||||
|
id: id,
|
||||||
|
mux: m,
|
||||||
|
doneC: make(chan error, 1),
|
||||||
|
readC: make(chan []byte, m.qlen),
|
||||||
|
}
|
||||||
|
m.conns[id] = c
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) Close() error {
|
||||||
|
m.closeOnce.Do(func() {
|
||||||
|
m.connLock.Lock()
|
||||||
|
defer m.connLock.Unlock()
|
||||||
|
for _, conn := range m.conns {
|
||||||
|
conn.close()
|
||||||
|
}
|
||||||
|
close(m.doneC)
|
||||||
|
m.trunk.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) Dialer(id ConnID) func(string, string) (net.Conn, error) {
|
||||||
|
return func(string, string) (net.Conn, error) {
|
||||||
|
return m.Open(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) Listen(id ConnID) (net.Listener, error) {
|
||||||
|
conn, err := m.Open(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nrinet.NewConnListener(conn), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) write(id ConnID, buf []byte) (int, error) {
|
||||||
|
var hdr [headerLen]byte
|
||||||
|
|
||||||
|
if len(buf) > maxPayloadSize {
|
||||||
|
return 0, syscall.EMSGSIZE
|
||||||
|
}
|
||||||
|
|
||||||
|
binary.BigEndian.PutUint32(hdr[0:4], uint32(id))
|
||||||
|
binary.BigEndian.PutUint32(hdr[4:8], uint32(len(buf)))
|
||||||
|
|
||||||
|
m.writeLock.Lock()
|
||||||
|
defer m.writeLock.Unlock()
|
||||||
|
|
||||||
|
n, err := m.trunk.Write(hdr[:])
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("failed to write header to trunk: %w", err)
|
||||||
|
if n != 0 {
|
||||||
|
m.setError(err)
|
||||||
|
m.Close()
|
||||||
|
}
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err = m.trunk.Write(buf)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("failed to write payload to trunk: %w", err)
|
||||||
|
if n != 0 {
|
||||||
|
m.setError(err)
|
||||||
|
m.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) reader() {
|
||||||
|
var (
|
||||||
|
hdr [headerLen]byte
|
||||||
|
cid uint32
|
||||||
|
cnt uint32
|
||||||
|
buf []byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
<-m.blockC
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-m.doneC:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.ReadFull(m.trunk, hdr[:])
|
||||||
|
if err != nil {
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, io.EOF):
|
||||||
|
case errors.Is(err, ttrpc.ErrClosed):
|
||||||
|
err = io.EOF
|
||||||
|
case errors.Is(err, ttrpc.ErrServerClosed):
|
||||||
|
err = io.EOF
|
||||||
|
case errors.Is(err, net.ErrClosed):
|
||||||
|
err = io.EOF
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("failed to read header from trunk: %w", err)
|
||||||
|
}
|
||||||
|
m.setError(err)
|
||||||
|
m.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cid = binary.BigEndian.Uint32(hdr[0:4])
|
||||||
|
cnt = binary.BigEndian.Uint32(hdr[4:8])
|
||||||
|
buf = make([]byte, int(cnt))
|
||||||
|
|
||||||
|
_, err = io.ReadFull(m.trunk, buf)
|
||||||
|
if err != nil {
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, io.EOF):
|
||||||
|
case errors.Is(err, ttrpc.ErrClosed):
|
||||||
|
err = io.EOF
|
||||||
|
case errors.Is(err, ttrpc.ErrServerClosed):
|
||||||
|
err = io.EOF
|
||||||
|
case errors.Is(err, net.ErrClosed):
|
||||||
|
err = io.EOF
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("failed to read payload from trunk: %w", err)
|
||||||
|
}
|
||||||
|
m.setError(err)
|
||||||
|
m.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.connLock.RLock()
|
||||||
|
conn, ok := m.conns[ConnID(cid)]
|
||||||
|
m.connLock.RUnlock()
|
||||||
|
if ok {
|
||||||
|
select {
|
||||||
|
case conn.readC <- buf:
|
||||||
|
default:
|
||||||
|
m.setError(errors.New("failed to queue payload for reading"))
|
||||||
|
m.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mux) setError(err error) {
|
||||||
|
m.errOnce.Do(func() {
|
||||||
|
m.err = err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// nolint
|
||||||
|
func (m *mux) error() error {
|
||||||
|
m.errOnce.Do(func() {
|
||||||
|
if m.err == nil {
|
||||||
|
m.err = io.EOF
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return m.err
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// multiplexed connections
|
||||||
|
//
|
||||||
|
|
||||||
|
// Reads reads the next message from the multiplexed connection.
|
||||||
|
func (c *conn) Read(buf []byte) (int, error) {
|
||||||
|
var (
|
||||||
|
msg []byte
|
||||||
|
err error
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case err, ok = <-c.doneC:
|
||||||
|
if !ok || err == nil {
|
||||||
|
err = c.mux.error()
|
||||||
|
}
|
||||||
|
return 0, err
|
||||||
|
case msg, ok = <-c.readC:
|
||||||
|
if !ok {
|
||||||
|
return 0, c.mux.error()
|
||||||
|
}
|
||||||
|
if cap(buf) < len(msg) {
|
||||||
|
return 0, syscall.ENOMEM
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(buf, msg)
|
||||||
|
return len(msg), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write writes the given data to the multiplexed connection.
|
||||||
|
func (c *conn) Write(b []byte) (int, error) {
|
||||||
|
select {
|
||||||
|
case err := <-c.doneC:
|
||||||
|
if err == nil {
|
||||||
|
err = io.EOF
|
||||||
|
}
|
||||||
|
return 0, err
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return c.mux.write(c.id, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the multiplexed connection.
|
||||||
|
func (c *conn) Close() error {
|
||||||
|
c.mux.connLock.Lock()
|
||||||
|
defer c.mux.connLock.Unlock()
|
||||||
|
if c.mux.conns[c.id] == c {
|
||||||
|
delete(c.mux.conns, c.id)
|
||||||
|
}
|
||||||
|
return c.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) close() error {
|
||||||
|
c.closeOnce.Do(func() {
|
||||||
|
close(c.doneC)
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalAddr is the unimplemented stub for the corresponding net.Conn function.
|
||||||
|
func (c *conn) LocalAddr() net.Addr {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoteAddr is the unimplemented stub for the corresponding net.Conn function.
|
||||||
|
func (c *conn) RemoteAddr() net.Addr {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDeadline is the unimplemented stub for the corresponding net.Conn function.
|
||||||
|
func (c *conn) SetDeadline(t time.Time) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetReadDeadline is the unimplemented stub for the corresponding net.Conn function.
|
||||||
|
func (c *conn) SetReadDeadline(t time.Time) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWriteDeadline is the unimplemented stub for the corresponding net.Conn function.
|
||||||
|
func (c *conn) SetWriteDeadline(t time.Time) error {
|
||||||
|
return nil
|
||||||
|
}
|
24
vendor/github.com/containerd/nri/pkg/net/multiplex/ttrpc.go
generated
vendored
Normal file
24
vendor/github.com/containerd/nri/pkg/net/multiplex/ttrpc.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package multiplex
|
||||||
|
|
||||||
|
const (
|
||||||
|
// PluginServiceConn is the mux connection ID for NRI plugin services.
|
||||||
|
PluginServiceConn ConnID = iota + 1
|
||||||
|
// RuntimeServiceConn is the mux connection ID for NRI runtime services.
|
||||||
|
RuntimeServiceConn
|
||||||
|
)
|
98
vendor/github.com/containerd/nri/pkg/net/socketpair_unix.go
generated
vendored
Normal file
98
vendor/github.com/containerd/nri/pkg/net/socketpair_unix.go
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
//go:build !windows
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
syscall "golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
local = 0
|
||||||
|
peer = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// SocketPair contains the file descriptors of a connected pair of sockets.
|
||||||
|
type SocketPair [2]int
|
||||||
|
|
||||||
|
// NewSocketPair returns a connected pair of sockets.
|
||||||
|
func NewSocketPair() (SocketPair, error) {
|
||||||
|
fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
|
||||||
|
if err != nil {
|
||||||
|
return [2]int{-1, -1}, fmt.Errorf("failed to create socketpair: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalFile returns the socketpair fd for local usage as an *os.File.
|
||||||
|
func (fds SocketPair) LocalFile() *os.File {
|
||||||
|
return os.NewFile(uintptr(fds[local]), fds.fileName()+"[0]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerFile returns the socketpair fd for peer usage as an *os.File.
|
||||||
|
func (fds SocketPair) PeerFile() *os.File {
|
||||||
|
return os.NewFile(uintptr(fds[peer]), fds.fileName()+"[1]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalConn returns a net.Conn for the local end of the socketpair.
|
||||||
|
func (fds SocketPair) LocalConn() (net.Conn, error) {
|
||||||
|
file := fds.LocalFile()
|
||||||
|
defer file.Close()
|
||||||
|
conn, err := net.FileConn(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create net.Conn for %s[0]: %w", fds.fileName(), err)
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerConn returns a net.Conn for the peer end of the socketpair.
|
||||||
|
func (fds SocketPair) PeerConn() (net.Conn, error) {
|
||||||
|
file := fds.PeerFile()
|
||||||
|
defer file.Close()
|
||||||
|
conn, err := net.FileConn(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create net.Conn for %s[1]: %w", fds.fileName(), err)
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes both ends of the socketpair.
|
||||||
|
func (fds SocketPair) Close() {
|
||||||
|
fds.LocalClose()
|
||||||
|
fds.PeerClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalClose closes the local end of the socketpair.
|
||||||
|
func (fds SocketPair) LocalClose() {
|
||||||
|
syscall.Close(fds[local])
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerClose closes the peer end of the socketpair.
|
||||||
|
func (fds SocketPair) PeerClose() {
|
||||||
|
syscall.Close(fds[peer])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fds SocketPair) fileName() string {
|
||||||
|
return fmt.Sprintf("socketpair-#%d:%d[0]", fds[local], fds[peer])
|
||||||
|
}
|
198
vendor/github.com/containerd/nri/pkg/net/socketpair_windows.go
generated
vendored
Normal file
198
vendor/github.com/containerd/nri/pkg/net/socketpair_windows.go
generated
vendored
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
sys "golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SocketPair contains a connected pair of sockets.
|
||||||
|
type SocketPair [2]sys.Handle
|
||||||
|
|
||||||
|
const (
|
||||||
|
local = 0
|
||||||
|
peer = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewSocketPair returns a connected pair of sockets.
|
||||||
|
func NewSocketPair() (SocketPair, error) {
|
||||||
|
/* return [2]sys.Handle{sys.InvalidHandle, sys.InvalidHandle},
|
||||||
|
errors.New("failed to emulatesocketpair, unimplemented for windows")*/
|
||||||
|
|
||||||
|
// untested: return emulateWithPreConnect()
|
||||||
|
return emulateWithPreConnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
func emulateWithPreConnect() (SocketPair, error) {
|
||||||
|
var (
|
||||||
|
invalid = SocketPair{sys.InvalidHandle, sys.InvalidHandle}
|
||||||
|
sa sys.SockaddrInet4
|
||||||
|
//sn sys.Sockaddr
|
||||||
|
l sys.Handle
|
||||||
|
a sys.Handle
|
||||||
|
p sys.Handle
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
l, err = socket(sys.AF_INET, sys.SOCK_STREAM, 0)
|
||||||
|
if err != nil {
|
||||||
|
return invalid, fmt.Errorf("failed to emulate socketpair (local Socket()): %w", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
sys.CloseHandle(l)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
sa.Addr[0] = 127
|
||||||
|
sa.Addr[3] = 1
|
||||||
|
sa.Port = 9999
|
||||||
|
|
||||||
|
err = sys.Bind(l, &sa)
|
||||||
|
if err != nil {
|
||||||
|
return invalid, fmt.Errorf("failed to emulate socketpair (Bind()): %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*sn, err = sys.Getsockname(l)
|
||||||
|
if err != nil {
|
||||||
|
return invalid, fmt.Errorf("failed to emulate socketpair (Getsockname()): %w", err)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
p, err = socket(sys.AF_INET, sys.SOCK_STREAM, 0)
|
||||||
|
if err != nil {
|
||||||
|
return invalid, fmt.Errorf("failed to emulate socketpair (peer Socket()): %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
sys.CloseHandle(p)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = sys.Listen(l, 0)
|
||||||
|
if err != nil {
|
||||||
|
return invalid, fmt.Errorf("failed to emulate socketpair (Listen()): %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err = connect(p, &sa)
|
||||||
|
}()
|
||||||
|
|
||||||
|
a, err = accept(l, sys.AF_INET, sys.SOCK_STREAM, 0)
|
||||||
|
if err != nil {
|
||||||
|
return invalid, fmt.Errorf("failed to emualte socketpair (Accept()): %w", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
sys.CloseHandle(a)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
sys.CloseHandle(l)
|
||||||
|
return SocketPair{a, p}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes both ends of the socketpair.
|
||||||
|
func (sp SocketPair) Close() {
|
||||||
|
sp.LocalClose()
|
||||||
|
sp.PeerClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalFile returns the socketpair fd for local usage as an *os.File.
|
||||||
|
func (sp SocketPair) LocalFile() *os.File {
|
||||||
|
return os.NewFile(uintptr(sp[local]), sp.fileName()+"[0]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerFile returns the socketpair fd for peer usage as an *os.File.
|
||||||
|
func (sp SocketPair) PeerFile() *os.File {
|
||||||
|
return os.NewFile(uintptr(sp[peer]), sp.fileName()+"[1]")
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalConn returns a net.Conn for the local end of the socketpair.
|
||||||
|
func (sp SocketPair) LocalConn() (net.Conn, error) {
|
||||||
|
file := sp.LocalFile()
|
||||||
|
defer file.Close()
|
||||||
|
conn, err := net.FileConn(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create net.Conn for %s[0]: %w", sp.fileName(), err)
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerConn returns a net.Conn for the peer end of the socketpair.
|
||||||
|
func (sp SocketPair) PeerConn() (net.Conn, error) {
|
||||||
|
file := sp.PeerFile()
|
||||||
|
defer file.Close()
|
||||||
|
conn, err := net.FileConn(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create net.Conn for %s[1]: %w", sp.fileName(), err)
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalClose closes the local end of the socketpair.
|
||||||
|
func (sp SocketPair) LocalClose() {
|
||||||
|
sys.CloseHandle(sp[local])
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerClose closes the peer end of the socketpair.
|
||||||
|
func (sp SocketPair) PeerClose() {
|
||||||
|
sys.CloseHandle(sp[peer])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sp SocketPair) fileName() string {
|
||||||
|
return fmt.Sprintf("socketpair-#%d:%d[0]", sp[local], sp[peer])
|
||||||
|
}
|
||||||
|
|
||||||
|
func socket(domain, typ, proto int) (sys.Handle, error) {
|
||||||
|
return sys.WSASocket(int32(domain), int32(typ), int32(proto), nil, 0, sys.WSA_FLAG_OVERLAPPED)
|
||||||
|
}
|
||||||
|
|
||||||
|
func connect(s sys.Handle, sa sys.Sockaddr) error {
|
||||||
|
o := &sys.Overlapped{}
|
||||||
|
return sys.ConnectEx(s, sa, nil, 0, nil, o)
|
||||||
|
}
|
||||||
|
|
||||||
|
func accept(l sys.Handle, domain, typ, proto int) (sys.Handle, error) {
|
||||||
|
var (
|
||||||
|
a sys.Handle
|
||||||
|
err error
|
||||||
|
buf = [1024]byte{}
|
||||||
|
overlap = sys.Overlapped{}
|
||||||
|
cnt = uint32(16 + 256)
|
||||||
|
)
|
||||||
|
|
||||||
|
a, err = socket(sys.AF_INET, sys.SOCK_STREAM, 0)
|
||||||
|
if err != nil {
|
||||||
|
return sys.InvalidHandle, fmt.Errorf("failed to emulate socketpair (accept): %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sys.AcceptEx(l, a, (*byte)(unsafe.Pointer(&buf)), 0, cnt, cnt, &cnt, &overlap)
|
||||||
|
if err != nil {
|
||||||
|
return sys.InvalidHandle, fmt.Errorf("failed to emulate socketpair (AcceptEx()): %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return a, nil
|
||||||
|
}
|
3
vendor/github.com/containerd/nri/types/v1/types.go
generated
vendored
3
vendor/github.com/containerd/nri/types/v1/types.go
generated
vendored
@ -18,8 +18,7 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Plugin type and configuration
|
// Plugin type and configuration
|
||||||
|
99
vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
generated
vendored
99
vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
generated
vendored
@ -12,10 +12,12 @@ type Spec struct {
|
|||||||
Root *Root `json:"root,omitempty"`
|
Root *Root `json:"root,omitempty"`
|
||||||
// Hostname configures the container's hostname.
|
// Hostname configures the container's hostname.
|
||||||
Hostname string `json:"hostname,omitempty"`
|
Hostname string `json:"hostname,omitempty"`
|
||||||
|
// Domainname configures the container's domainname.
|
||||||
|
Domainname string `json:"domainname,omitempty"`
|
||||||
// Mounts configures additional mounts (on top of Root).
|
// Mounts configures additional mounts (on top of Root).
|
||||||
Mounts []Mount `json:"mounts,omitempty"`
|
Mounts []Mount `json:"mounts,omitempty"`
|
||||||
// Hooks configures callbacks for container lifecycle events.
|
// Hooks configures callbacks for container lifecycle events.
|
||||||
Hooks *Hooks `json:"hooks,omitempty" platform:"linux,solaris"`
|
Hooks *Hooks `json:"hooks,omitempty" platform:"linux,solaris,zos"`
|
||||||
// Annotations contains arbitrary metadata for the container.
|
// Annotations contains arbitrary metadata for the container.
|
||||||
Annotations map[string]string `json:"annotations,omitempty"`
|
Annotations map[string]string `json:"annotations,omitempty"`
|
||||||
|
|
||||||
@ -27,6 +29,8 @@ type Spec struct {
|
|||||||
Windows *Windows `json:"windows,omitempty" platform:"windows"`
|
Windows *Windows `json:"windows,omitempty" platform:"windows"`
|
||||||
// VM specifies configuration for virtual-machine-based containers.
|
// VM specifies configuration for virtual-machine-based containers.
|
||||||
VM *VM `json:"vm,omitempty" platform:"vm"`
|
VM *VM `json:"vm,omitempty" platform:"vm"`
|
||||||
|
// ZOS is platform-specific configuration for z/OS based containers.
|
||||||
|
ZOS *ZOS `json:"zos,omitempty" platform:"zos"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process contains information to start a specific application inside the container.
|
// Process contains information to start a specific application inside the container.
|
||||||
@ -49,7 +53,7 @@ type Process struct {
|
|||||||
// Capabilities are Linux capabilities that are kept for the process.
|
// Capabilities are Linux capabilities that are kept for the process.
|
||||||
Capabilities *LinuxCapabilities `json:"capabilities,omitempty" platform:"linux"`
|
Capabilities *LinuxCapabilities `json:"capabilities,omitempty" platform:"linux"`
|
||||||
// Rlimits specifies rlimit options to apply to the process.
|
// Rlimits specifies rlimit options to apply to the process.
|
||||||
Rlimits []POSIXRlimit `json:"rlimits,omitempty" platform:"linux,solaris"`
|
Rlimits []POSIXRlimit `json:"rlimits,omitempty" platform:"linux,solaris,zos"`
|
||||||
// NoNewPrivileges controls whether additional privileges could be gained by processes in the container.
|
// NoNewPrivileges controls whether additional privileges could be gained by processes in the container.
|
||||||
NoNewPrivileges bool `json:"noNewPrivileges,omitempty" platform:"linux"`
|
NoNewPrivileges bool `json:"noNewPrivileges,omitempty" platform:"linux"`
|
||||||
// ApparmorProfile specifies the apparmor profile for the container.
|
// ApparmorProfile specifies the apparmor profile for the container.
|
||||||
@ -86,11 +90,11 @@ type Box struct {
|
|||||||
// User specifies specific user (and group) information for the container process.
|
// User specifies specific user (and group) information for the container process.
|
||||||
type User struct {
|
type User struct {
|
||||||
// UID is the user id.
|
// UID is the user id.
|
||||||
UID uint32 `json:"uid" platform:"linux,solaris"`
|
UID uint32 `json:"uid" platform:"linux,solaris,zos"`
|
||||||
// GID is the group id.
|
// GID is the group id.
|
||||||
GID uint32 `json:"gid" platform:"linux,solaris"`
|
GID uint32 `json:"gid" platform:"linux,solaris,zos"`
|
||||||
// Umask is the umask for the init process.
|
// Umask is the umask for the init process.
|
||||||
Umask *uint32 `json:"umask,omitempty" platform:"linux,solaris"`
|
Umask *uint32 `json:"umask,omitempty" platform:"linux,solaris,zos"`
|
||||||
// AdditionalGids are additional group ids set for the container's process.
|
// AdditionalGids are additional group ids set for the container's process.
|
||||||
AdditionalGids []uint32 `json:"additionalGids,omitempty" platform:"linux,solaris"`
|
AdditionalGids []uint32 `json:"additionalGids,omitempty" platform:"linux,solaris"`
|
||||||
// Username is the user name.
|
// Username is the user name.
|
||||||
@ -110,11 +114,16 @@ type Mount struct {
|
|||||||
// Destination is the absolute path where the mount will be placed in the container.
|
// Destination is the absolute path where the mount will be placed in the container.
|
||||||
Destination string `json:"destination"`
|
Destination string `json:"destination"`
|
||||||
// Type specifies the mount kind.
|
// Type specifies the mount kind.
|
||||||
Type string `json:"type,omitempty" platform:"linux,solaris"`
|
Type string `json:"type,omitempty" platform:"linux,solaris,zos"`
|
||||||
// Source specifies the source path of the mount.
|
// Source specifies the source path of the mount.
|
||||||
Source string `json:"source,omitempty"`
|
Source string `json:"source,omitempty"`
|
||||||
// Options are fstab style mount options.
|
// Options are fstab style mount options.
|
||||||
Options []string `json:"options,omitempty"`
|
Options []string `json:"options,omitempty"`
|
||||||
|
|
||||||
|
// UID/GID mappings used for changing file owners w/o calling chown, fs should support it.
|
||||||
|
// Every mount point could have its own mapping.
|
||||||
|
UIDMappings []LinuxIDMapping `json:"uidMappings,omitempty" platform:"linux"`
|
||||||
|
GIDMappings []LinuxIDMapping `json:"gidMappings,omitempty" platform:"linux"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook specifies a command that is run at a particular event in the lifecycle of a container
|
// Hook specifies a command that is run at a particular event in the lifecycle of a container
|
||||||
@ -178,7 +187,7 @@ type Linux struct {
|
|||||||
// MountLabel specifies the selinux context for the mounts in the container.
|
// MountLabel specifies the selinux context for the mounts in the container.
|
||||||
MountLabel string `json:"mountLabel,omitempty"`
|
MountLabel string `json:"mountLabel,omitempty"`
|
||||||
// IntelRdt contains Intel Resource Director Technology (RDT) information for
|
// IntelRdt contains Intel Resource Director Technology (RDT) information for
|
||||||
// handling resource constraints (e.g., L3 cache, memory bandwidth) for the container
|
// handling resource constraints and monitoring metrics (e.g., L3 cache, memory bandwidth) for the container
|
||||||
IntelRdt *LinuxIntelRdt `json:"intelRdt,omitempty"`
|
IntelRdt *LinuxIntelRdt `json:"intelRdt,omitempty"`
|
||||||
// Personality contains configuration for the Linux personality syscall
|
// Personality contains configuration for the Linux personality syscall
|
||||||
Personality *LinuxPersonality `json:"personality,omitempty"`
|
Personality *LinuxPersonality `json:"personality,omitempty"`
|
||||||
@ -250,8 +259,8 @@ type LinuxInterfacePriority struct {
|
|||||||
Priority uint32 `json:"priority"`
|
Priority uint32 `json:"priority"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// linuxBlockIODevice holds major:minor format supported in blkio cgroup
|
// LinuxBlockIODevice holds major:minor format supported in blkio cgroup
|
||||||
type linuxBlockIODevice struct {
|
type LinuxBlockIODevice struct {
|
||||||
// Major is the device's major number.
|
// Major is the device's major number.
|
||||||
Major int64 `json:"major"`
|
Major int64 `json:"major"`
|
||||||
// Minor is the device's minor number.
|
// Minor is the device's minor number.
|
||||||
@ -260,7 +269,7 @@ type linuxBlockIODevice struct {
|
|||||||
|
|
||||||
// LinuxWeightDevice struct holds a `major:minor weight` pair for weightDevice
|
// LinuxWeightDevice struct holds a `major:minor weight` pair for weightDevice
|
||||||
type LinuxWeightDevice struct {
|
type LinuxWeightDevice struct {
|
||||||
linuxBlockIODevice
|
LinuxBlockIODevice
|
||||||
// Weight is the bandwidth rate for the device.
|
// Weight is the bandwidth rate for the device.
|
||||||
Weight *uint16 `json:"weight,omitempty"`
|
Weight *uint16 `json:"weight,omitempty"`
|
||||||
// LeafWeight is the bandwidth rate for the device while competing with the cgroup's child cgroups, CFQ scheduler only
|
// LeafWeight is the bandwidth rate for the device while competing with the cgroup's child cgroups, CFQ scheduler only
|
||||||
@ -269,7 +278,7 @@ type LinuxWeightDevice struct {
|
|||||||
|
|
||||||
// LinuxThrottleDevice struct holds a `major:minor rate_per_second` pair
|
// LinuxThrottleDevice struct holds a `major:minor rate_per_second` pair
|
||||||
type LinuxThrottleDevice struct {
|
type LinuxThrottleDevice struct {
|
||||||
linuxBlockIODevice
|
LinuxBlockIODevice
|
||||||
// Rate is the IO rate limit per cgroup per device
|
// Rate is the IO rate limit per cgroup per device
|
||||||
Rate uint64 `json:"rate"`
|
Rate uint64 `json:"rate"`
|
||||||
}
|
}
|
||||||
@ -328,6 +337,8 @@ type LinuxCPU struct {
|
|||||||
Cpus string `json:"cpus,omitempty"`
|
Cpus string `json:"cpus,omitempty"`
|
||||||
// List of memory nodes in the cpuset. Default is to use any available memory node.
|
// List of memory nodes in the cpuset. Default is to use any available memory node.
|
||||||
Mems string `json:"mems,omitempty"`
|
Mems string `json:"mems,omitempty"`
|
||||||
|
// cgroups are configured with minimum weight, 0: default behavior, 1: SCHED_IDLE.
|
||||||
|
Idle *int64 `json:"idle,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinuxPids for Linux cgroup 'pids' resource management (Linux 4.3)
|
// LinuxPids for Linux cgroup 'pids' resource management (Linux 4.3)
|
||||||
@ -522,11 +533,21 @@ type WindowsMemoryResources struct {
|
|||||||
|
|
||||||
// WindowsCPUResources contains CPU resource management settings.
|
// WindowsCPUResources contains CPU resource management settings.
|
||||||
type WindowsCPUResources struct {
|
type WindowsCPUResources struct {
|
||||||
// Number of CPUs available to the container.
|
// Count is the number of CPUs available to the container. It represents the
|
||||||
|
// fraction of the configured processor `count` in a container in relation
|
||||||
|
// to the processors available in the host. The fraction ultimately
|
||||||
|
// determines the portion of processor cycles that the threads in a
|
||||||
|
// container can use during each scheduling interval, as the number of
|
||||||
|
// cycles per 10,000 cycles.
|
||||||
Count *uint64 `json:"count,omitempty"`
|
Count *uint64 `json:"count,omitempty"`
|
||||||
// CPU shares (relative weight to other containers with cpu shares).
|
// Shares limits the share of processor time given to the container relative
|
||||||
|
// to other workloads on the processor. The processor `shares` (`weight` at
|
||||||
|
// the platform level) is a value between 0 and 10000.
|
||||||
Shares *uint16 `json:"shares,omitempty"`
|
Shares *uint16 `json:"shares,omitempty"`
|
||||||
// Specifies the portion of processor cycles that this container can use as a percentage times 100.
|
// Maximum determines the portion of processor cycles that the threads in a
|
||||||
|
// container can use during each scheduling interval, as the number of
|
||||||
|
// cycles per 10,000 cycles. Set processor `maximum` to a percentage times
|
||||||
|
// 100.
|
||||||
Maximum *uint16 `json:"maximum,omitempty"`
|
Maximum *uint16 `json:"maximum,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,6 +634,19 @@ type Arch string
|
|||||||
// LinuxSeccompFlag is a flag to pass to seccomp(2).
|
// LinuxSeccompFlag is a flag to pass to seccomp(2).
|
||||||
type LinuxSeccompFlag string
|
type LinuxSeccompFlag string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// LinuxSeccompFlagLog is a seccomp flag to request all returned
|
||||||
|
// actions except SECCOMP_RET_ALLOW to be logged. An administrator may
|
||||||
|
// override this filter flag by preventing specific actions from being
|
||||||
|
// logged via the /proc/sys/kernel/seccomp/actions_logged file. (since
|
||||||
|
// Linux 4.14)
|
||||||
|
LinuxSeccompFlagLog LinuxSeccompFlag = "SECCOMP_FILTER_FLAG_LOG"
|
||||||
|
|
||||||
|
// LinuxSeccompFlagSpecAllow can be used to disable Speculative Store
|
||||||
|
// Bypass mitigation. (since Linux 4.17)
|
||||||
|
LinuxSeccompFlagSpecAllow LinuxSeccompFlag = "SECCOMP_FILTER_FLAG_SPEC_ALLOW"
|
||||||
|
)
|
||||||
|
|
||||||
// Additional architectures permitted to be used for system calls
|
// Additional architectures permitted to be used for system calls
|
||||||
// By default only the native architecture of the kernel is permitted
|
// By default only the native architecture of the kernel is permitted
|
||||||
const (
|
const (
|
||||||
@ -683,8 +717,9 @@ type LinuxSyscall struct {
|
|||||||
Args []LinuxSeccompArg `json:"args,omitempty"`
|
Args []LinuxSeccompArg `json:"args,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinuxIntelRdt has container runtime resource constraints for Intel RDT
|
// LinuxIntelRdt has container runtime resource constraints for Intel RDT CAT and MBA
|
||||||
// CAT and MBA features which introduced in Linux 4.10 and 4.12 kernel
|
// features and flags enabling Intel RDT CMT and MBM features.
|
||||||
|
// Intel RDT features are available in Linux 4.14 and newer kernel versions.
|
||||||
type LinuxIntelRdt struct {
|
type LinuxIntelRdt struct {
|
||||||
// The identity for RDT Class of Service
|
// The identity for RDT Class of Service
|
||||||
ClosID string `json:"closID,omitempty"`
|
ClosID string `json:"closID,omitempty"`
|
||||||
@ -697,4 +732,36 @@ type LinuxIntelRdt struct {
|
|||||||
// The unit of memory bandwidth is specified in "percentages" by
|
// The unit of memory bandwidth is specified in "percentages" by
|
||||||
// default, and in "MBps" if MBA Software Controller is enabled.
|
// default, and in "MBps" if MBA Software Controller is enabled.
|
||||||
MemBwSchema string `json:"memBwSchema,omitempty"`
|
MemBwSchema string `json:"memBwSchema,omitempty"`
|
||||||
|
|
||||||
|
// EnableCMT is the flag to indicate if the Intel RDT CMT is enabled. CMT (Cache Monitoring Technology) supports monitoring of
|
||||||
|
// the last-level cache (LLC) occupancy for the container.
|
||||||
|
EnableCMT bool `json:"enableCMT,omitempty"`
|
||||||
|
|
||||||
|
// EnableMBM is the flag to indicate if the Intel RDT MBM is enabled. MBM (Memory Bandwidth Monitoring) supports monitoring of
|
||||||
|
// total and local memory bandwidth for the container.
|
||||||
|
EnableMBM bool `json:"enableMBM,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZOS contains platform-specific configuration for z/OS based containers.
|
||||||
|
type ZOS struct {
|
||||||
|
// Devices are a list of device nodes that are created for the container
|
||||||
|
Devices []ZOSDevice `json:"devices,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZOSDevice represents the mknod information for a z/OS special device file
|
||||||
|
type ZOSDevice struct {
|
||||||
|
// Path to the device.
|
||||||
|
Path string `json:"path"`
|
||||||
|
// Device type, block, char, etc.
|
||||||
|
Type string `json:"type"`
|
||||||
|
// Major is the device's major number.
|
||||||
|
Major int64 `json:"major"`
|
||||||
|
// Minor is the device's minor number.
|
||||||
|
Minor int64 `json:"minor"`
|
||||||
|
// FileMode permission bits for the device.
|
||||||
|
FileMode *os.FileMode `json:"fileMode,omitempty"`
|
||||||
|
// UID of the device.
|
||||||
|
UID *uint32 `json:"uid,omitempty"`
|
||||||
|
// Gid of the device.
|
||||||
|
GID *uint32 `json:"gid,omitempty"`
|
||||||
}
|
}
|
||||||
|
122
vendor/github.com/opencontainers/runtime-tools/error/error.go
generated
vendored
122
vendor/github.com/opencontainers/runtime-tools/error/error.go
generated
vendored
@ -1,122 +0,0 @@
|
|||||||
// Package error implements generic tooling for tracking RFC 2119
|
|
||||||
// violations and linking back to the appropriate specification section.
|
|
||||||
package error
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Level represents the RFC 2119 compliance levels
|
|
||||||
type Level int
|
|
||||||
|
|
||||||
const (
|
|
||||||
// MAY-level
|
|
||||||
|
|
||||||
// May represents 'MAY' in RFC 2119.
|
|
||||||
May Level = iota
|
|
||||||
// Optional represents 'OPTIONAL' in RFC 2119.
|
|
||||||
Optional
|
|
||||||
|
|
||||||
// SHOULD-level
|
|
||||||
|
|
||||||
// Should represents 'SHOULD' in RFC 2119.
|
|
||||||
Should
|
|
||||||
// ShouldNot represents 'SHOULD NOT' in RFC 2119.
|
|
||||||
ShouldNot
|
|
||||||
// Recommended represents 'RECOMMENDED' in RFC 2119.
|
|
||||||
Recommended
|
|
||||||
// NotRecommended represents 'NOT RECOMMENDED' in RFC 2119.
|
|
||||||
NotRecommended
|
|
||||||
|
|
||||||
// MUST-level
|
|
||||||
|
|
||||||
// Must represents 'MUST' in RFC 2119
|
|
||||||
Must
|
|
||||||
// MustNot represents 'MUST NOT' in RFC 2119.
|
|
||||||
MustNot
|
|
||||||
// Shall represents 'SHALL' in RFC 2119.
|
|
||||||
Shall
|
|
||||||
// ShallNot represents 'SHALL NOT' in RFC 2119.
|
|
||||||
ShallNot
|
|
||||||
// Required represents 'REQUIRED' in RFC 2119.
|
|
||||||
Required
|
|
||||||
)
|
|
||||||
|
|
||||||
// Error represents an error with compliance level and specification reference.
|
|
||||||
type Error struct {
|
|
||||||
// Level represents the RFC 2119 compliance level.
|
|
||||||
Level Level
|
|
||||||
|
|
||||||
// Reference is a URL for the violated specification requirement.
|
|
||||||
Reference string
|
|
||||||
|
|
||||||
// Err holds additional details about the violation.
|
|
||||||
Err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseLevel takes a string level and returns the RFC 2119 compliance level constant.
|
|
||||||
func ParseLevel(level string) (Level, error) {
|
|
||||||
switch strings.ToUpper(level) {
|
|
||||||
case "MAY":
|
|
||||||
fallthrough
|
|
||||||
case "OPTIONAL":
|
|
||||||
return May, nil
|
|
||||||
case "SHOULD":
|
|
||||||
fallthrough
|
|
||||||
case "SHOULDNOT":
|
|
||||||
fallthrough
|
|
||||||
case "RECOMMENDED":
|
|
||||||
fallthrough
|
|
||||||
case "NOTRECOMMENDED":
|
|
||||||
return Should, nil
|
|
||||||
case "MUST":
|
|
||||||
fallthrough
|
|
||||||
case "MUSTNOT":
|
|
||||||
fallthrough
|
|
||||||
case "SHALL":
|
|
||||||
fallthrough
|
|
||||||
case "SHALLNOT":
|
|
||||||
fallthrough
|
|
||||||
case "REQUIRED":
|
|
||||||
return Must, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var l Level
|
|
||||||
return l, fmt.Errorf("%q is not a valid compliance level", level)
|
|
||||||
}
|
|
||||||
|
|
||||||
// String takes a RFC 2119 compliance level constant and returns a string representation.
|
|
||||||
func (level Level) String() string {
|
|
||||||
switch level {
|
|
||||||
case May:
|
|
||||||
return "MAY"
|
|
||||||
case Optional:
|
|
||||||
return "OPTIONAL"
|
|
||||||
case Should:
|
|
||||||
return "SHOULD"
|
|
||||||
case ShouldNot:
|
|
||||||
return "SHOULD NOT"
|
|
||||||
case Recommended:
|
|
||||||
return "RECOMMENDED"
|
|
||||||
case NotRecommended:
|
|
||||||
return "NOT RECOMMENDED"
|
|
||||||
case Must:
|
|
||||||
return "MUST"
|
|
||||||
case MustNot:
|
|
||||||
return "MUST NOT"
|
|
||||||
case Shall:
|
|
||||||
return "SHALL"
|
|
||||||
case ShallNot:
|
|
||||||
return "SHALL NOT"
|
|
||||||
case Required:
|
|
||||||
return "REQUIRED"
|
|
||||||
}
|
|
||||||
|
|
||||||
panic(fmt.Sprintf("%d is not a valid compliance level", level))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns the error message with specification reference.
|
|
||||||
func (err *Error) Error() string {
|
|
||||||
return fmt.Sprintf("%s\nRefer to: %s", err.Err.Error(), err.Reference)
|
|
||||||
}
|
|
48
vendor/github.com/opencontainers/runtime-tools/filepath/abs.go
generated
vendored
48
vendor/github.com/opencontainers/runtime-tools/filepath/abs.go
generated
vendored
@ -1,48 +0,0 @@
|
|||||||
package filepath
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var windowsAbs = regexp.MustCompile(`^[a-zA-Z]:\\.*$`)
|
|
||||||
|
|
||||||
// Abs is a version of path/filepath's Abs with an explicit operating
|
|
||||||
// system and current working directory.
|
|
||||||
func Abs(os, path, cwd string) (_ string, err error) {
|
|
||||||
if IsAbs(os, path) {
|
|
||||||
return Clean(os, path), nil
|
|
||||||
}
|
|
||||||
return Clean(os, Join(os, cwd, path)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsAbs is a version of path/filepath's IsAbs with an explicit
|
|
||||||
// operating system.
|
|
||||||
func IsAbs(os, path string) bool {
|
|
||||||
if os == "windows" {
|
|
||||||
// FIXME: copy hideous logic from Go's
|
|
||||||
// src/path/filepath/path_windows.go into somewhere where we can
|
|
||||||
// put 3-clause BSD licensed code.
|
|
||||||
return windowsAbs.MatchString(path)
|
|
||||||
}
|
|
||||||
sep := Separator(os)
|
|
||||||
|
|
||||||
// POSIX has [1]:
|
|
||||||
//
|
|
||||||
// > If a pathname begins with two successive <slash> characters,
|
|
||||||
// > the first component following the leading <slash> characters
|
|
||||||
// > may be interpreted in an implementation-defined manner,
|
|
||||||
// > although more than two leading <slash> characters shall be
|
|
||||||
// > treated as a single <slash> character.
|
|
||||||
//
|
|
||||||
// And Boost treats // as non-absolute [2], but Linux [3,4], Python
|
|
||||||
// [5] and Go [6] all treat // as absolute.
|
|
||||||
//
|
|
||||||
// [1]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
|
|
||||||
// [2]: https://github.com/boostorg/filesystem/blob/boost-1.64.0/test/path_test.cpp#L861
|
|
||||||
// [3]: http://man7.org/linux/man-pages/man7/path_resolution.7.html
|
|
||||||
// [4]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/path-lookup.md?h=v4.12#n41
|
|
||||||
// [5]: https://github.com/python/cpython/blob/v3.6.1/Lib/posixpath.py#L64-L66
|
|
||||||
// [6]: https://go.googlesource.com/go/+/go1.8.3/src/path/path.go#199
|
|
||||||
return strings.HasPrefix(path, string(sep))
|
|
||||||
}
|
|
32
vendor/github.com/opencontainers/runtime-tools/filepath/ancestor.go
generated
vendored
32
vendor/github.com/opencontainers/runtime-tools/filepath/ancestor.go
generated
vendored
@ -1,32 +0,0 @@
|
|||||||
package filepath
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsAncestor returns true when pathB is an strict ancestor of pathA,
|
|
||||||
// and false where the paths are equal or pathB is outside of pathA.
|
|
||||||
// Paths that are not absolute will be made absolute with Abs.
|
|
||||||
func IsAncestor(os, pathA, pathB, cwd string) (_ bool, err error) {
|
|
||||||
if pathA == pathB {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pathA, err = Abs(os, pathA, cwd)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
pathB, err = Abs(os, pathB, cwd)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
sep := Separator(os)
|
|
||||||
if !strings.HasSuffix(pathA, string(sep)) {
|
|
||||||
pathA = fmt.Sprintf("%s%c", pathA, sep)
|
|
||||||
}
|
|
||||||
if pathA == pathB {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return strings.HasPrefix(pathB, pathA), nil
|
|
||||||
}
|
|
74
vendor/github.com/opencontainers/runtime-tools/filepath/clean.go
generated
vendored
74
vendor/github.com/opencontainers/runtime-tools/filepath/clean.go
generated
vendored
@ -1,74 +0,0 @@
|
|||||||
package filepath
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Clean is an explicit-OS version of path/filepath's Clean.
|
|
||||||
func Clean(os, path string) string {
|
|
||||||
abs := IsAbs(os, path)
|
|
||||||
sep := Separator(os)
|
|
||||||
elements := strings.Split(path, string(sep))
|
|
||||||
|
|
||||||
// Replace multiple Separator elements with a single one.
|
|
||||||
for i := 0; i < len(elements); i++ {
|
|
||||||
if len(elements[i]) == 0 {
|
|
||||||
elements = append(elements[:i], elements[i+1:]...)
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eliminate each . path name element (the current directory).
|
|
||||||
for i := 0; i < len(elements); i++ {
|
|
||||||
if elements[i] == "." && len(elements) > 1 {
|
|
||||||
elements = append(elements[:i], elements[i+1:]...)
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eliminate each inner .. path name element (the parent directory)
|
|
||||||
// along with the non-.. element that precedes it.
|
|
||||||
for i := 1; i < len(elements); i++ {
|
|
||||||
if i == 1 && abs && sep == '\\' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if i > 0 && elements[i] == ".." {
|
|
||||||
elements = append(elements[:i-1], elements[i+1:]...)
|
|
||||||
i -= 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eliminate .. elements that begin a rooted path:
|
|
||||||
// that is, replace "/.." by "/" at the beginning of a path,
|
|
||||||
// assuming Separator is '/'.
|
|
||||||
offset := 0
|
|
||||||
if sep == '\\' {
|
|
||||||
offset = 1
|
|
||||||
}
|
|
||||||
if abs {
|
|
||||||
for len(elements) > offset && elements[offset] == ".." {
|
|
||||||
elements = append(elements[:offset], elements[offset+1:]...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cleaned := strings.Join(elements, string(sep))
|
|
||||||
if abs {
|
|
||||||
if sep == '/' {
|
|
||||||
cleaned = fmt.Sprintf("%c%s", sep, cleaned)
|
|
||||||
} else if len(elements) == 1 {
|
|
||||||
cleaned = fmt.Sprintf("%s%c", cleaned, sep)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the result of this process is an empty string, Clean returns
|
|
||||||
// the string ".".
|
|
||||||
if len(cleaned) == 0 {
|
|
||||||
cleaned = "."
|
|
||||||
}
|
|
||||||
|
|
||||||
if cleaned == path {
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
return Clean(os, cleaned)
|
|
||||||
}
|
|
6
vendor/github.com/opencontainers/runtime-tools/filepath/doc.go
generated
vendored
6
vendor/github.com/opencontainers/runtime-tools/filepath/doc.go
generated
vendored
@ -1,6 +0,0 @@
|
|||||||
// Package filepath implements Go's filepath package with explicit
|
|
||||||
// operating systems (and for some functions and explicit working
|
|
||||||
// directory). This allows tools built for one OS to operate on paths
|
|
||||||
// targeting another OS. For example, a Linux build can determine
|
|
||||||
// whether a path is absolute on Linux or on Windows.
|
|
||||||
package filepath
|
|
9
vendor/github.com/opencontainers/runtime-tools/filepath/join.go
generated
vendored
9
vendor/github.com/opencontainers/runtime-tools/filepath/join.go
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
package filepath
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
// Join is an explicit-OS version of path/filepath's Join.
|
|
||||||
func Join(os string, elem ...string) string {
|
|
||||||
sep := Separator(os)
|
|
||||||
return Clean(os, strings.Join(elem, string(sep)))
|
|
||||||
}
|
|
9
vendor/github.com/opencontainers/runtime-tools/filepath/separator.go
generated
vendored
9
vendor/github.com/opencontainers/runtime-tools/filepath/separator.go
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
package filepath
|
|
||||||
|
|
||||||
// Separator is an explicit-OS version of path/filepath's Separator.
|
|
||||||
func Separator(os string) rune {
|
|
||||||
if os == "windows" {
|
|
||||||
return '\\'
|
|
||||||
}
|
|
||||||
return '/'
|
|
||||||
}
|
|
28
vendor/github.com/opencontainers/runtime-tools/generate/config.go
generated
vendored
28
vendor/github.com/opencontainers/runtime-tools/generate/config.go
generated
vendored
@ -123,6 +123,13 @@ func (g *Generator) initConfigLinuxResourcesPids() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Generator) initConfigLinuxResourcesUnified() {
|
||||||
|
g.initConfigLinuxResources()
|
||||||
|
if g.Config.Linux.Resources.Unified == nil {
|
||||||
|
g.Config.Linux.Resources.Unified = map[string]string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (g *Generator) initConfigSolaris() {
|
func (g *Generator) initConfigSolaris() {
|
||||||
g.initConfig()
|
g.initConfig()
|
||||||
if g.Config.Solaris == nil {
|
if g.Config.Solaris == nil {
|
||||||
@ -185,24 +192,3 @@ func (g *Generator) initConfigVM() {
|
|||||||
g.Config.VM = &rspec.VM{}
|
g.Config.VM = &rspec.VM{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Generator) initConfigVMHypervisor() {
|
|
||||||
g.initConfigVM()
|
|
||||||
if &g.Config.VM.Hypervisor == nil {
|
|
||||||
g.Config.VM.Hypervisor = rspec.VMHypervisor{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Generator) initConfigVMKernel() {
|
|
||||||
g.initConfigVM()
|
|
||||||
if &g.Config.VM.Kernel == nil {
|
|
||||||
g.Config.VM.Kernel = rspec.VMKernel{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Generator) initConfigVMImage() {
|
|
||||||
g.initConfigVM()
|
|
||||||
if &g.Config.VM.Image == nil {
|
|
||||||
g.Config.VM.Image = rspec.VMImage{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
124
vendor/github.com/opencontainers/runtime-tools/generate/generate.go
generated
vendored
124
vendor/github.com/opencontainers/runtime-tools/generate/generate.go
generated
vendored
@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/opencontainers/runtime-tools/generate/seccomp"
|
"github.com/opencontainers/runtime-tools/generate/seccomp"
|
||||||
"github.com/opencontainers/runtime-tools/validate"
|
capsCheck "github.com/opencontainers/runtime-tools/validate/capabilities"
|
||||||
"github.com/syndtr/gocapability/capability"
|
"github.com/syndtr/gocapability/capability"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ type ExportOptions struct {
|
|||||||
// New creates a configuration Generator with the default
|
// New creates a configuration Generator with the default
|
||||||
// configuration for the target operating system.
|
// configuration for the target operating system.
|
||||||
func New(os string) (generator Generator, err error) {
|
func New(os string) (generator Generator, err error) {
|
||||||
if os != "linux" && os != "solaris" && os != "windows" {
|
if os != "linux" && os != "solaris" && os != "windows" && os != "freebsd" {
|
||||||
return generator, fmt.Errorf("no defaults configured for %s", os)
|
return generator, fmt.Errorf("no defaults configured for %s", os)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ func New(os string) (generator Generator, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if os == "linux" || os == "solaris" {
|
if os == "linux" || os == "solaris" || os == "freebsd" {
|
||||||
config.Process.User = rspec.User{}
|
config.Process.User = rspec.User{}
|
||||||
config.Process.Env = []string{
|
config.Process.Env = []string{
|
||||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||||
@ -182,7 +182,7 @@ func New(os string) (generator Generator, err error) {
|
|||||||
Destination: "/dev",
|
Destination: "/dev",
|
||||||
Type: "tmpfs",
|
Type: "tmpfs",
|
||||||
Source: "tmpfs",
|
Source: "tmpfs",
|
||||||
Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
|
Options: []string{"nosuid", "noexec", "strictatime", "mode=755", "size=65536k"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Destination: "/dev/pts",
|
Destination: "/dev/pts",
|
||||||
@ -237,6 +237,21 @@ func New(os string) (generator Generator, err error) {
|
|||||||
},
|
},
|
||||||
Seccomp: seccomp.DefaultProfile(&config),
|
Seccomp: seccomp.DefaultProfile(&config),
|
||||||
}
|
}
|
||||||
|
} else if os == "freebsd" {
|
||||||
|
config.Mounts = []rspec.Mount{
|
||||||
|
{
|
||||||
|
Destination: "/dev",
|
||||||
|
Type: "devfs",
|
||||||
|
Source: "devfs",
|
||||||
|
Options: []string{"ruleset=4"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Destination: "/dev/fd",
|
||||||
|
Type: "fdescfs",
|
||||||
|
Source: "fdesc",
|
||||||
|
Options: []string{},
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
envCache := map[string]int{}
|
envCache := map[string]int{}
|
||||||
@ -249,10 +264,6 @@ func New(os string) (generator Generator, err error) {
|
|||||||
|
|
||||||
// NewFromSpec creates a configuration Generator from a given
|
// NewFromSpec creates a configuration Generator from a given
|
||||||
// configuration.
|
// configuration.
|
||||||
//
|
|
||||||
// Deprecated: Replace with:
|
|
||||||
//
|
|
||||||
// generator := Generator{Config: config}
|
|
||||||
func NewFromSpec(config *rspec.Spec) Generator {
|
func NewFromSpec(config *rspec.Spec) Generator {
|
||||||
envCache := map[string]int{}
|
envCache := map[string]int{}
|
||||||
if config != nil && config.Process != nil {
|
if config != nil && config.Process != nil {
|
||||||
@ -444,6 +455,13 @@ func (g *Generator) SetProcessUsername(username string) {
|
|||||||
g.Config.Process.User.Username = username
|
g.Config.Process.User.Username = username
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetProcessUmask sets g.Config.Process.User.Umask.
|
||||||
|
func (g *Generator) SetProcessUmask(umask uint32) {
|
||||||
|
g.initConfigProcess()
|
||||||
|
u := umask
|
||||||
|
g.Config.Process.User.Umask = &u
|
||||||
|
}
|
||||||
|
|
||||||
// SetProcessGID sets g.Config.Process.User.GID.
|
// SetProcessGID sets g.Config.Process.User.GID.
|
||||||
func (g *Generator) SetProcessGID(gid uint32) {
|
func (g *Generator) SetProcessGID(gid uint32) {
|
||||||
g.initConfigProcess()
|
g.initConfigProcess()
|
||||||
@ -597,6 +615,12 @@ func (g *Generator) SetLinuxCgroupsPath(path string) {
|
|||||||
g.Config.Linux.CgroupsPath = path
|
g.Config.Linux.CgroupsPath = path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetLinuxIntelRdtClosID sets g.Config.Linux.IntelRdt.ClosID
|
||||||
|
func (g *Generator) SetLinuxIntelRdtClosID(clos string) {
|
||||||
|
g.initConfigLinuxIntelRdt()
|
||||||
|
g.Config.Linux.IntelRdt.ClosID = clos
|
||||||
|
}
|
||||||
|
|
||||||
// SetLinuxIntelRdtL3CacheSchema sets g.Config.Linux.IntelRdt.L3CacheSchema
|
// SetLinuxIntelRdtL3CacheSchema sets g.Config.Linux.IntelRdt.L3CacheSchema
|
||||||
func (g *Generator) SetLinuxIntelRdtL3CacheSchema(schema string) {
|
func (g *Generator) SetLinuxIntelRdtL3CacheSchema(schema string) {
|
||||||
g.initConfigLinuxIntelRdt()
|
g.initConfigLinuxIntelRdt()
|
||||||
@ -844,6 +868,28 @@ func (g *Generator) DropLinuxResourcesHugepageLimit(pageSize string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddLinuxResourcesUnified sets the g.Config.Linux.Resources.Unified
|
||||||
|
func (g *Generator) SetLinuxResourcesUnified(unified map[string]string) {
|
||||||
|
g.initConfigLinuxResourcesUnified()
|
||||||
|
for k, v := range unified {
|
||||||
|
g.Config.Linux.Resources.Unified[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLinuxResourcesUnified adds or updates the key-value pair from g.Config.Linux.Resources.Unified
|
||||||
|
func (g *Generator) AddLinuxResourcesUnified(key, val string) {
|
||||||
|
g.initConfigLinuxResourcesUnified()
|
||||||
|
g.Config.Linux.Resources.Unified[key] = val
|
||||||
|
}
|
||||||
|
|
||||||
|
// DropLinuxResourcesUnified drops a key-value pair from g.Config.Linux.Resources.Unified
|
||||||
|
func (g *Generator) DropLinuxResourcesUnified(key string) {
|
||||||
|
if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.Unified == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete(g.Config.Linux.Resources.Unified, key)
|
||||||
|
}
|
||||||
|
|
||||||
// SetLinuxResourcesMemoryLimit sets g.Config.Linux.Resources.Memory.Limit.
|
// SetLinuxResourcesMemoryLimit sets g.Config.Linux.Resources.Memory.Limit.
|
||||||
func (g *Generator) SetLinuxResourcesMemoryLimit(limit int64) {
|
func (g *Generator) SetLinuxResourcesMemoryLimit(limit int64) {
|
||||||
g.initConfigLinuxResourcesMemory()
|
g.initConfigLinuxResourcesMemory()
|
||||||
@ -1018,10 +1064,9 @@ func (g *Generator) ClearPreStartHooks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddPreStartHook add a prestart hook into g.Config.Hooks.Prestart.
|
// AddPreStartHook add a prestart hook into g.Config.Hooks.Prestart.
|
||||||
func (g *Generator) AddPreStartHook(preStartHook rspec.Hook) error {
|
func (g *Generator) AddPreStartHook(preStartHook rspec.Hook) {
|
||||||
g.initConfigHooks()
|
g.initConfigHooks()
|
||||||
g.Config.Hooks.Prestart = append(g.Config.Hooks.Prestart, preStartHook)
|
g.Config.Hooks.Prestart = append(g.Config.Hooks.Prestart, preStartHook)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearPostStopHooks clear g.Config.Hooks.Poststop.
|
// ClearPostStopHooks clear g.Config.Hooks.Poststop.
|
||||||
@ -1033,10 +1078,9 @@ func (g *Generator) ClearPostStopHooks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddPostStopHook adds a poststop hook into g.Config.Hooks.Poststop.
|
// AddPostStopHook adds a poststop hook into g.Config.Hooks.Poststop.
|
||||||
func (g *Generator) AddPostStopHook(postStopHook rspec.Hook) error {
|
func (g *Generator) AddPostStopHook(postStopHook rspec.Hook) {
|
||||||
g.initConfigHooks()
|
g.initConfigHooks()
|
||||||
g.Config.Hooks.Poststop = append(g.Config.Hooks.Poststop, postStopHook)
|
g.Config.Hooks.Poststop = append(g.Config.Hooks.Poststop, postStopHook)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearPostStartHooks clear g.Config.Hooks.Poststart.
|
// ClearPostStartHooks clear g.Config.Hooks.Poststart.
|
||||||
@ -1048,10 +1092,9 @@ func (g *Generator) ClearPostStartHooks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddPostStartHook adds a poststart hook into g.Config.Hooks.Poststart.
|
// AddPostStartHook adds a poststart hook into g.Config.Hooks.Poststart.
|
||||||
func (g *Generator) AddPostStartHook(postStartHook rspec.Hook) error {
|
func (g *Generator) AddPostStartHook(postStartHook rspec.Hook) {
|
||||||
g.initConfigHooks()
|
g.initConfigHooks()
|
||||||
g.Config.Hooks.Poststart = append(g.Config.Hooks.Poststart, postStartHook)
|
g.Config.Hooks.Poststart = append(g.Config.Hooks.Poststart, postStartHook)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddMount adds a mount into g.Config.Mounts.
|
// AddMount adds a mount into g.Config.Mounts.
|
||||||
@ -1093,7 +1136,7 @@ func (g *Generator) SetupPrivileged(privileged bool) {
|
|||||||
if privileged { // Add all capabilities in privileged mode.
|
if privileged { // Add all capabilities in privileged mode.
|
||||||
var finalCapList []string
|
var finalCapList []string
|
||||||
for _, cap := range capability.List() {
|
for _, cap := range capability.List() {
|
||||||
if g.HostSpecific && cap > validate.LastCap() {
|
if g.HostSpecific && cap > capsCheck.LastCap() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
finalCapList = append(finalCapList, fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())))
|
finalCapList = append(finalCapList, fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())))
|
||||||
@ -1127,7 +1170,7 @@ func (g *Generator) ClearProcessCapabilities() {
|
|||||||
// AddProcessCapability adds a process capability into all 5 capability sets.
|
// AddProcessCapability adds a process capability into all 5 capability sets.
|
||||||
func (g *Generator) AddProcessCapability(c string) error {
|
func (g *Generator) AddProcessCapability(c string) error {
|
||||||
cp := strings.ToUpper(c)
|
cp := strings.ToUpper(c)
|
||||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1190,7 +1233,7 @@ func (g *Generator) AddProcessCapability(c string) error {
|
|||||||
// AddProcessCapabilityAmbient adds a process capability into g.Config.Process.Capabilities.Ambient.
|
// AddProcessCapabilityAmbient adds a process capability into g.Config.Process.Capabilities.Ambient.
|
||||||
func (g *Generator) AddProcessCapabilityAmbient(c string) error {
|
func (g *Generator) AddProcessCapabilityAmbient(c string) error {
|
||||||
cp := strings.ToUpper(c)
|
cp := strings.ToUpper(c)
|
||||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1214,7 +1257,7 @@ func (g *Generator) AddProcessCapabilityAmbient(c string) error {
|
|||||||
// AddProcessCapabilityBounding adds a process capability into g.Config.Process.Capabilities.Bounding.
|
// AddProcessCapabilityBounding adds a process capability into g.Config.Process.Capabilities.Bounding.
|
||||||
func (g *Generator) AddProcessCapabilityBounding(c string) error {
|
func (g *Generator) AddProcessCapabilityBounding(c string) error {
|
||||||
cp := strings.ToUpper(c)
|
cp := strings.ToUpper(c)
|
||||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1237,7 +1280,7 @@ func (g *Generator) AddProcessCapabilityBounding(c string) error {
|
|||||||
// AddProcessCapabilityEffective adds a process capability into g.Config.Process.Capabilities.Effective.
|
// AddProcessCapabilityEffective adds a process capability into g.Config.Process.Capabilities.Effective.
|
||||||
func (g *Generator) AddProcessCapabilityEffective(c string) error {
|
func (g *Generator) AddProcessCapabilityEffective(c string) error {
|
||||||
cp := strings.ToUpper(c)
|
cp := strings.ToUpper(c)
|
||||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1260,7 +1303,7 @@ func (g *Generator) AddProcessCapabilityEffective(c string) error {
|
|||||||
// AddProcessCapabilityInheritable adds a process capability into g.Config.Process.Capabilities.Inheritable.
|
// AddProcessCapabilityInheritable adds a process capability into g.Config.Process.Capabilities.Inheritable.
|
||||||
func (g *Generator) AddProcessCapabilityInheritable(c string) error {
|
func (g *Generator) AddProcessCapabilityInheritable(c string) error {
|
||||||
cp := strings.ToUpper(c)
|
cp := strings.ToUpper(c)
|
||||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1283,7 +1326,7 @@ func (g *Generator) AddProcessCapabilityInheritable(c string) error {
|
|||||||
// AddProcessCapabilityPermitted adds a process capability into g.Config.Process.Capabilities.Permitted.
|
// AddProcessCapabilityPermitted adds a process capability into g.Config.Process.Capabilities.Permitted.
|
||||||
func (g *Generator) AddProcessCapabilityPermitted(c string) error {
|
func (g *Generator) AddProcessCapabilityPermitted(c string) error {
|
||||||
cp := strings.ToUpper(c)
|
cp := strings.ToUpper(c)
|
||||||
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
|
if err := capsCheck.CapValid(cp, g.HostSpecific); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1336,7 +1379,7 @@ func (g *Generator) DropProcessCapability(c string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return validate.CapValid(cp, false)
|
return capsCheck.CapValid(cp, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropProcessCapabilityAmbient drops a process capability from g.Config.Process.Capabilities.Ambient.
|
// DropProcessCapabilityAmbient drops a process capability from g.Config.Process.Capabilities.Ambient.
|
||||||
@ -1352,7 +1395,7 @@ func (g *Generator) DropProcessCapabilityAmbient(c string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return validate.CapValid(cp, false)
|
return capsCheck.CapValid(cp, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropProcessCapabilityBounding drops a process capability from g.Config.Process.Capabilities.Bounding.
|
// DropProcessCapabilityBounding drops a process capability from g.Config.Process.Capabilities.Bounding.
|
||||||
@ -1368,7 +1411,7 @@ func (g *Generator) DropProcessCapabilityBounding(c string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return validate.CapValid(cp, false)
|
return capsCheck.CapValid(cp, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropProcessCapabilityEffective drops a process capability from g.Config.Process.Capabilities.Effective.
|
// DropProcessCapabilityEffective drops a process capability from g.Config.Process.Capabilities.Effective.
|
||||||
@ -1384,7 +1427,7 @@ func (g *Generator) DropProcessCapabilityEffective(c string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return validate.CapValid(cp, false)
|
return capsCheck.CapValid(cp, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropProcessCapabilityInheritable drops a process capability from g.Config.Process.Capabilities.Inheritable.
|
// DropProcessCapabilityInheritable drops a process capability from g.Config.Process.Capabilities.Inheritable.
|
||||||
@ -1400,7 +1443,7 @@ func (g *Generator) DropProcessCapabilityInheritable(c string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return validate.CapValid(cp, false)
|
return capsCheck.CapValid(cp, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropProcessCapabilityPermitted drops a process capability from g.Config.Process.Capabilities.Permitted.
|
// DropProcessCapabilityPermitted drops a process capability from g.Config.Process.Capabilities.Permitted.
|
||||||
@ -1416,7 +1459,7 @@ func (g *Generator) DropProcessCapabilityPermitted(c string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return validate.CapValid(cp, false)
|
return capsCheck.CapValid(cp, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapStrToNamespace(ns string, path string) (rspec.LinuxNamespace, error) {
|
func mapStrToNamespace(ns string, path string) (rspec.LinuxNamespace, error) {
|
||||||
@ -1495,9 +1538,6 @@ func (g *Generator) AddDevice(device rspec.LinuxDevice) {
|
|||||||
g.Config.Linux.Devices[i] = device
|
g.Config.Linux.Devices[i] = device
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if dev.Type == device.Type && dev.Major == device.Major && dev.Minor == device.Minor {
|
|
||||||
fmt.Fprintln(os.Stderr, "WARNING: The same type, major and minor should not be used for multiple devices.")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g.Config.Linux.Devices = append(g.Config.Linux.Devices, device)
|
g.Config.Linux.Devices = append(g.Config.Linux.Devices, device)
|
||||||
@ -1556,12 +1596,8 @@ func (g *Generator) RemoveLinuxResourcesDevice(allow bool, devType string, major
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// strPtr returns the pointer pointing to the string s.
|
|
||||||
func strPtr(s string) *string { return &s }
|
|
||||||
|
|
||||||
// SetSyscallAction adds rules for syscalls with the specified action
|
// SetSyscallAction adds rules for syscalls with the specified action
|
||||||
func (g *Generator) SetSyscallAction(arguments seccomp.SyscallOpts) error {
|
func (g *Generator) SetSyscallAction(arguments seccomp.SyscallOpts) error {
|
||||||
g.initConfigLinuxSeccomp()
|
g.initConfigLinuxSeccomp()
|
||||||
@ -1581,6 +1617,12 @@ func (g *Generator) SetDefaultSeccompActionForce(action string) error {
|
|||||||
return seccomp.ParseDefaultActionForce(action, g.Config.Linux.Seccomp)
|
return seccomp.ParseDefaultActionForce(action, g.Config.Linux.Seccomp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDomainName sets g.Config.Domainname
|
||||||
|
func (g *Generator) SetDomainName(domain string) {
|
||||||
|
g.initConfig()
|
||||||
|
g.Config.Domainname = domain
|
||||||
|
}
|
||||||
|
|
||||||
// SetSeccompArchitecture sets the supported seccomp architectures
|
// SetSeccompArchitecture sets the supported seccomp architectures
|
||||||
func (g *Generator) SetSeccompArchitecture(architecture string) error {
|
func (g *Generator) SetSeccompArchitecture(architecture string) error {
|
||||||
g.initConfigLinuxSeccomp()
|
g.initConfigLinuxSeccomp()
|
||||||
@ -1687,14 +1729,14 @@ func (g *Generator) SetVMHypervisorPath(path string) error {
|
|||||||
if !strings.HasPrefix(path, "/") {
|
if !strings.HasPrefix(path, "/") {
|
||||||
return fmt.Errorf("hypervisorPath %v is not an absolute path", path)
|
return fmt.Errorf("hypervisorPath %v is not an absolute path", path)
|
||||||
}
|
}
|
||||||
g.initConfigVMHypervisor()
|
g.initConfigVM()
|
||||||
g.Config.VM.Hypervisor.Path = path
|
g.Config.VM.Hypervisor.Path = path
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVMHypervisorParameters sets g.Config.VM.Hypervisor.Parameters
|
// SetVMHypervisorParameters sets g.Config.VM.Hypervisor.Parameters
|
||||||
func (g *Generator) SetVMHypervisorParameters(parameters []string) {
|
func (g *Generator) SetVMHypervisorParameters(parameters []string) {
|
||||||
g.initConfigVMHypervisor()
|
g.initConfigVM()
|
||||||
g.Config.VM.Hypervisor.Parameters = parameters
|
g.Config.VM.Hypervisor.Parameters = parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1703,14 +1745,14 @@ func (g *Generator) SetVMKernelPath(path string) error {
|
|||||||
if !strings.HasPrefix(path, "/") {
|
if !strings.HasPrefix(path, "/") {
|
||||||
return fmt.Errorf("kernelPath %v is not an absolute path", path)
|
return fmt.Errorf("kernelPath %v is not an absolute path", path)
|
||||||
}
|
}
|
||||||
g.initConfigVMKernel()
|
g.initConfigVM()
|
||||||
g.Config.VM.Kernel.Path = path
|
g.Config.VM.Kernel.Path = path
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVMKernelParameters sets g.Config.VM.Kernel.Parameters
|
// SetVMKernelParameters sets g.Config.VM.Kernel.Parameters
|
||||||
func (g *Generator) SetVMKernelParameters(parameters []string) {
|
func (g *Generator) SetVMKernelParameters(parameters []string) {
|
||||||
g.initConfigVMKernel()
|
g.initConfigVM()
|
||||||
g.Config.VM.Kernel.Parameters = parameters
|
g.Config.VM.Kernel.Parameters = parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1719,7 +1761,7 @@ func (g *Generator) SetVMKernelInitRD(initrd string) error {
|
|||||||
if !strings.HasPrefix(initrd, "/") {
|
if !strings.HasPrefix(initrd, "/") {
|
||||||
return fmt.Errorf("kernelInitrd %v is not an absolute path", initrd)
|
return fmt.Errorf("kernelInitrd %v is not an absolute path", initrd)
|
||||||
}
|
}
|
||||||
g.initConfigVMKernel()
|
g.initConfigVM()
|
||||||
g.Config.VM.Kernel.InitRD = initrd
|
g.Config.VM.Kernel.InitRD = initrd
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1729,7 +1771,7 @@ func (g *Generator) SetVMImagePath(path string) error {
|
|||||||
if !strings.HasPrefix(path, "/") {
|
if !strings.HasPrefix(path, "/") {
|
||||||
return fmt.Errorf("imagePath %v is not an absolute path", path)
|
return fmt.Errorf("imagePath %v is not an absolute path", path)
|
||||||
}
|
}
|
||||||
g.initConfigVMImage()
|
g.initConfigVM()
|
||||||
g.Config.VM.Image.Path = path
|
g.Config.VM.Image.Path = path
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1745,7 +1787,7 @@ func (g *Generator) SetVMImageFormat(format string) error {
|
|||||||
default:
|
default:
|
||||||
return fmt.Errorf("Commonly supported formats are: raw, qcow2, vdi, vmdk, vhd")
|
return fmt.Errorf("Commonly supported formats are: raw, qcow2, vdi, vmdk, vhd")
|
||||||
}
|
}
|
||||||
g.initConfigVMImage()
|
g.initConfigVM()
|
||||||
g.Config.VM.Image.Format = format
|
g.Config.VM.Image.Format = format
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
5
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go
generated
vendored
5
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go
generated
vendored
@ -4,9 +4,4 @@ const (
|
|||||||
seccompOverwrite = "overwrite"
|
seccompOverwrite = "overwrite"
|
||||||
seccompAppend = "append"
|
seccompAppend = "append"
|
||||||
nothing = "nothing"
|
nothing = "nothing"
|
||||||
kill = "kill"
|
|
||||||
trap = "trap"
|
|
||||||
trace = "trace"
|
|
||||||
allow = "allow"
|
|
||||||
errno = "errno"
|
|
||||||
)
|
)
|
||||||
|
32
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go
generated
vendored
32
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go
generated
vendored
@ -151,6 +151,9 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
|
|||||||
"io_submit",
|
"io_submit",
|
||||||
"ipc",
|
"ipc",
|
||||||
"kill",
|
"kill",
|
||||||
|
"landlock_add_rule",
|
||||||
|
"landlock_create_ruleset",
|
||||||
|
"landlock_restrict_self",
|
||||||
"lchown",
|
"lchown",
|
||||||
"lchown32",
|
"lchown32",
|
||||||
"lgetxattr",
|
"lgetxattr",
|
||||||
@ -303,6 +306,7 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
|
|||||||
"stat64",
|
"stat64",
|
||||||
"statfs",
|
"statfs",
|
||||||
"statfs64",
|
"statfs64",
|
||||||
|
"statx",
|
||||||
"symlink",
|
"symlink",
|
||||||
"symlinkat",
|
"symlinkat",
|
||||||
"sync",
|
"sync",
|
||||||
@ -353,11 +357,23 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
|
|||||||
Value: 0x0,
|
Value: 0x0,
|
||||||
Op: rspec.OpEqualTo,
|
Op: rspec.OpEqualTo,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"personality"},
|
||||||
|
Action: rspec.ActAllow,
|
||||||
|
Args: []rspec.LinuxSeccompArg{
|
||||||
{
|
{
|
||||||
Index: 0,
|
Index: 0,
|
||||||
Value: 0x0008,
|
Value: 0x0008,
|
||||||
Op: rspec.OpEqualTo,
|
Op: rspec.OpEqualTo,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"personality"},
|
||||||
|
Action: rspec.ActAllow,
|
||||||
|
Args: []rspec.LinuxSeccompArg{
|
||||||
{
|
{
|
||||||
Index: 0,
|
Index: 0,
|
||||||
Value: 0xffffffff,
|
Value: 0xffffffff,
|
||||||
@ -512,7 +528,7 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
|
|||||||
Args: []rspec.LinuxSeccompArg{
|
Args: []rspec.LinuxSeccompArg{
|
||||||
{
|
{
|
||||||
Index: sysCloneFlagsIndex,
|
Index: sysCloneFlagsIndex,
|
||||||
Value: CloneNewNS | CloneNewUTS | CloneNewIPC | CloneNewUser | CloneNewPID | CloneNewNet,
|
Value: CloneNewNS | CloneNewUTS | CloneNewIPC | CloneNewUser | CloneNewPID | CloneNewNet | CloneNewCgroup,
|
||||||
ValueTwo: 0,
|
ValueTwo: 0,
|
||||||
Op: rspec.OpMaskedEqual,
|
Op: rspec.OpMaskedEqual,
|
||||||
},
|
},
|
||||||
@ -566,6 +582,20 @@ func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp {
|
|||||||
},
|
},
|
||||||
}...)
|
}...)
|
||||||
/* Flags parameter of the clone syscall is the 2nd on s390 */
|
/* Flags parameter of the clone syscall is the 2nd on s390 */
|
||||||
|
syscalls = append(syscalls, []rspec.LinuxSyscall{
|
||||||
|
{
|
||||||
|
Names: []string{"clone"},
|
||||||
|
Action: rspec.ActAllow,
|
||||||
|
Args: []rspec.LinuxSeccompArg{
|
||||||
|
{
|
||||||
|
Index: 1,
|
||||||
|
Value: 2080505856,
|
||||||
|
ValueTwo: 0,
|
||||||
|
Op: rspec.OpMaskedEqual,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &rspec.LinuxSeccomp{
|
return &rspec.LinuxSeccomp{
|
||||||
|
16
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go
generated
vendored
16
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go
generated
vendored
@ -1,15 +1,17 @@
|
|||||||
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package seccomp
|
package seccomp
|
||||||
|
|
||||||
import "syscall"
|
import "golang.org/x/sys/unix"
|
||||||
|
|
||||||
// System values passed through on linux
|
// System values passed through on linux
|
||||||
const (
|
const (
|
||||||
CloneNewIPC = syscall.CLONE_NEWIPC
|
CloneNewIPC = unix.CLONE_NEWIPC
|
||||||
CloneNewNet = syscall.CLONE_NEWNET
|
CloneNewNet = unix.CLONE_NEWNET
|
||||||
CloneNewNS = syscall.CLONE_NEWNS
|
CloneNewNS = unix.CLONE_NEWNS
|
||||||
CloneNewPID = syscall.CLONE_NEWPID
|
CloneNewPID = unix.CLONE_NEWPID
|
||||||
CloneNewUser = syscall.CLONE_NEWUSER
|
CloneNewUser = unix.CLONE_NEWUSER
|
||||||
CloneNewUTS = syscall.CLONE_NEWUTS
|
CloneNewUTS = unix.CLONE_NEWUTS
|
||||||
|
CloneNewCgroup = unix.CLONE_NEWCGROUP
|
||||||
)
|
)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !linux
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package seccomp
|
package seccomp
|
||||||
|
16
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go
generated
vendored
16
vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go
generated
vendored
@ -92,22 +92,6 @@ func identical(config1, config2 *rspec.LinuxSyscall) bool {
|
|||||||
return reflect.DeepEqual(config1, config2)
|
return reflect.DeepEqual(config1, config2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func identicalExceptAction(config1, config2 *rspec.LinuxSyscall) bool {
|
|
||||||
samename := sameName(config1, config2)
|
|
||||||
sameAction := sameAction(config1, config2)
|
|
||||||
sameArgs := sameArgs(config1, config2)
|
|
||||||
|
|
||||||
return samename && !sameAction && sameArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
func identicalExceptArgs(config1, config2 *rspec.LinuxSyscall) bool {
|
|
||||||
samename := sameName(config1, config2)
|
|
||||||
sameAction := sameAction(config1, config2)
|
|
||||||
sameArgs := sameArgs(config1, config2)
|
|
||||||
|
|
||||||
return samename && sameAction && !sameArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
func sameName(config1, config2 *rspec.LinuxSyscall) bool {
|
func sameName(config1, config2 *rspec.LinuxSyscall) bool {
|
||||||
return reflect.DeepEqual(config1.Names, config2.Names)
|
return reflect.DeepEqual(config1.Names, config2.Names)
|
||||||
}
|
}
|
||||||
|
29
vendor/github.com/opencontainers/runtime-tools/specerror/bundle.go
generated
vendored
29
vendor/github.com/opencontainers/runtime-tools/specerror/bundle.go
generated
vendored
@ -1,29 +0,0 @@
|
|||||||
package specerror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
rfc2119 "github.com/opencontainers/runtime-tools/error"
|
|
||||||
)
|
|
||||||
|
|
||||||
// define error codes
|
|
||||||
const (
|
|
||||||
// ConfigInRootBundleDir represents "This REQUIRED file MUST reside in the root of the bundle directory"
|
|
||||||
ConfigInRootBundleDir Code = 0xa001 + iota
|
|
||||||
// ConfigConstName represents "This REQUIRED file MUST be named `config.json`."
|
|
||||||
ConfigConstName
|
|
||||||
// ArtifactsInSingleDir represents "When supplied, while these artifacts MUST all be present in a single directory on the local filesystem, that directory itself is not part of the bundle."
|
|
||||||
ArtifactsInSingleDir
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
containerFormatRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "bundle.md#container-format"), nil
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
register(ConfigInRootBundleDir, rfc2119.Must, containerFormatRef)
|
|
||||||
register(ConfigConstName, rfc2119.Must, containerFormatRef)
|
|
||||||
register(ArtifactsInSingleDir, rfc2119.Must, containerFormatRef)
|
|
||||||
}
|
|
134
vendor/github.com/opencontainers/runtime-tools/specerror/config-linux.go
generated
vendored
134
vendor/github.com/opencontainers/runtime-tools/specerror/config-linux.go
generated
vendored
@ -1,134 +0,0 @@
|
|||||||
package specerror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
rfc2119 "github.com/opencontainers/runtime-tools/error"
|
|
||||||
)
|
|
||||||
|
|
||||||
// define error codes
|
|
||||||
const (
|
|
||||||
// DefaultFilesystems represents "The following filesystems SHOULD be made available in each container's filesystem:"
|
|
||||||
DefaultFilesystems Code = 0xc001 + iota
|
|
||||||
// NSPathAbs represents "This value MUST be an absolute path in the runtime mount namespace."
|
|
||||||
NSPathAbs
|
|
||||||
// NSProcInPath represents "The runtime MUST place the container process in the namespace associated with that `path`."
|
|
||||||
NSProcInPath
|
|
||||||
// NSPathMatchTypeError represents "The runtime MUST generate an error if `path` is not associated with a namespace of type `type`."
|
|
||||||
NSPathMatchTypeError
|
|
||||||
// NSNewNSWithoutPath represents "If `path` is not specified, the runtime MUST create a new container namespace of type `type`."
|
|
||||||
NSNewNSWithoutPath
|
|
||||||
// NSInheritWithoutType represents "If a namespace type is not specified in the `namespaces` array, the container MUST inherit the runtime namespace of that type."
|
|
||||||
NSInheritWithoutType
|
|
||||||
// NSErrorOnDup represents "If a `namespaces` field contains duplicated namespaces with same `type`, the runtime MUST generate an error."
|
|
||||||
NSErrorOnDup
|
|
||||||
// UserNSMapOwnershipRO represents "The runtime SHOULD NOT modify the ownership of referenced filesystems to realize the mapping."
|
|
||||||
UserNSMapOwnershipRO
|
|
||||||
// DevicesAvailable represents "devices (array of objects, OPTIONAL) lists devices that MUST be available in the container."
|
|
||||||
DevicesAvailable
|
|
||||||
// DevicesFileNotMatch represents "If a file already exists at `path` that does not match the requested device, the runtime MUST generate an error."
|
|
||||||
DevicesFileNotMatch
|
|
||||||
// DevicesMajMinRequired represents "`major, minor` (int64, REQUIRED unless `type` is `p`) - major, minor numbers for the device."
|
|
||||||
DevicesMajMinRequired
|
|
||||||
// DevicesErrorOnDup represents "The same `type`, `major` and `minor` SHOULD NOT be used for multiple devices."
|
|
||||||
DevicesErrorOnDup
|
|
||||||
// DefaultDevices represents "In addition to any devices configured with this setting, the runtime MUST also supply default devices."
|
|
||||||
DefaultDevices
|
|
||||||
// CgroupsPathAbsOrRel represents "The value of `cgroupsPath` MUST be either an absolute path or a relative path."
|
|
||||||
CgroupsPathAbsOrRel
|
|
||||||
// CgroupsAbsPathRelToMount represents "In the case of an absolute path (starting with `/`), the runtime MUST take the path to be relative to the cgroups mount point."
|
|
||||||
CgroupsAbsPathRelToMount
|
|
||||||
// CgroupsPathAttach represents "If the value is specified, the runtime MUST consistently attach to the same place in the cgroups hierarchy given the same value of `cgroupsPath`."
|
|
||||||
CgroupsPathAttach
|
|
||||||
// CgroupsPathError represents "Runtimes MAY consider certain `cgroupsPath` values to be invalid, and MUST generate an error if this is the case."
|
|
||||||
CgroupsPathError
|
|
||||||
// DevicesApplyInOrder represents "The runtime MUST apply entries in the listed order."
|
|
||||||
DevicesApplyInOrder
|
|
||||||
// BlkIOWeightOrLeafWeightExist represents "You MUST specify at least one of `weight` or `leafWeight` in a given entry, and MAY specify both."
|
|
||||||
BlkIOWeightOrLeafWeightExist
|
|
||||||
// IntelRdtPIDWrite represents "If `intelRdt` is set, the runtime MUST write the container process ID to the `<container-id>/tasks` file in a mounted `resctrl` pseudo-filesystem, using the container ID from `start` and creating the `container-id` directory if necessary."
|
|
||||||
IntelRdtPIDWrite
|
|
||||||
// IntelRdtNoMountedResctrlError represents "If no mounted `resctrl` pseudo-filesystem is available in the runtime mount namespace, the runtime MUST generate an error."
|
|
||||||
IntelRdtNoMountedResctrlError
|
|
||||||
// NotManipResctrlWithoutIntelRdt represents "If `intelRdt` is not set, the runtime MUST NOT manipulate any `resctrl` pseudo-filesystems."
|
|
||||||
NotManipResctrlWithoutIntelRdt
|
|
||||||
// IntelRdtL3CacheSchemaWrite represents "If `l3CacheSchema` is set, runtimes MUST write the value to the `schemata` file in the `<container-id>` directory discussed in `intelRdt`."
|
|
||||||
IntelRdtL3CacheSchemaWrite
|
|
||||||
// IntelRdtL3CacheSchemaNotWrite represents "If `l3CacheSchema` is not set, runtimes MUST NOT write to `schemata` files in any `resctrl` pseudo-filesystems."
|
|
||||||
IntelRdtL3CacheSchemaNotWrite
|
|
||||||
// SeccSyscallsNamesRequired represents "`names` MUST contain at least one entry."
|
|
||||||
SeccSyscallsNamesRequired
|
|
||||||
// MaskedPathsAbs represents "maskedPaths (array of strings, OPTIONAL) will mask over the provided paths inside the container so that they cannot be read. The values MUST be absolute paths in the container namespace."
|
|
||||||
MaskedPathsAbs
|
|
||||||
// ReadonlyPathsAbs represents "readonlyPaths (array of strings, OPTIONAL) will set the provided paths as readonly inside the container. The values MUST be absolute paths in the container namespace."
|
|
||||||
ReadonlyPathsAbs
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
defaultFilesystemsRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#default-filesystems"), nil
|
|
||||||
}
|
|
||||||
namespacesRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#namespaces"), nil
|
|
||||||
}
|
|
||||||
userNamespaceMappingsRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#user-namespace-mappings"), nil
|
|
||||||
}
|
|
||||||
devicesRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#devices"), nil
|
|
||||||
}
|
|
||||||
defaultDevicesRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#default-devices"), nil
|
|
||||||
}
|
|
||||||
cgroupsPathRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#cgroups-path"), nil
|
|
||||||
}
|
|
||||||
deviceWhitelistRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#device-whitelist"), nil
|
|
||||||
}
|
|
||||||
blockIoRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#block-io"), nil
|
|
||||||
}
|
|
||||||
intelrdtRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#intelrdt"), nil
|
|
||||||
}
|
|
||||||
seccompRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#seccomp"), nil
|
|
||||||
}
|
|
||||||
maskedPathsRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#masked-paths"), nil
|
|
||||||
}
|
|
||||||
readonlyPathsRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#readonly-paths"), nil
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
register(DefaultFilesystems, rfc2119.Should, defaultFilesystemsRef)
|
|
||||||
register(NSPathAbs, rfc2119.Must, namespacesRef)
|
|
||||||
register(NSProcInPath, rfc2119.Must, namespacesRef)
|
|
||||||
register(NSPathMatchTypeError, rfc2119.Must, namespacesRef)
|
|
||||||
register(NSNewNSWithoutPath, rfc2119.Must, namespacesRef)
|
|
||||||
register(NSInheritWithoutType, rfc2119.Must, namespacesRef)
|
|
||||||
register(NSErrorOnDup, rfc2119.Must, namespacesRef)
|
|
||||||
register(UserNSMapOwnershipRO, rfc2119.Should, userNamespaceMappingsRef)
|
|
||||||
register(DevicesAvailable, rfc2119.Must, devicesRef)
|
|
||||||
register(DevicesFileNotMatch, rfc2119.Must, devicesRef)
|
|
||||||
register(DevicesMajMinRequired, rfc2119.Required, devicesRef)
|
|
||||||
register(DevicesErrorOnDup, rfc2119.Should, devicesRef)
|
|
||||||
register(DefaultDevices, rfc2119.Must, defaultDevicesRef)
|
|
||||||
register(CgroupsPathAbsOrRel, rfc2119.Must, cgroupsPathRef)
|
|
||||||
register(CgroupsAbsPathRelToMount, rfc2119.Must, cgroupsPathRef)
|
|
||||||
register(CgroupsPathAttach, rfc2119.Must, cgroupsPathRef)
|
|
||||||
register(CgroupsPathError, rfc2119.Must, cgroupsPathRef)
|
|
||||||
register(DevicesApplyInOrder, rfc2119.Must, deviceWhitelistRef)
|
|
||||||
register(BlkIOWeightOrLeafWeightExist, rfc2119.Must, blockIoRef)
|
|
||||||
register(IntelRdtPIDWrite, rfc2119.Must, intelrdtRef)
|
|
||||||
register(IntelRdtNoMountedResctrlError, rfc2119.Must, intelrdtRef)
|
|
||||||
register(NotManipResctrlWithoutIntelRdt, rfc2119.Must, intelrdtRef)
|
|
||||||
register(IntelRdtL3CacheSchemaWrite, rfc2119.Must, intelrdtRef)
|
|
||||||
register(IntelRdtL3CacheSchemaNotWrite, rfc2119.Must, intelrdtRef)
|
|
||||||
register(SeccSyscallsNamesRequired, rfc2119.Must, seccompRef)
|
|
||||||
register(MaskedPathsAbs, rfc2119.Must, maskedPathsRef)
|
|
||||||
register(ReadonlyPathsAbs, rfc2119.Must, readonlyPathsRef)
|
|
||||||
}
|
|
32
vendor/github.com/opencontainers/runtime-tools/specerror/config-windows.go
generated
vendored
32
vendor/github.com/opencontainers/runtime-tools/specerror/config-windows.go
generated
vendored
@ -1,32 +0,0 @@
|
|||||||
package specerror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
rfc2119 "github.com/opencontainers/runtime-tools/error"
|
|
||||||
)
|
|
||||||
|
|
||||||
// define error codes
|
|
||||||
const (
|
|
||||||
// WindowsLayerFoldersRequired represents "`layerFolders` MUST contain at least one entry."
|
|
||||||
WindowsLayerFoldersRequired Code = 0xd001 + iota
|
|
||||||
// WindowsHyperVPresent represents "If present, the container MUST be run with Hyper-V isolation."
|
|
||||||
WindowsHyperVPresent
|
|
||||||
// WindowsHyperVOmit represents "If omitted, the container MUST be run as a Windows Server container."
|
|
||||||
WindowsHyperVOmit
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
layerfoldersRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-windows.md#layerfolders"), nil
|
|
||||||
}
|
|
||||||
hypervRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config-windows.md#hyperv"), nil
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
register(WindowsLayerFoldersRequired, rfc2119.Must, layerfoldersRef)
|
|
||||||
register(WindowsHyperVPresent, rfc2119.Must, hypervRef)
|
|
||||||
register(WindowsHyperVOmit, rfc2119.Must, hypervRef)
|
|
||||||
}
|
|
188
vendor/github.com/opencontainers/runtime-tools/specerror/config.go
generated
vendored
188
vendor/github.com/opencontainers/runtime-tools/specerror/config.go
generated
vendored
@ -1,188 +0,0 @@
|
|||||||
package specerror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
rfc2119 "github.com/opencontainers/runtime-tools/error"
|
|
||||||
)
|
|
||||||
|
|
||||||
// define error codes
|
|
||||||
const (
|
|
||||||
// SpecVersionInSemVer represents "`ociVersion` (string, REQUIRED) MUST be in SemVer v2.0.0 format and specifies the version of the Open Container Initiative Runtime Specification with which the bundle complies."
|
|
||||||
SpecVersionInSemVer Code = 0xb001 + iota
|
|
||||||
// RootOnWindowsRequired represents "On Windows, for Windows Server Containers, this field is REQUIRED."
|
|
||||||
RootOnWindowsRequired
|
|
||||||
// RootOnHyperVNotSet represents "For Hyper-V Containers, this field MUST NOT be set."
|
|
||||||
RootOnHyperVNotSet
|
|
||||||
// RootOnNonWindowsRequired represents "On all other platforms, this field is REQUIRED."
|
|
||||||
RootOnNonWindowsRequired
|
|
||||||
// RootPathOnWindowsGUID represents "On Windows, `path` MUST be a volume GUID path."
|
|
||||||
RootPathOnWindowsGUID
|
|
||||||
// RootPathOnPosixConvention represents "The value SHOULD be the conventional `rootfs`."
|
|
||||||
RootPathOnPosixConvention
|
|
||||||
// RootPathExist represents "A directory MUST exist at the path declared by the field."
|
|
||||||
RootPathExist
|
|
||||||
// RootReadonlyImplement represents "`readonly` (bool, OPTIONAL) If true then the root filesystem MUST be read-only inside the container, defaults to false."
|
|
||||||
RootReadonlyImplement
|
|
||||||
// RootReadonlyOnWindowsFalse represents "* On Windows, this field MUST be omitted or false."
|
|
||||||
RootReadonlyOnWindowsFalse
|
|
||||||
// MountsInOrder represents "The runtime MUST mount entries in the listed order."
|
|
||||||
MountsInOrder
|
|
||||||
// MountsDestAbs represents "Destination of mount point: path inside container. This value MUST be an absolute path."
|
|
||||||
MountsDestAbs
|
|
||||||
// MountsDestOnWindowsNotNested represents "Windows: one mount destination MUST NOT be nested within another mount (e.g., c:\\foo and c:\\foo\\bar)."
|
|
||||||
MountsDestOnWindowsNotNested
|
|
||||||
// MountsOptionsOnWindowsROSupport represents "Windows: runtimes MUST support `ro`, mounting the filesystem read-only when `ro` is given."
|
|
||||||
MountsOptionsOnWindowsROSupport
|
|
||||||
// ProcRequiredAtStart represents "This property is REQUIRED when `start` is called."
|
|
||||||
ProcRequiredAtStart
|
|
||||||
// ProcConsoleSizeIgnore represents "Runtimes MUST ignore `consoleSize` if `terminal` is `false` or unset."
|
|
||||||
ProcConsoleSizeIgnore
|
|
||||||
// ProcCwdAbs represents "cwd (string, REQUIRED) is the working directory that will be set for the executable. This value MUST be an absolute path."
|
|
||||||
ProcCwdAbs
|
|
||||||
// ProcArgsOneEntryRequired represents "This specification extends the IEEE standard in that at least one entry is REQUIRED, and that entry is used with the same semantics as `execvp`'s *file*."
|
|
||||||
ProcArgsOneEntryRequired
|
|
||||||
// PosixProcRlimitsTypeGenError represents "The runtime MUST generate an error for any values which cannot be mapped to a relevant kernel interface."
|
|
||||||
PosixProcRlimitsTypeGenError
|
|
||||||
// PosixProcRlimitsTypeGet represents "For each entry in `rlimits`, a `getrlimit(3)` on `type` MUST succeed."
|
|
||||||
PosixProcRlimitsTypeGet
|
|
||||||
// PosixProcRlimitsTypeValueError represents "valid values are defined in the ... man page"
|
|
||||||
PosixProcRlimitsTypeValueError
|
|
||||||
// PosixProcRlimitsSoftMatchCur represents "`rlim.rlim_cur` MUST match the configured value."
|
|
||||||
PosixProcRlimitsSoftMatchCur
|
|
||||||
// PosixProcRlimitsHardMatchMax represents "`rlim.rlim_max` MUST match the configured value."
|
|
||||||
PosixProcRlimitsHardMatchMax
|
|
||||||
// PosixProcRlimitsErrorOnDup represents "If `rlimits` contains duplicated entries with same `type`, the runtime MUST generate an error."
|
|
||||||
PosixProcRlimitsErrorOnDup
|
|
||||||
// LinuxProcCapError represents "Any value which cannot be mapped to a relevant kernel interface MUST cause an error."
|
|
||||||
LinuxProcCapError
|
|
||||||
// LinuxProcOomScoreAdjSet represents "If `oomScoreAdj` is set, the runtime MUST set `oom_score_adj` to the given value."
|
|
||||||
LinuxProcOomScoreAdjSet
|
|
||||||
// LinuxProcOomScoreAdjNotSet represents "If `oomScoreAdj` is not set, the runtime MUST NOT change the value of `oom_score_adj`."
|
|
||||||
LinuxProcOomScoreAdjNotSet
|
|
||||||
// PlatformSpecConfOnWindowsSet represents "This MUST be set if the target platform of this spec is `windows`."
|
|
||||||
PlatformSpecConfOnWindowsSet
|
|
||||||
// PosixHooksPathAbs represents "This specification extends the IEEE standard in that `path` MUST be absolute."
|
|
||||||
PosixHooksPathAbs
|
|
||||||
// PosixHooksTimeoutPositive represents "If set, `timeout` MUST be greater than zero."
|
|
||||||
PosixHooksTimeoutPositive
|
|
||||||
// PosixHooksCalledInOrder represents "Hooks MUST be called in the listed order."
|
|
||||||
PosixHooksCalledInOrder
|
|
||||||
// PosixHooksStateToStdin represents "The state of the container MUST be passed to hooks over stdin so that they may do work appropriate to the current state of the container."
|
|
||||||
PosixHooksStateToStdin
|
|
||||||
// PrestartTiming represents "The pre-start hooks MUST be called after the `start` operation is called but before the user-specified program command is executed."
|
|
||||||
PrestartTiming
|
|
||||||
// PoststartTiming represents "The post-start hooks MUST be called after the user-specified process is executed but before the `start` operation returns."
|
|
||||||
PoststartTiming
|
|
||||||
// PoststopTiming represents "The post-stop hooks MUST be called after the container is deleted but before the `delete` operation returns."
|
|
||||||
PoststopTiming
|
|
||||||
// AnnotationsKeyValueMap represents "Annotations MUST be a key-value map."
|
|
||||||
AnnotationsKeyValueMap
|
|
||||||
// AnnotationsKeyString represents "Keys MUST be strings."
|
|
||||||
AnnotationsKeyString
|
|
||||||
// AnnotationsKeyRequired represents "Keys MUST NOT be an empty string."
|
|
||||||
AnnotationsKeyRequired
|
|
||||||
// AnnotationsKeyReversedDomain represents "Keys SHOULD be named using a reverse domain notation - e.g. `com.example.myKey`."
|
|
||||||
AnnotationsKeyReversedDomain
|
|
||||||
// AnnotationsKeyReservedNS represents "Keys using the `org.opencontainers` namespace are reserved and MUST NOT be used by subsequent specifications."
|
|
||||||
AnnotationsKeyReservedNS
|
|
||||||
// AnnotationsKeyIgnoreUnknown represents "Implementations that are reading/processing this configuration file MUST NOT generate an error if they encounter an unknown annotation key."
|
|
||||||
AnnotationsKeyIgnoreUnknown
|
|
||||||
// AnnotationsValueString represents "Values MUST be strings."
|
|
||||||
AnnotationsValueString
|
|
||||||
// ExtensibilityIgnoreUnknownProp represents "Runtimes that are reading or processing this configuration file MUST NOT generate an error if they encounter an unknown property."
|
|
||||||
ExtensibilityIgnoreUnknownProp
|
|
||||||
// ValidValues represents "Runtimes that are reading or processing this configuration file MUST generate an error when invalid or unsupported values are encountered."
|
|
||||||
ValidValues
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
specificationVersionRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#specification-version"), nil
|
|
||||||
}
|
|
||||||
rootRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#root"), nil
|
|
||||||
}
|
|
||||||
mountsRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#mounts"), nil
|
|
||||||
}
|
|
||||||
processRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#process"), nil
|
|
||||||
}
|
|
||||||
posixProcessRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#posix-process"), nil
|
|
||||||
}
|
|
||||||
linuxProcessRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#linux-process"), nil
|
|
||||||
}
|
|
||||||
platformSpecificConfigurationRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#platform-specific-configuration"), nil
|
|
||||||
}
|
|
||||||
posixPlatformHooksRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#posix-platform-hooks"), nil
|
|
||||||
}
|
|
||||||
prestartRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#prestart"), nil
|
|
||||||
}
|
|
||||||
poststartRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#poststart"), nil
|
|
||||||
}
|
|
||||||
poststopRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#poststop"), nil
|
|
||||||
}
|
|
||||||
annotationsRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#annotations"), nil
|
|
||||||
}
|
|
||||||
extensibilityRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#extensibility"), nil
|
|
||||||
}
|
|
||||||
validValuesRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "config.md#valid-values"), nil
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
register(SpecVersionInSemVer, rfc2119.Must, specificationVersionRef)
|
|
||||||
register(RootOnWindowsRequired, rfc2119.Required, rootRef)
|
|
||||||
register(RootOnHyperVNotSet, rfc2119.Must, rootRef)
|
|
||||||
register(RootOnNonWindowsRequired, rfc2119.Required, rootRef)
|
|
||||||
register(RootPathOnWindowsGUID, rfc2119.Must, rootRef)
|
|
||||||
register(RootPathOnPosixConvention, rfc2119.Should, rootRef)
|
|
||||||
register(RootPathExist, rfc2119.Must, rootRef)
|
|
||||||
register(RootReadonlyImplement, rfc2119.Must, rootRef)
|
|
||||||
register(RootReadonlyOnWindowsFalse, rfc2119.Must, rootRef)
|
|
||||||
register(MountsInOrder, rfc2119.Must, mountsRef)
|
|
||||||
register(MountsDestAbs, rfc2119.Must, mountsRef)
|
|
||||||
register(MountsDestOnWindowsNotNested, rfc2119.Must, mountsRef)
|
|
||||||
register(MountsOptionsOnWindowsROSupport, rfc2119.Must, mountsRef)
|
|
||||||
register(ProcRequiredAtStart, rfc2119.Required, processRef)
|
|
||||||
register(ProcConsoleSizeIgnore, rfc2119.Must, processRef)
|
|
||||||
register(ProcCwdAbs, rfc2119.Must, processRef)
|
|
||||||
register(ProcArgsOneEntryRequired, rfc2119.Required, processRef)
|
|
||||||
register(PosixProcRlimitsTypeGenError, rfc2119.Must, posixProcessRef)
|
|
||||||
register(PosixProcRlimitsTypeGet, rfc2119.Must, posixProcessRef)
|
|
||||||
register(PosixProcRlimitsTypeValueError, rfc2119.Should, posixProcessRef)
|
|
||||||
register(PosixProcRlimitsSoftMatchCur, rfc2119.Must, posixProcessRef)
|
|
||||||
register(PosixProcRlimitsHardMatchMax, rfc2119.Must, posixProcessRef)
|
|
||||||
register(PosixProcRlimitsErrorOnDup, rfc2119.Must, posixProcessRef)
|
|
||||||
register(LinuxProcCapError, rfc2119.Must, linuxProcessRef)
|
|
||||||
register(LinuxProcOomScoreAdjSet, rfc2119.Must, linuxProcessRef)
|
|
||||||
register(LinuxProcOomScoreAdjNotSet, rfc2119.Must, linuxProcessRef)
|
|
||||||
register(PlatformSpecConfOnWindowsSet, rfc2119.Must, platformSpecificConfigurationRef)
|
|
||||||
register(PosixHooksPathAbs, rfc2119.Must, posixPlatformHooksRef)
|
|
||||||
register(PosixHooksTimeoutPositive, rfc2119.Must, posixPlatformHooksRef)
|
|
||||||
register(PosixHooksCalledInOrder, rfc2119.Must, posixPlatformHooksRef)
|
|
||||||
register(PosixHooksStateToStdin, rfc2119.Must, posixPlatformHooksRef)
|
|
||||||
register(PrestartTiming, rfc2119.Must, prestartRef)
|
|
||||||
register(PoststartTiming, rfc2119.Must, poststartRef)
|
|
||||||
register(PoststopTiming, rfc2119.Must, poststopRef)
|
|
||||||
register(AnnotationsKeyValueMap, rfc2119.Must, annotationsRef)
|
|
||||||
register(AnnotationsKeyString, rfc2119.Must, annotationsRef)
|
|
||||||
register(AnnotationsKeyRequired, rfc2119.Must, annotationsRef)
|
|
||||||
register(AnnotationsKeyReversedDomain, rfc2119.Should, annotationsRef)
|
|
||||||
register(AnnotationsKeyReservedNS, rfc2119.Must, annotationsRef)
|
|
||||||
register(AnnotationsKeyIgnoreUnknown, rfc2119.Must, annotationsRef)
|
|
||||||
register(AnnotationsValueString, rfc2119.Must, annotationsRef)
|
|
||||||
register(ExtensibilityIgnoreUnknownProp, rfc2119.Must, extensibilityRef)
|
|
||||||
register(ValidValues, rfc2119.Must, validValuesRef)
|
|
||||||
}
|
|
152
vendor/github.com/opencontainers/runtime-tools/specerror/error.go
generated
vendored
152
vendor/github.com/opencontainers/runtime-tools/specerror/error.go
generated
vendored
@ -1,152 +0,0 @@
|
|||||||
// Package specerror implements runtime-spec-specific tooling for
|
|
||||||
// tracking RFC 2119 violations.
|
|
||||||
package specerror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
|
||||||
rfc2119 "github.com/opencontainers/runtime-tools/error"
|
|
||||||
)
|
|
||||||
|
|
||||||
const referenceTemplate = "https://github.com/opencontainers/runtime-spec/blob/v%s/%s"
|
|
||||||
|
|
||||||
// Code represents the spec violation, enumerating both
|
|
||||||
// configuration violations and runtime violations.
|
|
||||||
type Code int64
|
|
||||||
|
|
||||||
const (
|
|
||||||
// NonError represents that an input is not an error
|
|
||||||
NonError Code = 0x1a001 + iota
|
|
||||||
// NonRFCError represents that an error is not a rfc2119 error
|
|
||||||
NonRFCError
|
|
||||||
)
|
|
||||||
|
|
||||||
type errorTemplate struct {
|
|
||||||
Level rfc2119.Level
|
|
||||||
Reference func(version string) (reference string, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error represents a runtime-spec violation.
|
|
||||||
type Error struct {
|
|
||||||
// Err holds the RFC 2119 violation.
|
|
||||||
Err rfc2119.Error
|
|
||||||
|
|
||||||
// Code is a matchable holds a Code
|
|
||||||
Code Code
|
|
||||||
}
|
|
||||||
|
|
||||||
// LevelErrors represents Errors filtered into fatal and warnings.
|
|
||||||
type LevelErrors struct {
|
|
||||||
// Warnings holds Errors that were below a compliance-level threshold.
|
|
||||||
Warnings []*Error
|
|
||||||
|
|
||||||
// Error holds errors that were at or above a compliance-level
|
|
||||||
// threshold, as well as errors that are not Errors.
|
|
||||||
Error *multierror.Error
|
|
||||||
}
|
|
||||||
|
|
||||||
var ociErrors = map[Code]errorTemplate{}
|
|
||||||
|
|
||||||
func register(code Code, level rfc2119.Level, ref func(versiong string) (string, error)) {
|
|
||||||
if _, ok := ociErrors[code]; ok {
|
|
||||||
panic(fmt.Sprintf("should not regist a same code twice: %v", code))
|
|
||||||
}
|
|
||||||
|
|
||||||
ociErrors[code] = errorTemplate{Level: level, Reference: ref}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns the error message with specification reference.
|
|
||||||
func (err *Error) Error() string {
|
|
||||||
return err.Err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRFCError creates an rfc2119.Error referencing a spec violation.
|
|
||||||
//
|
|
||||||
// A version string (for the version of the spec that was violated)
|
|
||||||
// must be set to get a working URL.
|
|
||||||
func NewRFCError(code Code, err error, version string) (*rfc2119.Error, error) {
|
|
||||||
template := ociErrors[code]
|
|
||||||
reference, err2 := template.Reference(version)
|
|
||||||
if err2 != nil {
|
|
||||||
return nil, err2
|
|
||||||
}
|
|
||||||
return &rfc2119.Error{
|
|
||||||
Level: template.Level,
|
|
||||||
Reference: reference,
|
|
||||||
Err: err,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRFCErrorOrPanic creates an rfc2119.Error referencing a spec
|
|
||||||
// violation and panics on failure. This is handy for situations
|
|
||||||
// where you can't be bothered to check NewRFCError for failure.
|
|
||||||
func NewRFCErrorOrPanic(code Code, err error, version string) *rfc2119.Error {
|
|
||||||
rfcError, err2 := NewRFCError(code, err, version)
|
|
||||||
if err2 != nil {
|
|
||||||
panic(err2.Error())
|
|
||||||
}
|
|
||||||
return rfcError
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewError creates an Error referencing a spec violation. The error
|
|
||||||
// can be cast to an *Error for extracting structured information
|
|
||||||
// about the level of the violation and a reference to the violated
|
|
||||||
// spec condition.
|
|
||||||
//
|
|
||||||
// A version string (for the version of the spec that was violated)
|
|
||||||
// must be set to get a working URL.
|
|
||||||
func NewError(code Code, err error, version string) error {
|
|
||||||
rfcError, err2 := NewRFCError(code, err, version)
|
|
||||||
if err2 != nil {
|
|
||||||
return err2
|
|
||||||
}
|
|
||||||
return &Error{
|
|
||||||
Err: *rfcError,
|
|
||||||
Code: code,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindError finds an error from a source error (multiple error) and
|
|
||||||
// returns the error code if found.
|
|
||||||
// If the source error is nil or empty, return NonError.
|
|
||||||
// If the source error is not a multiple error, return NonRFCError.
|
|
||||||
func FindError(err error, code Code) Code {
|
|
||||||
if err == nil {
|
|
||||||
return NonError
|
|
||||||
}
|
|
||||||
|
|
||||||
if merr, ok := err.(*multierror.Error); ok {
|
|
||||||
if merr.ErrorOrNil() == nil {
|
|
||||||
return NonError
|
|
||||||
}
|
|
||||||
for _, e := range merr.Errors {
|
|
||||||
if rfcErr, ok := e.(*Error); ok {
|
|
||||||
if rfcErr.Code == code {
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NonRFCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// SplitLevel removes RFC 2119 errors with a level less than 'level'
|
|
||||||
// from the source error. If the source error is not a multierror, it
|
|
||||||
// is returned unchanged.
|
|
||||||
func SplitLevel(errIn error, level rfc2119.Level) (levelErrors LevelErrors, errOut error) {
|
|
||||||
merr, ok := errIn.(*multierror.Error)
|
|
||||||
if !ok {
|
|
||||||
return levelErrors, errIn
|
|
||||||
}
|
|
||||||
for _, err := range merr.Errors {
|
|
||||||
e, ok := err.(*Error)
|
|
||||||
if ok && e.Err.Level < level {
|
|
||||||
fmt.Println(e)
|
|
||||||
levelErrors.Warnings = append(levelErrors.Warnings, e)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
levelErrors.Error = multierror.Append(levelErrors.Error, err)
|
|
||||||
}
|
|
||||||
return levelErrors, nil
|
|
||||||
}
|
|
23
vendor/github.com/opencontainers/runtime-tools/specerror/runtime-linux.go
generated
vendored
23
vendor/github.com/opencontainers/runtime-tools/specerror/runtime-linux.go
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
package specerror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
rfc2119 "github.com/opencontainers/runtime-tools/error"
|
|
||||||
)
|
|
||||||
|
|
||||||
// define error codes
|
|
||||||
const (
|
|
||||||
// DefaultRuntimeLinuxSymlinks represents "While creating the container (step 2 in the lifecycle), runtimes MUST create default symlinks if the source file exists after processing `mounts`."
|
|
||||||
DefaultRuntimeLinuxSymlinks Code = 0xf001 + iota
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
devSymbolicLinksRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "runtime-linux.md#dev-symbolic-links"), nil
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
register(DefaultRuntimeLinuxSymlinks, rfc2119.Must, devSymbolicLinksRef)
|
|
||||||
}
|
|
179
vendor/github.com/opencontainers/runtime-tools/specerror/runtime.go
generated
vendored
179
vendor/github.com/opencontainers/runtime-tools/specerror/runtime.go
generated
vendored
@ -1,179 +0,0 @@
|
|||||||
package specerror
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
rfc2119 "github.com/opencontainers/runtime-tools/error"
|
|
||||||
)
|
|
||||||
|
|
||||||
// define error codes
|
|
||||||
const (
|
|
||||||
// EntityOperSameContainer represents "The entity using a runtime to create a container MUST be able to use the operations defined in this specification against that same container."
|
|
||||||
EntityOperSameContainer Code = 0xe001 + iota
|
|
||||||
// StateIDUniq represents "`id` (string, REQUIRED) is the container's ID. This MUST be unique across all containers on this host."
|
|
||||||
StateIDUniq
|
|
||||||
// StateNewStatus represents "Additional values MAY be defined by the runtime, however, they MUST be used to represent new runtime states not defined above."
|
|
||||||
StateNewStatus
|
|
||||||
// DefaultStateJSONPattern represents "When serialized in JSON, the format MUST adhere to the default pattern."
|
|
||||||
DefaultStateJSONPattern
|
|
||||||
// EnvCreateImplement represents "The container's runtime environment MUST be created according to the configuration in `config.json`."
|
|
||||||
EnvCreateImplement
|
|
||||||
// EnvCreateError represents "If the runtime is unable to create the environment specified in the `config.json`, it MUST generate an error."
|
|
||||||
EnvCreateError
|
|
||||||
// ProcNotRunAtResRequest represents "While the resources requested in the `config.json` MUST be created, the user-specified program (from `process`) MUST NOT be run at this time."
|
|
||||||
ProcNotRunAtResRequest
|
|
||||||
// ConfigUpdatesWithoutAffect represents "Any updates to `config.json` after this step MUST NOT affect the container."
|
|
||||||
ConfigUpdatesWithoutAffect
|
|
||||||
// PrestartHooksInvoke represents "The prestart hooks MUST be invoked by the runtime."
|
|
||||||
PrestartHooksInvoke
|
|
||||||
// PrestartHookFailGenError represents "If any prestart hook fails, the runtime MUST generate an error, stop the container, and continue the lifecycle at step 9."
|
|
||||||
PrestartHookFailGenError
|
|
||||||
// ProcImplement represents "The runtime MUST run the user-specified program, as specified by `process`."
|
|
||||||
ProcImplement
|
|
||||||
// PoststartHooksInvoke represents "The poststart hooks MUST be invoked by the runtime."
|
|
||||||
PoststartHooksInvoke
|
|
||||||
// PoststartHookFailGenWarn represents "If any poststart hook fails, the runtime MUST log a warning, but the remaining hooks and lifecycle continue as if the hook had succeeded."
|
|
||||||
PoststartHookFailGenWarn
|
|
||||||
// UndoCreateSteps represents "The container MUST be destroyed by undoing the steps performed during create phase (step 2)."
|
|
||||||
UndoCreateSteps
|
|
||||||
// PoststopHooksInvoke represents "The poststop hooks MUST be invoked by the runtime."
|
|
||||||
PoststopHooksInvoke
|
|
||||||
// PoststopHookFailGenWarn represents "If any poststop hook fails, the runtime MUST log a warning, but the remaining hooks and lifecycle continue as if the hook had succeeded."
|
|
||||||
PoststopHookFailGenWarn
|
|
||||||
// ErrorsLeaveStateUnchange represents "Unless otherwise stated, generating an error MUST leave the state of the environment as if the operation were never attempted - modulo any possible trivial ancillary changes such as logging."
|
|
||||||
ErrorsLeaveStateUnchange
|
|
||||||
// WarnsLeaveFlowUnchange represents "Unless otherwise stated, logging a warning does not change the flow of the operation; it MUST continue as if the warning had not been logged."
|
|
||||||
WarnsLeaveFlowUnchange
|
|
||||||
// DefaultOperations represents "Unless otherwise stated, runtimes MUST support the default operations."
|
|
||||||
DefaultOperations
|
|
||||||
// QueryWithoutIDGenError represents "This operation MUST generate an error if it is not provided the ID of a container."
|
|
||||||
QueryWithoutIDGenError
|
|
||||||
// QueryNonExistGenError represents "Attempting to query a container that does not exist MUST generate an error."
|
|
||||||
QueryNonExistGenError
|
|
||||||
// QueryStateImplement represents "This operation MUST return the state of a container as specified in the State section."
|
|
||||||
QueryStateImplement
|
|
||||||
// CreateWithBundlePathAndID represents "This operation MUST generate an error if it is not provided a path to the bundle and the container ID to associate with the container."
|
|
||||||
CreateWithBundlePathAndID
|
|
||||||
// CreateWithUniqueID represents "If the ID provided is not unique across all containers within the scope of the runtime, or is not valid in any other way, the implementation MUST generate an error and a new container MUST NOT be created."
|
|
||||||
CreateWithUniqueID
|
|
||||||
// CreateNewContainer represents "This operation MUST create a new container."
|
|
||||||
CreateNewContainer
|
|
||||||
// PropsApplyExceptProcOnCreate represents "All of the properties configured in `config.json` except for `process` MUST be applied."
|
|
||||||
PropsApplyExceptProcOnCreate
|
|
||||||
// ProcArgsApplyUntilStart represents `process.args` MUST NOT be applied until triggered by the `start` operation."
|
|
||||||
ProcArgsApplyUntilStart
|
|
||||||
// PropApplyFailGenError represents "If the runtime cannot apply a property as specified in the configuration, it MUST generate an error."
|
|
||||||
PropApplyFailGenError
|
|
||||||
// PropApplyFailNotCreate represents "If the runtime cannot apply a property as specified in the configuration, a new container MUST NOT be created."
|
|
||||||
PropApplyFailNotCreate
|
|
||||||
// StartWithoutIDGenError represents "`start` operation MUST generate an error if it is not provided the container ID."
|
|
||||||
StartWithoutIDGenError
|
|
||||||
// StartNotCreatedHaveNoEffect represents "Attempting to `start` a container that is not `created` MUST have no effect on the container."
|
|
||||||
StartNotCreatedHaveNoEffect
|
|
||||||
// StartNotCreatedGenError represents "Attempting to `start` a container that is not `created` MUST generate an error."
|
|
||||||
StartNotCreatedGenError
|
|
||||||
// StartProcImplement represents "`start` operation MUST run the user-specified program as specified by `process`."
|
|
||||||
StartProcImplement
|
|
||||||
// StartWithProcUnsetGenError represents "`start` operation MUST generate an error if `process` was not set."
|
|
||||||
StartWithProcUnsetGenError
|
|
||||||
// KillWithoutIDGenError represents "`kill` operation MUST generate an error if it is not provided the container ID."
|
|
||||||
KillWithoutIDGenError
|
|
||||||
// KillNonCreateRunHaveNoEffect represents "Attempting to send a signal to a container that is neither `created` nor `running` MUST have no effect on the container."
|
|
||||||
KillNonCreateRunHaveNoEffect
|
|
||||||
// KillNonCreateRunGenError represents "Attempting to send a signal to a container that is neither `created` nor `running` MUST generate an error."
|
|
||||||
KillNonCreateRunGenError
|
|
||||||
// KillSignalImplement represents "`kill` operation MUST send the specified signal to the container process."
|
|
||||||
KillSignalImplement
|
|
||||||
// DeleteWithoutIDGenError represents "`delete` operation MUST generate an error if it is not provided the container ID."
|
|
||||||
DeleteWithoutIDGenError
|
|
||||||
// DeleteNonStopHaveNoEffect represents "Attempting to `delete` a container that is not `stopped` MUST have no effect on the container."
|
|
||||||
DeleteNonStopHaveNoEffect
|
|
||||||
// DeleteNonStopGenError represents "Attempting to `delete` a container that is not `stopped` MUST generate an error."
|
|
||||||
DeleteNonStopGenError
|
|
||||||
// DeleteResImplement represents "Deleting a container MUST delete the resources that were created during the `create` step."
|
|
||||||
DeleteResImplement
|
|
||||||
// DeleteOnlyCreatedRes represents "Note that resources associated with the container, but not created by this container, MUST NOT be deleted."
|
|
||||||
DeleteOnlyCreatedRes
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
scopeOfAContainerRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "runtime.md#scope-of-a-container"), nil
|
|
||||||
}
|
|
||||||
stateRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "runtime.md#state"), nil
|
|
||||||
}
|
|
||||||
lifecycleRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "runtime.md#lifecycle"), nil
|
|
||||||
}
|
|
||||||
errorsRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "runtime.md#errors"), nil
|
|
||||||
}
|
|
||||||
warningsRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "runtime.md#warnings"), nil
|
|
||||||
}
|
|
||||||
operationsRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "runtime.md#operations"), nil
|
|
||||||
}
|
|
||||||
queryStateRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "runtime.md#query-state"), nil
|
|
||||||
}
|
|
||||||
createRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "runtime.md#create"), nil
|
|
||||||
}
|
|
||||||
startRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "runtime.md#start"), nil
|
|
||||||
}
|
|
||||||
killRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "runtime.md#kill"), nil
|
|
||||||
}
|
|
||||||
deleteRef = func(version string) (reference string, err error) {
|
|
||||||
return fmt.Sprintf(referenceTemplate, version, "runtime.md#delete"), nil
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
register(EntityOperSameContainer, rfc2119.Must, scopeOfAContainerRef)
|
|
||||||
register(StateIDUniq, rfc2119.Must, stateRef)
|
|
||||||
register(StateNewStatus, rfc2119.Must, stateRef)
|
|
||||||
register(DefaultStateJSONPattern, rfc2119.Must, stateRef)
|
|
||||||
register(EnvCreateImplement, rfc2119.Must, lifecycleRef)
|
|
||||||
register(EnvCreateError, rfc2119.Must, lifecycleRef)
|
|
||||||
register(ProcNotRunAtResRequest, rfc2119.Must, lifecycleRef)
|
|
||||||
register(ConfigUpdatesWithoutAffect, rfc2119.Must, lifecycleRef)
|
|
||||||
register(PrestartHooksInvoke, rfc2119.Must, lifecycleRef)
|
|
||||||
register(PrestartHookFailGenError, rfc2119.Must, lifecycleRef)
|
|
||||||
register(ProcImplement, rfc2119.Must, lifecycleRef)
|
|
||||||
register(PoststartHooksInvoke, rfc2119.Must, lifecycleRef)
|
|
||||||
register(PoststartHookFailGenWarn, rfc2119.Must, lifecycleRef)
|
|
||||||
register(UndoCreateSteps, rfc2119.Must, lifecycleRef)
|
|
||||||
register(PoststopHooksInvoke, rfc2119.Must, lifecycleRef)
|
|
||||||
register(PoststopHookFailGenWarn, rfc2119.Must, lifecycleRef)
|
|
||||||
register(ErrorsLeaveStateUnchange, rfc2119.Must, errorsRef)
|
|
||||||
register(WarnsLeaveFlowUnchange, rfc2119.Must, warningsRef)
|
|
||||||
register(DefaultOperations, rfc2119.Must, operationsRef)
|
|
||||||
register(QueryWithoutIDGenError, rfc2119.Must, queryStateRef)
|
|
||||||
register(QueryNonExistGenError, rfc2119.Must, queryStateRef)
|
|
||||||
register(QueryStateImplement, rfc2119.Must, queryStateRef)
|
|
||||||
register(CreateWithBundlePathAndID, rfc2119.Must, createRef)
|
|
||||||
register(CreateWithUniqueID, rfc2119.Must, createRef)
|
|
||||||
register(CreateNewContainer, rfc2119.Must, createRef)
|
|
||||||
register(PropsApplyExceptProcOnCreate, rfc2119.Must, createRef)
|
|
||||||
register(ProcArgsApplyUntilStart, rfc2119.Must, createRef)
|
|
||||||
register(PropApplyFailGenError, rfc2119.Must, createRef)
|
|
||||||
register(PropApplyFailNotCreate, rfc2119.Must, createRef)
|
|
||||||
register(StartWithoutIDGenError, rfc2119.Must, startRef)
|
|
||||||
register(StartNotCreatedHaveNoEffect, rfc2119.Must, startRef)
|
|
||||||
register(StartNotCreatedGenError, rfc2119.Must, startRef)
|
|
||||||
register(StartProcImplement, rfc2119.Must, startRef)
|
|
||||||
register(StartWithProcUnsetGenError, rfc2119.Must, startRef)
|
|
||||||
register(KillWithoutIDGenError, rfc2119.Must, killRef)
|
|
||||||
register(KillNonCreateRunHaveNoEffect, rfc2119.Must, killRef)
|
|
||||||
register(KillNonCreateRunGenError, rfc2119.Must, killRef)
|
|
||||||
register(KillSignalImplement, rfc2119.Must, killRef)
|
|
||||||
register(DeleteWithoutIDGenError, rfc2119.Must, deleteRef)
|
|
||||||
register(DeleteNonStopHaveNoEffect, rfc2119.Must, deleteRef)
|
|
||||||
register(DeleteNonStopGenError, rfc2119.Must, deleteRef)
|
|
||||||
register(DeleteResImplement, rfc2119.Must, deleteRef)
|
|
||||||
register(DeleteOnlyCreatedRes, rfc2119.Must, deleteRef)
|
|
||||||
}
|
|
31
vendor/github.com/opencontainers/runtime-tools/validate/capabilities/validate.go
generated
vendored
Normal file
31
vendor/github.com/opencontainers/runtime-tools/validate/capabilities/validate.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package capabilities
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/syndtr/gocapability/capability"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CapValid checks whether a capability is valid
|
||||||
|
func CapValid(c string, hostSpecific bool) error {
|
||||||
|
isValid := false
|
||||||
|
|
||||||
|
if !strings.HasPrefix(c, "CAP_") {
|
||||||
|
return fmt.Errorf("capability %s must start with CAP_", c)
|
||||||
|
}
|
||||||
|
for _, cap := range capability.List() {
|
||||||
|
if c == fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())) {
|
||||||
|
if hostSpecific && cap > LastCap() {
|
||||||
|
return fmt.Errorf("%s is not supported on the current host", c)
|
||||||
|
}
|
||||||
|
isValid = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isValid {
|
||||||
|
return fmt.Errorf("invalid capability: %s", c)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
16
vendor/github.com/opencontainers/runtime-tools/validate/capabilities/validate_linux.go
generated
vendored
Normal file
16
vendor/github.com/opencontainers/runtime-tools/validate/capabilities/validate_linux.go
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package capabilities
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/syndtr/gocapability/capability"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LastCap return last cap of system
|
||||||
|
func LastCap() capability.Cap {
|
||||||
|
last := capability.CAP_LAST_CAP
|
||||||
|
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
|
||||||
|
if last == capability.Cap(63) {
|
||||||
|
last = capability.CAP_BLOCK_SUSPEND
|
||||||
|
}
|
||||||
|
|
||||||
|
return last
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !linux
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package validate
|
package validate
|
||||||
@ -10,8 +11,3 @@ import (
|
|||||||
func LastCap() capability.Cap {
|
func LastCap() capability.Cap {
|
||||||
return capability.Cap(-1)
|
return capability.Cap(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckLinux is a noop on this platform
|
|
||||||
func (v *Validator) CheckLinux() (errs error) {
|
|
||||||
return nil
|
|
||||||
}
|
|
838
vendor/github.com/opencontainers/runtime-tools/validate/validate.go
generated
vendored
838
vendor/github.com/opencontainers/runtime-tools/validate/validate.go
generated
vendored
@ -1,838 +0,0 @@
|
|||||||
package validate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
|
||||||
"regexp"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"github.com/blang/semver"
|
|
||||||
"github.com/hashicorp/go-multierror"
|
|
||||||
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
|
||||||
osFilepath "github.com/opencontainers/runtime-tools/filepath"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/syndtr/gocapability/capability"
|
|
||||||
|
|
||||||
"github.com/opencontainers/runtime-tools/specerror"
|
|
||||||
"github.com/xeipuuv/gojsonschema"
|
|
||||||
)
|
|
||||||
|
|
||||||
const specConfig = "config.json"
|
|
||||||
|
|
||||||
var (
|
|
||||||
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html
|
|
||||||
posixRlimits = []string{
|
|
||||||
"RLIMIT_AS",
|
|
||||||
"RLIMIT_CORE",
|
|
||||||
"RLIMIT_CPU",
|
|
||||||
"RLIMIT_DATA",
|
|
||||||
"RLIMIT_FSIZE",
|
|
||||||
"RLIMIT_NOFILE",
|
|
||||||
"RLIMIT_STACK",
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/getrlimit.2?h=man-pages-4.13
|
|
||||||
linuxRlimits = append(posixRlimits, []string{
|
|
||||||
"RLIMIT_MEMLOCK",
|
|
||||||
"RLIMIT_MSGQUEUE",
|
|
||||||
"RLIMIT_NICE",
|
|
||||||
"RLIMIT_NPROC",
|
|
||||||
"RLIMIT_RSS",
|
|
||||||
"RLIMIT_RTPRIO",
|
|
||||||
"RLIMIT_RTTIME",
|
|
||||||
"RLIMIT_SIGPENDING",
|
|
||||||
}...)
|
|
||||||
|
|
||||||
configSchemaTemplate = "https://raw.githubusercontent.com/opencontainers/runtime-spec/v%s/schema/config-schema.json"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Validator represents a validator for runtime bundle
|
|
||||||
type Validator struct {
|
|
||||||
spec *rspec.Spec
|
|
||||||
bundlePath string
|
|
||||||
HostSpecific bool
|
|
||||||
platform string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewValidator creates a Validator
|
|
||||||
func NewValidator(spec *rspec.Spec, bundlePath string, hostSpecific bool, platform string) (Validator, error) {
|
|
||||||
if hostSpecific && platform != runtime.GOOS {
|
|
||||||
return Validator{}, fmt.Errorf("When hostSpecific is set, platform must be same as the host platform")
|
|
||||||
}
|
|
||||||
return Validator{
|
|
||||||
spec: spec,
|
|
||||||
bundlePath: bundlePath,
|
|
||||||
HostSpecific: hostSpecific,
|
|
||||||
platform: platform,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewValidatorFromPath creates a Validator with specified bundle path
|
|
||||||
func NewValidatorFromPath(bundlePath string, hostSpecific bool, platform string) (Validator, error) {
|
|
||||||
if bundlePath == "" {
|
|
||||||
return Validator{}, fmt.Errorf("bundle path shouldn't be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := os.Stat(bundlePath); err != nil {
|
|
||||||
return Validator{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
configPath := filepath.Join(bundlePath, specConfig)
|
|
||||||
content, err := ioutil.ReadFile(configPath)
|
|
||||||
if err != nil {
|
|
||||||
return Validator{}, specerror.NewError(specerror.ConfigInRootBundleDir, err, rspec.Version)
|
|
||||||
}
|
|
||||||
if !utf8.Valid(content) {
|
|
||||||
return Validator{}, fmt.Errorf("%q is not encoded in UTF-8", configPath)
|
|
||||||
}
|
|
||||||
var spec rspec.Spec
|
|
||||||
if err = json.Unmarshal(content, &spec); err != nil {
|
|
||||||
return Validator{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return NewValidator(&spec, bundlePath, hostSpecific, platform)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckAll checks all parts of runtime bundle
|
|
||||||
func (v *Validator) CheckAll() error {
|
|
||||||
var errs *multierror.Error
|
|
||||||
errs = multierror.Append(errs, v.CheckJSONSchema())
|
|
||||||
errs = multierror.Append(errs, v.CheckPlatform())
|
|
||||||
errs = multierror.Append(errs, v.CheckRoot())
|
|
||||||
errs = multierror.Append(errs, v.CheckMandatoryFields())
|
|
||||||
errs = multierror.Append(errs, v.CheckSemVer())
|
|
||||||
errs = multierror.Append(errs, v.CheckMounts())
|
|
||||||
errs = multierror.Append(errs, v.CheckProcess())
|
|
||||||
errs = multierror.Append(errs, v.CheckLinux())
|
|
||||||
errs = multierror.Append(errs, v.CheckAnnotations())
|
|
||||||
if v.platform == "linux" || v.platform == "solaris" {
|
|
||||||
errs = multierror.Append(errs, v.CheckHooks())
|
|
||||||
}
|
|
||||||
|
|
||||||
return errs.ErrorOrNil()
|
|
||||||
}
|
|
||||||
|
|
||||||
// JSONSchemaURL returns the URL for the JSON Schema specifying the
|
|
||||||
// configuration format. It consumes configSchemaTemplate, but we
|
|
||||||
// provide it as a function to isolate consumers from inconsistent
|
|
||||||
// naming as runtime-spec evolves.
|
|
||||||
func JSONSchemaURL(version string) (url string, err error) {
|
|
||||||
ver, err := semver.Parse(version)
|
|
||||||
if err != nil {
|
|
||||||
return "", specerror.NewError(specerror.SpecVersionInSemVer, err, rspec.Version)
|
|
||||||
}
|
|
||||||
configRenamedToConfigSchemaVersion, err := semver.Parse("1.0.0-rc2") // config.json became config-schema.json in 1.0.0-rc2
|
|
||||||
if ver.Compare(configRenamedToConfigSchemaVersion) == -1 {
|
|
||||||
return "", fmt.Errorf("unsupported configuration version (older than %s)", configRenamedToConfigSchemaVersion)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf(configSchemaTemplate, version), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckJSONSchema validates the configuration against the
|
|
||||||
// runtime-spec JSON Schema, using the version of the schema that
|
|
||||||
// matches the configuration's declared version.
|
|
||||||
func (v *Validator) CheckJSONSchema() (errs error) {
|
|
||||||
logrus.Debugf("check JSON schema")
|
|
||||||
|
|
||||||
url, err := JSONSchemaURL(v.spec.Version)
|
|
||||||
if err != nil {
|
|
||||||
errs = multierror.Append(errs, err)
|
|
||||||
return errs
|
|
||||||
}
|
|
||||||
|
|
||||||
schemaLoader := gojsonschema.NewReferenceLoader(url)
|
|
||||||
documentLoader := gojsonschema.NewGoLoader(v.spec)
|
|
||||||
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
|
|
||||||
if err != nil {
|
|
||||||
errs = multierror.Append(errs, err)
|
|
||||||
return errs
|
|
||||||
}
|
|
||||||
|
|
||||||
if !result.Valid() {
|
|
||||||
for _, resultError := range result.Errors() {
|
|
||||||
errs = multierror.Append(errs, errors.New(resultError.String()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return errs
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckRoot checks status of v.spec.Root
|
|
||||||
func (v *Validator) CheckRoot() (errs error) {
|
|
||||||
logrus.Debugf("check root")
|
|
||||||
|
|
||||||
if v.platform == "windows" && v.spec.Windows != nil {
|
|
||||||
if v.spec.Windows.HyperV != nil {
|
|
||||||
if v.spec.Root != nil {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(specerror.RootOnHyperVNotSet, fmt.Errorf("for Hyper-V containers, Root must not be set"), rspec.Version))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} else if v.spec.Root == nil {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(specerror.RootOnWindowsRequired, fmt.Errorf("on Windows, for Windows Server Containers, this field is REQUIRED"), rspec.Version))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else if v.platform != "windows" && v.spec.Root == nil {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(specerror.RootOnNonWindowsRequired, fmt.Errorf("on all other platforms, this field is REQUIRED"), rspec.Version))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.platform == "windows" {
|
|
||||||
matched, err := regexp.MatchString(`\\\\[?]\\Volume[{][a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}[}]\\`, v.spec.Root.Path)
|
|
||||||
if err != nil {
|
|
||||||
errs = multierror.Append(errs, err)
|
|
||||||
} else if !matched {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(specerror.RootPathOnWindowsGUID, fmt.Errorf("root.path is %q, but it MUST be a volume GUID path when target platform is windows", v.spec.Root.Path), rspec.Version))
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.spec.Root.Readonly {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(specerror.RootReadonlyOnWindowsFalse, fmt.Errorf("root.readonly field MUST be omitted or false when target platform is windows"), rspec.Version))
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
absBundlePath, err := filepath.Abs(v.bundlePath)
|
|
||||||
if err != nil {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("unable to convert %q to an absolute path", v.bundlePath))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if filepath.Base(v.spec.Root.Path) != "rootfs" {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(specerror.RootPathOnPosixConvention, fmt.Errorf("path name should be the conventional 'rootfs'"), rspec.Version))
|
|
||||||
}
|
|
||||||
|
|
||||||
var rootfsPath string
|
|
||||||
var absRootPath string
|
|
||||||
if filepath.IsAbs(v.spec.Root.Path) {
|
|
||||||
rootfsPath = v.spec.Root.Path
|
|
||||||
absRootPath = filepath.Clean(rootfsPath)
|
|
||||||
} else {
|
|
||||||
var err error
|
|
||||||
rootfsPath = filepath.Join(v.bundlePath, v.spec.Root.Path)
|
|
||||||
absRootPath, err = filepath.Abs(rootfsPath)
|
|
||||||
if err != nil {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("unable to convert %q to an absolute path", rootfsPath))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if fi, err := os.Stat(rootfsPath); err != nil {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(specerror.RootPathExist, fmt.Errorf("cannot find the root path %q", rootfsPath), rspec.Version))
|
|
||||||
} else if !fi.IsDir() {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(specerror.RootPathExist, fmt.Errorf("root.path %q is not a directory", rootfsPath), rspec.Version))
|
|
||||||
}
|
|
||||||
|
|
||||||
rootParent := filepath.Dir(absRootPath)
|
|
||||||
if absRootPath == string(filepath.Separator) || rootParent != absBundlePath {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(specerror.ArtifactsInSingleDir, fmt.Errorf("root.path is %q, but it MUST be a child of %q", v.spec.Root.Path, absBundlePath), rspec.Version))
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckSemVer checks v.spec.Version
|
|
||||||
func (v *Validator) CheckSemVer() (errs error) {
|
|
||||||
logrus.Debugf("check semver")
|
|
||||||
|
|
||||||
version := v.spec.Version
|
|
||||||
_, err := semver.Parse(version)
|
|
||||||
if err != nil {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(specerror.SpecVersionInSemVer, fmt.Errorf("%q is not valid SemVer: %s", version, err.Error()), rspec.Version))
|
|
||||||
}
|
|
||||||
if version != rspec.Version {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("validate currently only handles version %s, but the supplied configuration targets %s", rspec.Version, version))
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckHooks check v.spec.Hooks
|
|
||||||
func (v *Validator) CheckHooks() (errs error) {
|
|
||||||
logrus.Debugf("check hooks")
|
|
||||||
|
|
||||||
if v.platform != "linux" && v.platform != "solaris" {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("For %q platform, the configuration structure does not support hooks", v.platform))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.spec.Hooks != nil {
|
|
||||||
errs = multierror.Append(errs, v.checkEventHooks("prestart", v.spec.Hooks.Prestart, v.HostSpecific))
|
|
||||||
errs = multierror.Append(errs, v.checkEventHooks("poststart", v.spec.Hooks.Poststart, v.HostSpecific))
|
|
||||||
errs = multierror.Append(errs, v.checkEventHooks("poststop", v.spec.Hooks.Poststop, v.HostSpecific))
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *Validator) checkEventHooks(hookType string, hooks []rspec.Hook, hostSpecific bool) (errs error) {
|
|
||||||
for i, hook := range hooks {
|
|
||||||
if !osFilepath.IsAbs(v.platform, hook.Path) {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(
|
|
||||||
specerror.PosixHooksPathAbs,
|
|
||||||
fmt.Errorf("hooks.%s[%d].path %v: is not absolute path",
|
|
||||||
hookType, i, hook.Path),
|
|
||||||
rspec.Version))
|
|
||||||
}
|
|
||||||
|
|
||||||
if hostSpecific {
|
|
||||||
fi, err := os.Stat(hook.Path)
|
|
||||||
if err != nil {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("cannot find %s hook: %v", hookType, hook.Path))
|
|
||||||
}
|
|
||||||
if fi.Mode()&0111 == 0 {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("the %s hook %v: is not executable", hookType, hook.Path))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, env := range hook.Env {
|
|
||||||
if !envValid(env) {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("env %q for hook %v is in the invalid form", env, hook.Path))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckProcess checks v.spec.Process
|
|
||||||
func (v *Validator) CheckProcess() (errs error) {
|
|
||||||
logrus.Debugf("check process")
|
|
||||||
|
|
||||||
if v.spec.Process == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
process := v.spec.Process
|
|
||||||
if !osFilepath.IsAbs(v.platform, process.Cwd) {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(
|
|
||||||
specerror.ProcCwdAbs,
|
|
||||||
fmt.Errorf("cwd %q is not an absolute path", process.Cwd),
|
|
||||||
rspec.Version))
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, env := range process.Env {
|
|
||||||
if !envValid(env) {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("env %q should be in the form of 'key=value'. The left hand side must consist solely of letters, digits, and underscores '_'", env))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(process.Args) == 0 {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(
|
|
||||||
specerror.ProcArgsOneEntryRequired,
|
|
||||||
fmt.Errorf("args must not be empty"),
|
|
||||||
rspec.Version))
|
|
||||||
} else {
|
|
||||||
if filepath.IsAbs(process.Args[0]) && v.spec.Root != nil {
|
|
||||||
var rootfsPath string
|
|
||||||
if filepath.IsAbs(v.spec.Root.Path) {
|
|
||||||
rootfsPath = v.spec.Root.Path
|
|
||||||
} else {
|
|
||||||
rootfsPath = filepath.Join(v.bundlePath, v.spec.Root.Path)
|
|
||||||
}
|
|
||||||
absPath := filepath.Join(rootfsPath, process.Args[0])
|
|
||||||
fileinfo, err := os.Stat(absPath)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
logrus.Warnf("executable %q is not available in rootfs currently", process.Args[0])
|
|
||||||
} else if err != nil {
|
|
||||||
errs = multierror.Append(errs, err)
|
|
||||||
} else {
|
|
||||||
m := fileinfo.Mode()
|
|
||||||
if m.IsDir() || m&0111 == 0 {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("arg %q is not executable", process.Args[0]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.platform == "linux" || v.platform == "solaris" {
|
|
||||||
errs = multierror.Append(errs, v.CheckRlimits())
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.platform == "linux" {
|
|
||||||
if v.spec.Process.Capabilities != nil {
|
|
||||||
errs = multierror.Append(errs, v.CheckCapabilities())
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(process.ApparmorProfile) > 0 {
|
|
||||||
profilePath := filepath.Join(v.bundlePath, v.spec.Root.Path, "/etc/apparmor.d", process.ApparmorProfile)
|
|
||||||
_, err := os.Stat(profilePath)
|
|
||||||
if err != nil {
|
|
||||||
errs = multierror.Append(errs, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckCapabilities checks v.spec.Process.Capabilities
|
|
||||||
func (v *Validator) CheckCapabilities() (errs error) {
|
|
||||||
if v.platform != "linux" {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("For %q platform, the configuration structure does not support process.capabilities", v.platform))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
process := v.spec.Process
|
|
||||||
var effective, permitted, inheritable, ambient bool
|
|
||||||
caps := make(map[string][]string)
|
|
||||||
|
|
||||||
for _, cap := range process.Capabilities.Bounding {
|
|
||||||
caps[cap] = append(caps[cap], "bounding")
|
|
||||||
}
|
|
||||||
for _, cap := range process.Capabilities.Effective {
|
|
||||||
caps[cap] = append(caps[cap], "effective")
|
|
||||||
}
|
|
||||||
for _, cap := range process.Capabilities.Inheritable {
|
|
||||||
caps[cap] = append(caps[cap], "inheritable")
|
|
||||||
}
|
|
||||||
for _, cap := range process.Capabilities.Permitted {
|
|
||||||
caps[cap] = append(caps[cap], "permitted")
|
|
||||||
}
|
|
||||||
for _, cap := range process.Capabilities.Ambient {
|
|
||||||
caps[cap] = append(caps[cap], "ambient")
|
|
||||||
}
|
|
||||||
|
|
||||||
for capability, owns := range caps {
|
|
||||||
if err := CapValid(capability, v.HostSpecific); err != nil {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("capability %q is not valid, man capabilities(7)", capability))
|
|
||||||
}
|
|
||||||
|
|
||||||
effective, permitted, ambient, inheritable = false, false, false, false
|
|
||||||
for _, set := range owns {
|
|
||||||
if set == "effective" {
|
|
||||||
effective = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if set == "inheritable" {
|
|
||||||
inheritable = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if set == "permitted" {
|
|
||||||
permitted = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if set == "ambient" {
|
|
||||||
ambient = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if effective && !permitted {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("effective capability %q is not allowed, as it's not permitted", capability))
|
|
||||||
}
|
|
||||||
if ambient && !(permitted && inheritable) {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("ambient capability %q is not allowed, as it's not permitted and inheribate", capability))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckRlimits checks v.spec.Process.Rlimits
|
|
||||||
func (v *Validator) CheckRlimits() (errs error) {
|
|
||||||
if v.platform != "linux" && v.platform != "solaris" {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("For %q platform, the configuration structure does not support process.rlimits", v.platform))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
process := v.spec.Process
|
|
||||||
for index, rlimit := range process.Rlimits {
|
|
||||||
for i := index + 1; i < len(process.Rlimits); i++ {
|
|
||||||
if process.Rlimits[index].Type == process.Rlimits[i].Type {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(
|
|
||||||
specerror.PosixProcRlimitsErrorOnDup,
|
|
||||||
fmt.Errorf("rlimit can not contain the same type %q",
|
|
||||||
process.Rlimits[index].Type),
|
|
||||||
rspec.Version))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
errs = multierror.Append(errs, v.rlimitValid(rlimit))
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func supportedMountTypes(OS string, hostSpecific bool) (map[string]bool, error) {
|
|
||||||
supportedTypes := make(map[string]bool)
|
|
||||||
|
|
||||||
if OS != "linux" && OS != "windows" {
|
|
||||||
logrus.Warnf("%v is not supported to check mount type", OS)
|
|
||||||
return nil, nil
|
|
||||||
} else if OS == "windows" {
|
|
||||||
supportedTypes["ntfs"] = true
|
|
||||||
return supportedTypes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if hostSpecific {
|
|
||||||
f, err := os.Open("/proc/filesystems")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
s := bufio.NewScanner(f)
|
|
||||||
for s.Scan() {
|
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
return supportedTypes, err
|
|
||||||
}
|
|
||||||
|
|
||||||
text := s.Text()
|
|
||||||
parts := strings.Split(text, "\t")
|
|
||||||
if len(parts) > 1 {
|
|
||||||
supportedTypes[parts[1]] = true
|
|
||||||
} else {
|
|
||||||
supportedTypes[parts[0]] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
supportedTypes["bind"] = true
|
|
||||||
|
|
||||||
return supportedTypes, nil
|
|
||||||
}
|
|
||||||
logrus.Warn("Checking linux mount types without --host-specific is not supported yet")
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckMounts checks v.spec.Mounts
|
|
||||||
func (v *Validator) CheckMounts() (errs error) {
|
|
||||||
logrus.Debugf("check mounts")
|
|
||||||
|
|
||||||
supportedTypes, err := supportedMountTypes(v.platform, v.HostSpecific)
|
|
||||||
if err != nil {
|
|
||||||
errs = multierror.Append(errs, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, mountA := range v.spec.Mounts {
|
|
||||||
if supportedTypes != nil && !supportedTypes[mountA.Type] {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("unsupported mount type %q", mountA.Type))
|
|
||||||
}
|
|
||||||
if !osFilepath.IsAbs(v.platform, mountA.Destination) {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(
|
|
||||||
specerror.MountsDestAbs,
|
|
||||||
fmt.Errorf("mounts[%d].destination %q is not absolute",
|
|
||||||
i,
|
|
||||||
mountA.Destination),
|
|
||||||
rspec.Version))
|
|
||||||
}
|
|
||||||
for j, mountB := range v.spec.Mounts {
|
|
||||||
if i == j {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// whether B.Desination is nested within A.Destination
|
|
||||||
nested, err := osFilepath.IsAncestor(v.platform, mountA.Destination, mountB.Destination, ".")
|
|
||||||
if err != nil {
|
|
||||||
errs = multierror.Append(errs, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if nested {
|
|
||||||
if v.platform == "windows" && i < j {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(
|
|
||||||
specerror.MountsDestOnWindowsNotNested,
|
|
||||||
fmt.Errorf("on Windows, %v nested within %v is forbidden",
|
|
||||||
mountB.Destination, mountA.Destination),
|
|
||||||
rspec.Version))
|
|
||||||
}
|
|
||||||
if i > j {
|
|
||||||
logrus.Warnf("%v will be covered by %v", mountB.Destination, mountA.Destination)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckPlatform checks v.platform
|
|
||||||
func (v *Validator) CheckPlatform() (errs error) {
|
|
||||||
logrus.Debugf("check platform")
|
|
||||||
|
|
||||||
if v.platform != "linux" && v.platform != "solaris" && v.platform != "windows" {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("platform %q is not supported", v.platform))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.HostSpecific && v.platform != runtime.GOOS {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("platform %q differs from the host %q, skipping host-specific checks", v.platform, runtime.GOOS))
|
|
||||||
v.HostSpecific = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.platform == "windows" {
|
|
||||||
if v.spec.Windows == nil {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(
|
|
||||||
specerror.PlatformSpecConfOnWindowsSet,
|
|
||||||
fmt.Errorf("'windows' MUST be set when platform is `windows`"),
|
|
||||||
rspec.Version))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckLinuxResources checks v.spec.Linux.Resources
|
|
||||||
func (v *Validator) CheckLinuxResources() (errs error) {
|
|
||||||
logrus.Debugf("check linux resources")
|
|
||||||
|
|
||||||
r := v.spec.Linux.Resources
|
|
||||||
if r.Memory != nil {
|
|
||||||
if r.Memory.Limit != nil && r.Memory.Swap != nil && uint64(*r.Memory.Limit) > uint64(*r.Memory.Swap) {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("minimum memoryswap should be larger than memory limit"))
|
|
||||||
}
|
|
||||||
if r.Memory.Limit != nil && r.Memory.Reservation != nil && uint64(*r.Memory.Reservation) > uint64(*r.Memory.Limit) {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("minimum memory limit should be larger than memory reservation"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if r.Network != nil && v.HostSpecific {
|
|
||||||
var exist bool
|
|
||||||
interfaces, err := net.Interfaces()
|
|
||||||
if err != nil {
|
|
||||||
errs = multierror.Append(errs, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, prio := range r.Network.Priorities {
|
|
||||||
exist = false
|
|
||||||
for _, ni := range interfaces {
|
|
||||||
if prio.Name == ni.Name {
|
|
||||||
exist = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !exist {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("interface %s does not exist currently", prio.Name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for index := 0; index < len(r.Devices); index++ {
|
|
||||||
switch r.Devices[index].Type {
|
|
||||||
case "a", "b", "c", "":
|
|
||||||
default:
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("type of devices %s is invalid", r.Devices[index].Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
access := []byte(r.Devices[index].Access)
|
|
||||||
for i := 0; i < len(access); i++ {
|
|
||||||
switch access[i] {
|
|
||||||
case 'r', 'w', 'm':
|
|
||||||
default:
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("access %s is invalid", r.Devices[index].Access))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.BlockIO != nil && r.BlockIO.WeightDevice != nil {
|
|
||||||
for i, weightDevice := range r.BlockIO.WeightDevice {
|
|
||||||
if weightDevice.Weight == nil && weightDevice.LeafWeight == nil {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(
|
|
||||||
specerror.BlkIOWeightOrLeafWeightExist,
|
|
||||||
fmt.Errorf("linux.resources.blockIO.weightDevice[%d] specifies neither weight nor leafWeight", i),
|
|
||||||
rspec.Version))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckAnnotations checks v.spec.Annotations
|
|
||||||
func (v *Validator) CheckAnnotations() (errs error) {
|
|
||||||
logrus.Debugf("check annotations")
|
|
||||||
|
|
||||||
reversedDomain := regexp.MustCompile(`^[A-Za-z]{2,6}(\.[A-Za-z0-9-]{1,63})+$`)
|
|
||||||
for key := range v.spec.Annotations {
|
|
||||||
if strings.HasPrefix(key, "org.opencontainers") {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(
|
|
||||||
specerror.AnnotationsKeyReservedNS,
|
|
||||||
fmt.Errorf("key %q is reserved", key),
|
|
||||||
rspec.Version))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reversedDomain.MatchString(key) {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(
|
|
||||||
specerror.AnnotationsKeyReversedDomain,
|
|
||||||
fmt.Errorf("key %q SHOULD be named using a reverse domain notation", key),
|
|
||||||
rspec.Version))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// CapValid checks whether a capability is valid
|
|
||||||
func CapValid(c string, hostSpecific bool) error {
|
|
||||||
isValid := false
|
|
||||||
|
|
||||||
if !strings.HasPrefix(c, "CAP_") {
|
|
||||||
return fmt.Errorf("capability %s must start with CAP_", c)
|
|
||||||
}
|
|
||||||
for _, cap := range capability.List() {
|
|
||||||
if c == fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())) {
|
|
||||||
if hostSpecific && cap > LastCap() {
|
|
||||||
return fmt.Errorf("%s is not supported on the current host", c)
|
|
||||||
}
|
|
||||||
isValid = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isValid {
|
|
||||||
return fmt.Errorf("invalid capability: %s", c)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func envValid(env string) bool {
|
|
||||||
items := strings.Split(env, "=")
|
|
||||||
if len(items) < 2 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, ch := range strings.TrimSpace(items[0]) {
|
|
||||||
if !unicode.IsDigit(ch) && !unicode.IsLetter(ch) && ch != '_' {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if i == 0 && unicode.IsDigit(ch) {
|
|
||||||
logrus.Warnf("Env %v: variable name beginning with digit is not recommended.", env)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *Validator) rlimitValid(rlimit rspec.POSIXRlimit) (errs error) {
|
|
||||||
if rlimit.Hard < rlimit.Soft {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("hard limit of rlimit %s should not be less than soft limit", rlimit.Type))
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.platform == "linux" {
|
|
||||||
for _, val := range linuxRlimits {
|
|
||||||
if val == rlimit.Type {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
errs = multierror.Append(errs, specerror.NewError(specerror.PosixProcRlimitsTypeValueError, fmt.Errorf("rlimit type %q may not be valid", rlimit.Type), v.spec.Version))
|
|
||||||
} else if v.platform == "solaris" {
|
|
||||||
for _, val := range posixRlimits {
|
|
||||||
if val == rlimit.Type {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
errs = multierror.Append(errs, specerror.NewError(specerror.PosixProcRlimitsTypeValueError, fmt.Errorf("rlimit type %q may not be valid", rlimit.Type), v.spec.Version))
|
|
||||||
} else {
|
|
||||||
logrus.Warnf("process.rlimits validation not yet implemented for platform %q", v.platform)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func isStruct(t reflect.Type) bool {
|
|
||||||
return t.Kind() == reflect.Struct
|
|
||||||
}
|
|
||||||
|
|
||||||
func isStructPtr(t reflect.Type) bool {
|
|
||||||
return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkMandatoryUnit(field reflect.Value, tagField reflect.StructField, parent string) (errs error) {
|
|
||||||
mandatory := !strings.Contains(tagField.Tag.Get("json"), "omitempty")
|
|
||||||
switch field.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
if mandatory && field.IsNil() {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("'%s.%s' should not be empty", parent, tagField.Name))
|
|
||||||
}
|
|
||||||
case reflect.String:
|
|
||||||
if mandatory && (field.Len() == 0) {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("'%s.%s' should not be empty", parent, tagField.Name))
|
|
||||||
}
|
|
||||||
case reflect.Slice:
|
|
||||||
if mandatory && (field.IsNil() || field.Len() == 0) {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("'%s.%s' should not be empty", parent, tagField.Name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for index := 0; index < field.Len(); index++ {
|
|
||||||
mValue := field.Index(index)
|
|
||||||
if mValue.CanInterface() {
|
|
||||||
errs = multierror.Append(errs, checkMandatory(mValue.Interface()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Map:
|
|
||||||
if mandatory && (field.IsNil() || field.Len() == 0) {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("'%s.%s' should not be empty", parent, tagField.Name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
keys := field.MapKeys()
|
|
||||||
for index := 0; index < len(keys); index++ {
|
|
||||||
mValue := field.MapIndex(keys[index])
|
|
||||||
if mValue.CanInterface() {
|
|
||||||
errs = multierror.Append(errs, checkMandatory(mValue.Interface()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkMandatory(obj interface{}) (errs error) {
|
|
||||||
objT := reflect.TypeOf(obj)
|
|
||||||
objV := reflect.ValueOf(obj)
|
|
||||||
if isStructPtr(objT) {
|
|
||||||
objT = objT.Elem()
|
|
||||||
objV = objV.Elem()
|
|
||||||
} else if !isStruct(objT) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < objT.NumField(); i++ {
|
|
||||||
t := objT.Field(i).Type
|
|
||||||
if isStructPtr(t) && objV.Field(i).IsNil() {
|
|
||||||
if !strings.Contains(objT.Field(i).Tag.Get("json"), "omitempty") {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("'%s.%s' should not be empty", objT.Name(), objT.Field(i).Name))
|
|
||||||
}
|
|
||||||
} else if (isStruct(t) || isStructPtr(t)) && objV.Field(i).CanInterface() {
|
|
||||||
errs = multierror.Append(errs, checkMandatory(objV.Field(i).Interface()))
|
|
||||||
} else {
|
|
||||||
errs = multierror.Append(errs, checkMandatoryUnit(objV.Field(i), objT.Field(i), objT.Name()))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckMandatoryFields checks mandatory field of container's config file
|
|
||||||
func (v *Validator) CheckMandatoryFields() error {
|
|
||||||
logrus.Debugf("check mandatory fields")
|
|
||||||
|
|
||||||
if v.spec == nil {
|
|
||||||
return fmt.Errorf("Spec can't be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkMandatory(v.spec)
|
|
||||||
}
|
|
237
vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go
generated
vendored
237
vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go
generated
vendored
@ -1,237 +0,0 @@
|
|||||||
// +build linux
|
|
||||||
|
|
||||||
package validate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/syndtr/gocapability/capability"
|
|
||||||
|
|
||||||
multierror "github.com/hashicorp/go-multierror"
|
|
||||||
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
|
||||||
osFilepath "github.com/opencontainers/runtime-tools/filepath"
|
|
||||||
"github.com/opencontainers/runtime-tools/specerror"
|
|
||||||
"github.com/opencontainers/selinux/go-selinux/label"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LastCap return last cap of system
|
|
||||||
func LastCap() capability.Cap {
|
|
||||||
last := capability.CAP_LAST_CAP
|
|
||||||
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
|
|
||||||
if last == capability.Cap(63) {
|
|
||||||
last = capability.CAP_BLOCK_SUSPEND
|
|
||||||
}
|
|
||||||
|
|
||||||
return last
|
|
||||||
}
|
|
||||||
|
|
||||||
func deviceValid(d rspec.LinuxDevice) bool {
|
|
||||||
switch d.Type {
|
|
||||||
case "b", "c", "u":
|
|
||||||
if d.Major <= 0 || d.Minor <= 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
case "p":
|
|
||||||
if d.Major != 0 || d.Minor != 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckLinux checks v.spec.Linux
|
|
||||||
func (v *Validator) CheckLinux() (errs error) {
|
|
||||||
logrus.Debugf("check linux")
|
|
||||||
|
|
||||||
if v.spec.Linux == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var nsTypeList = map[rspec.LinuxNamespaceType]struct {
|
|
||||||
num int
|
|
||||||
newExist bool
|
|
||||||
}{
|
|
||||||
rspec.PIDNamespace: {0, false},
|
|
||||||
rspec.NetworkNamespace: {0, false},
|
|
||||||
rspec.MountNamespace: {0, false},
|
|
||||||
rspec.IPCNamespace: {0, false},
|
|
||||||
rspec.UTSNamespace: {0, false},
|
|
||||||
rspec.UserNamespace: {0, false},
|
|
||||||
rspec.CgroupNamespace: {0, false},
|
|
||||||
}
|
|
||||||
|
|
||||||
for index := 0; index < len(v.spec.Linux.Namespaces); index++ {
|
|
||||||
ns := v.spec.Linux.Namespaces[index]
|
|
||||||
if ns.Path != "" && !osFilepath.IsAbs(v.platform, ns.Path) {
|
|
||||||
errs = multierror.Append(errs, specerror.NewError(specerror.NSPathAbs, fmt.Errorf("namespace.path %q is not an absolute path", ns.Path), rspec.Version))
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpItem := nsTypeList[ns.Type]
|
|
||||||
tmpItem.num = tmpItem.num + 1
|
|
||||||
if tmpItem.num > 1 {
|
|
||||||
errs = multierror.Append(errs, specerror.NewError(specerror.NSErrorOnDup, fmt.Errorf("duplicated namespace %q", ns.Type), rspec.Version))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ns.Path) == 0 {
|
|
||||||
tmpItem.newExist = true
|
|
||||||
}
|
|
||||||
nsTypeList[ns.Type] = tmpItem
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len(v.spec.Linux.UIDMappings) > 0 || len(v.spec.Linux.GIDMappings) > 0) && !nsTypeList[rspec.UserNamespace].newExist {
|
|
||||||
errs = multierror.Append(errs, errors.New("the UID/GID mappings requires a new User namespace to be specified as well"))
|
|
||||||
}
|
|
||||||
|
|
||||||
for k := range v.spec.Linux.Sysctl {
|
|
||||||
if strings.HasPrefix(k, "net.") && !nsTypeList[rspec.NetworkNamespace].newExist {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("sysctl %v requires a new Network namespace to be specified as well", k))
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(k, "fs.mqueue.") {
|
|
||||||
if !nsTypeList[rspec.MountNamespace].newExist || !nsTypeList[rspec.IPCNamespace].newExist {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("sysctl %v requires a new IPC namespace and Mount namespace to be specified as well", k))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.platform == "linux" && !nsTypeList[rspec.UTSNamespace].newExist && v.spec.Hostname != "" {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("on Linux, hostname requires a new UTS namespace to be specified as well"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Linux devices validation
|
|
||||||
devList := make(map[string]bool)
|
|
||||||
devTypeList := make(map[string]bool)
|
|
||||||
for index := 0; index < len(v.spec.Linux.Devices); index++ {
|
|
||||||
device := v.spec.Linux.Devices[index]
|
|
||||||
if !deviceValid(device) {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("device %v is invalid", device))
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, exists := devList[device.Path]; exists {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("device %s is duplicated", device.Path))
|
|
||||||
} else {
|
|
||||||
var rootfsPath string
|
|
||||||
if filepath.IsAbs(v.spec.Root.Path) {
|
|
||||||
rootfsPath = v.spec.Root.Path
|
|
||||||
} else {
|
|
||||||
rootfsPath = filepath.Join(v.bundlePath, v.spec.Root.Path)
|
|
||||||
}
|
|
||||||
absPath := filepath.Join(rootfsPath, device.Path)
|
|
||||||
fi, err := os.Stat(absPath)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
devList[device.Path] = true
|
|
||||||
} else if err != nil {
|
|
||||||
errs = multierror.Append(errs, err)
|
|
||||||
} else {
|
|
||||||
fStat, ok := fi.Sys().(*syscall.Stat_t)
|
|
||||||
if !ok {
|
|
||||||
errs = multierror.Append(errs, specerror.NewError(specerror.DevicesAvailable,
|
|
||||||
fmt.Errorf("cannot determine state for device %s", device.Path), rspec.Version))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var devType string
|
|
||||||
switch fStat.Mode & syscall.S_IFMT {
|
|
||||||
case syscall.S_IFCHR:
|
|
||||||
devType = "c"
|
|
||||||
case syscall.S_IFBLK:
|
|
||||||
devType = "b"
|
|
||||||
case syscall.S_IFIFO:
|
|
||||||
devType = "p"
|
|
||||||
default:
|
|
||||||
devType = "unmatched"
|
|
||||||
}
|
|
||||||
if devType != device.Type || (devType == "c" && device.Type == "u") {
|
|
||||||
errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch,
|
|
||||||
fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if devType != "p" {
|
|
||||||
dev := fStat.Rdev
|
|
||||||
major := (dev >> 8) & 0xfff
|
|
||||||
minor := (dev & 0xff) | ((dev >> 12) & 0xfff00)
|
|
||||||
if int64(major) != device.Major || int64(minor) != device.Minor {
|
|
||||||
errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch,
|
|
||||||
fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if device.FileMode != nil {
|
|
||||||
expectedPerm := *device.FileMode & os.ModePerm
|
|
||||||
actualPerm := fi.Mode() & os.ModePerm
|
|
||||||
if expectedPerm != actualPerm {
|
|
||||||
errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch,
|
|
||||||
fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if device.UID != nil {
|
|
||||||
if *device.UID != fStat.Uid {
|
|
||||||
errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch,
|
|
||||||
fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if device.GID != nil {
|
|
||||||
if *device.GID != fStat.Gid {
|
|
||||||
errs = multierror.Append(errs, specerror.NewError(specerror.DevicesFileNotMatch,
|
|
||||||
fmt.Errorf("unmatched %s already exists in filesystem", device.Path), rspec.Version))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// unify u->c when comparing, they are synonyms
|
|
||||||
var devID string
|
|
||||||
if device.Type == "u" {
|
|
||||||
devID = fmt.Sprintf("%s:%d:%d", "c", device.Major, device.Minor)
|
|
||||||
} else {
|
|
||||||
devID = fmt.Sprintf("%s:%d:%d", device.Type, device.Major, device.Minor)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, exists := devTypeList[devID]; exists {
|
|
||||||
logrus.Warnf("%v", specerror.NewError(specerror.DevicesErrorOnDup, fmt.Errorf("type:%s, major:%d and minor:%d for linux devices is duplicated", device.Type, device.Major, device.Minor), rspec.Version))
|
|
||||||
} else {
|
|
||||||
devTypeList[devID] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.spec.Linux.Resources != nil {
|
|
||||||
errs = multierror.Append(errs, v.CheckLinuxResources())
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, maskedPath := range v.spec.Linux.MaskedPaths {
|
|
||||||
if !strings.HasPrefix(maskedPath, "/") {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(
|
|
||||||
specerror.MaskedPathsAbs,
|
|
||||||
fmt.Errorf("maskedPath %v is not an absolute path", maskedPath),
|
|
||||||
rspec.Version))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, readonlyPath := range v.spec.Linux.ReadonlyPaths {
|
|
||||||
if !strings.HasPrefix(readonlyPath, "/") {
|
|
||||||
errs = multierror.Append(errs,
|
|
||||||
specerror.NewError(
|
|
||||||
specerror.ReadonlyPathsAbs,
|
|
||||||
fmt.Errorf("readonlyPath %v is not an absolute path", readonlyPath),
|
|
||||||
rspec.Version))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.spec.Linux.MountLabel != "" {
|
|
||||||
if err := label.Validate(v.spec.Linux.MountLabel); err != nil {
|
|
||||||
errs = multierror.Append(errs, fmt.Errorf("mountLabel %v is invalid", v.spec.Linux.MountLabel))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
202
vendor/github.com/xeipuuv/gojsonpointer/LICENSE-APACHE-2.0.txt
generated
vendored
202
vendor/github.com/xeipuuv/gojsonpointer/LICENSE-APACHE-2.0.txt
generated
vendored
@ -1,202 +0,0 @@
|
|||||||
|
|
||||||
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 2015 xeipuuv
|
|
||||||
|
|
||||||
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.
|
|
41
vendor/github.com/xeipuuv/gojsonpointer/README.md
generated
vendored
41
vendor/github.com/xeipuuv/gojsonpointer/README.md
generated
vendored
@ -1,41 +0,0 @@
|
|||||||
# gojsonpointer
|
|
||||||
An implementation of JSON Pointer - Go language
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
jsonText := `{
|
|
||||||
"name": "Bobby B",
|
|
||||||
"occupation": {
|
|
||||||
"title" : "King",
|
|
||||||
"years" : 15,
|
|
||||||
"heir" : "Joffrey B"
|
|
||||||
}
|
|
||||||
}`
|
|
||||||
|
|
||||||
var jsonDocument map[string]interface{}
|
|
||||||
json.Unmarshal([]byte(jsonText), &jsonDocument)
|
|
||||||
|
|
||||||
//create a JSON pointer
|
|
||||||
pointerString := "/occupation/title"
|
|
||||||
pointer, _ := NewJsonPointer(pointerString)
|
|
||||||
|
|
||||||
//SET a new value for the "title" in the document
|
|
||||||
pointer.Set(jsonDocument, "Supreme Leader of Westeros")
|
|
||||||
|
|
||||||
//GET the new "title" from the document
|
|
||||||
title, _, _ := pointer.Get(jsonDocument)
|
|
||||||
fmt.Println(title) //outputs "Supreme Leader of Westeros"
|
|
||||||
|
|
||||||
//DELETE the "heir" from the document
|
|
||||||
deletePointer := NewJsonPointer("/occupation/heir")
|
|
||||||
deletePointer.Delete(jsonDocument)
|
|
||||||
|
|
||||||
b, _ := json.Marshal(jsonDocument)
|
|
||||||
fmt.Println(string(b))
|
|
||||||
//outputs `{"name":"Bobby B","occupation":{"title":"Supreme Leader of Westeros","years":15}}`
|
|
||||||
|
|
||||||
|
|
||||||
## References
|
|
||||||
http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
|
|
||||||
|
|
||||||
### Note
|
|
||||||
The 4.Evaluation part of the previous reference, starting with 'If the currently referenced value is a JSON array, the reference token MUST contain either...' is not implemented.
|
|
211
vendor/github.com/xeipuuv/gojsonpointer/pointer.go
generated
vendored
211
vendor/github.com/xeipuuv/gojsonpointer/pointer.go
generated
vendored
@ -1,211 +0,0 @@
|
|||||||
// Copyright 2015 xeipuuv ( https://github.com/xeipuuv )
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// author xeipuuv
|
|
||||||
// author-github https://github.com/xeipuuv
|
|
||||||
// author-mail xeipuuv@gmail.com
|
|
||||||
//
|
|
||||||
// repository-name gojsonpointer
|
|
||||||
// repository-desc An implementation of JSON Pointer - Go language
|
|
||||||
//
|
|
||||||
// description Main and unique file.
|
|
||||||
//
|
|
||||||
// created 25-02-2013
|
|
||||||
|
|
||||||
package gojsonpointer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
const_empty_pointer = ``
|
|
||||||
const_pointer_separator = `/`
|
|
||||||
|
|
||||||
const_invalid_start = `JSON pointer must be empty or start with a "` + const_pointer_separator + `"`
|
|
||||||
)
|
|
||||||
|
|
||||||
type implStruct struct {
|
|
||||||
mode string // "SET" or "GET"
|
|
||||||
|
|
||||||
inDocument interface{}
|
|
||||||
|
|
||||||
setInValue interface{}
|
|
||||||
|
|
||||||
getOutNode interface{}
|
|
||||||
getOutKind reflect.Kind
|
|
||||||
outError error
|
|
||||||
}
|
|
||||||
|
|
||||||
type JsonPointer struct {
|
|
||||||
referenceTokens []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewJsonPointer parses the given string JSON pointer and returns an object
|
|
||||||
func NewJsonPointer(jsonPointerString string) (p JsonPointer, err error) {
|
|
||||||
|
|
||||||
// Pointer to the root of the document
|
|
||||||
if len(jsonPointerString) == 0 {
|
|
||||||
// Keep referenceTokens nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if jsonPointerString[0] != '/' {
|
|
||||||
return p, errors.New(const_invalid_start)
|
|
||||||
}
|
|
||||||
|
|
||||||
p.referenceTokens = strings.Split(jsonPointerString[1:], const_pointer_separator)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uses the pointer to retrieve a value from a JSON document
|
|
||||||
func (p *JsonPointer) Get(document interface{}) (interface{}, reflect.Kind, error) {
|
|
||||||
|
|
||||||
is := &implStruct{mode: "GET", inDocument: document}
|
|
||||||
p.implementation(is)
|
|
||||||
return is.getOutNode, is.getOutKind, is.outError
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uses the pointer to update a value from a JSON document
|
|
||||||
func (p *JsonPointer) Set(document interface{}, value interface{}) (interface{}, error) {
|
|
||||||
|
|
||||||
is := &implStruct{mode: "SET", inDocument: document, setInValue: value}
|
|
||||||
p.implementation(is)
|
|
||||||
return document, is.outError
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uses the pointer to delete a value from a JSON document
|
|
||||||
func (p *JsonPointer) Delete(document interface{}) (interface{}, error) {
|
|
||||||
is := &implStruct{mode: "DEL", inDocument: document}
|
|
||||||
p.implementation(is)
|
|
||||||
return document, is.outError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Both Get and Set functions use the same implementation to avoid code duplication
|
|
||||||
func (p *JsonPointer) implementation(i *implStruct) {
|
|
||||||
|
|
||||||
kind := reflect.Invalid
|
|
||||||
|
|
||||||
// Full document when empty
|
|
||||||
if len(p.referenceTokens) == 0 {
|
|
||||||
i.getOutNode = i.inDocument
|
|
||||||
i.outError = nil
|
|
||||||
i.getOutKind = kind
|
|
||||||
i.outError = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
node := i.inDocument
|
|
||||||
|
|
||||||
previousNodes := make([]interface{}, len(p.referenceTokens))
|
|
||||||
previousTokens := make([]string, len(p.referenceTokens))
|
|
||||||
|
|
||||||
for ti, token := range p.referenceTokens {
|
|
||||||
|
|
||||||
isLastToken := ti == len(p.referenceTokens)-1
|
|
||||||
previousNodes[ti] = node
|
|
||||||
previousTokens[ti] = token
|
|
||||||
|
|
||||||
switch v := node.(type) {
|
|
||||||
|
|
||||||
case map[string]interface{}:
|
|
||||||
decodedToken := decodeReferenceToken(token)
|
|
||||||
if _, ok := v[decodedToken]; ok {
|
|
||||||
node = v[decodedToken]
|
|
||||||
if isLastToken && i.mode == "SET" {
|
|
||||||
v[decodedToken] = i.setInValue
|
|
||||||
} else if isLastToken && i.mode =="DEL" {
|
|
||||||
delete(v,decodedToken)
|
|
||||||
}
|
|
||||||
} else if (isLastToken && i.mode == "SET") {
|
|
||||||
v[decodedToken] = i.setInValue
|
|
||||||
} else {
|
|
||||||
i.outError = fmt.Errorf("Object has no key '%s'", decodedToken)
|
|
||||||
i.getOutKind = reflect.Map
|
|
||||||
i.getOutNode = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case []interface{}:
|
|
||||||
tokenIndex, err := strconv.Atoi(token)
|
|
||||||
if err != nil {
|
|
||||||
i.outError = fmt.Errorf("Invalid array index '%s'", token)
|
|
||||||
i.getOutKind = reflect.Slice
|
|
||||||
i.getOutNode = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if tokenIndex < 0 || tokenIndex >= len(v) {
|
|
||||||
i.outError = fmt.Errorf("Out of bound array[0,%d] index '%d'", len(v), tokenIndex)
|
|
||||||
i.getOutKind = reflect.Slice
|
|
||||||
i.getOutNode = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
node = v[tokenIndex]
|
|
||||||
if isLastToken && i.mode == "SET" {
|
|
||||||
v[tokenIndex] = i.setInValue
|
|
||||||
} else if isLastToken && i.mode =="DEL" {
|
|
||||||
v[tokenIndex] = v[len(v)-1]
|
|
||||||
v[len(v)-1] = nil
|
|
||||||
v = v[:len(v)-1]
|
|
||||||
previousNodes[ti-1].(map[string]interface{})[previousTokens[ti-1]] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
i.outError = fmt.Errorf("Invalid token reference '%s'", token)
|
|
||||||
i.getOutKind = reflect.ValueOf(node).Kind()
|
|
||||||
i.getOutNode = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
i.getOutNode = node
|
|
||||||
i.getOutKind = reflect.ValueOf(node).Kind()
|
|
||||||
i.outError = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pointer to string representation function
|
|
||||||
func (p *JsonPointer) String() string {
|
|
||||||
|
|
||||||
if len(p.referenceTokens) == 0 {
|
|
||||||
return const_empty_pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
pointerString := const_pointer_separator + strings.Join(p.referenceTokens, const_pointer_separator)
|
|
||||||
|
|
||||||
return pointerString
|
|
||||||
}
|
|
||||||
|
|
||||||
// Specific JSON pointer encoding here
|
|
||||||
// ~0 => ~
|
|
||||||
// ~1 => /
|
|
||||||
// ... and vice versa
|
|
||||||
|
|
||||||
func decodeReferenceToken(token string) string {
|
|
||||||
step1 := strings.Replace(token, `~1`, `/`, -1)
|
|
||||||
step2 := strings.Replace(step1, `~0`, `~`, -1)
|
|
||||||
return step2
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeReferenceToken(token string) string {
|
|
||||||
step1 := strings.Replace(token, `~`, `~0`, -1)
|
|
||||||
step2 := strings.Replace(step1, `/`, `~1`, -1)
|
|
||||||
return step2
|
|
||||||
}
|
|
202
vendor/github.com/xeipuuv/gojsonreference/LICENSE-APACHE-2.0.txt
generated
vendored
202
vendor/github.com/xeipuuv/gojsonreference/LICENSE-APACHE-2.0.txt
generated
vendored
@ -1,202 +0,0 @@
|
|||||||
|
|
||||||
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 2015 xeipuuv
|
|
||||||
|
|
||||||
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.
|
|
10
vendor/github.com/xeipuuv/gojsonreference/README.md
generated
vendored
10
vendor/github.com/xeipuuv/gojsonreference/README.md
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
# gojsonreference
|
|
||||||
An implementation of JSON Reference - Go language
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
https://github.com/xeipuuv/gojsonpointer
|
|
||||||
|
|
||||||
## References
|
|
||||||
http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
|
|
||||||
|
|
||||||
http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03
|
|
147
vendor/github.com/xeipuuv/gojsonreference/reference.go
generated
vendored
147
vendor/github.com/xeipuuv/gojsonreference/reference.go
generated
vendored
@ -1,147 +0,0 @@
|
|||||||
// Copyright 2015 xeipuuv ( https://github.com/xeipuuv )
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// author xeipuuv
|
|
||||||
// author-github https://github.com/xeipuuv
|
|
||||||
// author-mail xeipuuv@gmail.com
|
|
||||||
//
|
|
||||||
// repository-name gojsonreference
|
|
||||||
// repository-desc An implementation of JSON Reference - Go language
|
|
||||||
//
|
|
||||||
// description Main and unique file.
|
|
||||||
//
|
|
||||||
// created 26-02-2013
|
|
||||||
|
|
||||||
package gojsonreference
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"net/url"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/xeipuuv/gojsonpointer"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
const_fragment_char = `#`
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewJsonReference(jsonReferenceString string) (JsonReference, error) {
|
|
||||||
|
|
||||||
var r JsonReference
|
|
||||||
err := r.parse(jsonReferenceString)
|
|
||||||
return r, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type JsonReference struct {
|
|
||||||
referenceUrl *url.URL
|
|
||||||
referencePointer gojsonpointer.JsonPointer
|
|
||||||
|
|
||||||
HasFullUrl bool
|
|
||||||
HasUrlPathOnly bool
|
|
||||||
HasFragmentOnly bool
|
|
||||||
HasFileScheme bool
|
|
||||||
HasFullFilePath bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *JsonReference) GetUrl() *url.URL {
|
|
||||||
return r.referenceUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *JsonReference) GetPointer() *gojsonpointer.JsonPointer {
|
|
||||||
return &r.referencePointer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *JsonReference) String() string {
|
|
||||||
|
|
||||||
if r.referenceUrl != nil {
|
|
||||||
return r.referenceUrl.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.HasFragmentOnly {
|
|
||||||
return const_fragment_char + r.referencePointer.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.referencePointer.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *JsonReference) IsCanonical() bool {
|
|
||||||
return (r.HasFileScheme && r.HasFullFilePath) || (!r.HasFileScheme && r.HasFullUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
// "Constructor", parses the given string JSON reference
|
|
||||||
func (r *JsonReference) parse(jsonReferenceString string) (err error) {
|
|
||||||
|
|
||||||
r.referenceUrl, err = url.Parse(jsonReferenceString)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
refUrl := r.referenceUrl
|
|
||||||
|
|
||||||
if refUrl.Scheme != "" && refUrl.Host != "" {
|
|
||||||
r.HasFullUrl = true
|
|
||||||
} else {
|
|
||||||
if refUrl.Path != "" {
|
|
||||||
r.HasUrlPathOnly = true
|
|
||||||
} else if refUrl.RawQuery == "" && refUrl.Fragment != "" {
|
|
||||||
r.HasFragmentOnly = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r.HasFileScheme = refUrl.Scheme == "file"
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
// on Windows, a file URL may have an extra leading slash, and if it
|
|
||||||
// doesn't then its first component will be treated as the host by the
|
|
||||||
// Go runtime
|
|
||||||
if refUrl.Host == "" && strings.HasPrefix(refUrl.Path, "/") {
|
|
||||||
r.HasFullFilePath = filepath.IsAbs(refUrl.Path[1:])
|
|
||||||
} else {
|
|
||||||
r.HasFullFilePath = filepath.IsAbs(refUrl.Host + refUrl.Path)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r.HasFullFilePath = filepath.IsAbs(refUrl.Path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// invalid json-pointer error means url has no json-pointer fragment. simply ignore error
|
|
||||||
r.referencePointer, _ = gojsonpointer.NewJsonPointer(refUrl.Fragment)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a new reference from a parent and a child
|
|
||||||
// If the child cannot inherit from the parent, an error is returned
|
|
||||||
func (r *JsonReference) Inherits(child JsonReference) (*JsonReference, error) {
|
|
||||||
if child.GetUrl() == nil {
|
|
||||||
return nil, errors.New("childUrl is nil!")
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.GetUrl() == nil {
|
|
||||||
return nil, errors.New("parentUrl is nil!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a copy of the parent url to make sure we do not modify the original.
|
|
||||||
// URL reference resolving fails if the fragment of the child is empty, but the parent's is not.
|
|
||||||
// The fragment of the child must be used, so the fragment of the parent is manually removed.
|
|
||||||
parentUrl := *r.GetUrl()
|
|
||||||
parentUrl.Fragment = ""
|
|
||||||
|
|
||||||
ref, err := NewJsonReference(parentUrl.ResolveReference(child.GetUrl()).String())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &ref, err
|
|
||||||
}
|
|
3
vendor/github.com/xeipuuv/gojsonschema/.gitignore
generated
vendored
3
vendor/github.com/xeipuuv/gojsonschema/.gitignore
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
*.sw[nop]
|
|
||||||
*.iml
|
|
||||||
.vscode/
|
|
9
vendor/github.com/xeipuuv/gojsonschema/.travis.yml
generated
vendored
9
vendor/github.com/xeipuuv/gojsonschema/.travis.yml
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
language: go
|
|
||||||
go:
|
|
||||||
- "1.11"
|
|
||||||
- "1.12"
|
|
||||||
- "1.13"
|
|
||||||
before_install:
|
|
||||||
- go get github.com/xeipuuv/gojsonreference
|
|
||||||
- go get github.com/xeipuuv/gojsonpointer
|
|
||||||
- go get github.com/stretchr/testify/assert
|
|
202
vendor/github.com/xeipuuv/gojsonschema/LICENSE-APACHE-2.0.txt
generated
vendored
202
vendor/github.com/xeipuuv/gojsonschema/LICENSE-APACHE-2.0.txt
generated
vendored
@ -1,202 +0,0 @@
|
|||||||
|
|
||||||
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 2015 xeipuuv
|
|
||||||
|
|
||||||
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.
|
|
466
vendor/github.com/xeipuuv/gojsonschema/README.md
generated
vendored
466
vendor/github.com/xeipuuv/gojsonschema/README.md
generated
vendored
@ -1,466 +0,0 @@
|
|||||||
[](https://godoc.org/github.com/xeipuuv/gojsonschema)
|
|
||||||
[](https://travis-ci.org/xeipuuv/gojsonschema)
|
|
||||||
[](https://goreportcard.com/report/github.com/xeipuuv/gojsonschema)
|
|
||||||
|
|
||||||
# gojsonschema
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
An implementation of JSON Schema for the Go programming language. Supports draft-04, draft-06 and draft-07.
|
|
||||||
|
|
||||||
References :
|
|
||||||
|
|
||||||
* http://json-schema.org
|
|
||||||
* http://json-schema.org/latest/json-schema-core.html
|
|
||||||
* http://json-schema.org/latest/json-schema-validation.html
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
```
|
|
||||||
go get github.com/xeipuuv/gojsonschema
|
|
||||||
```
|
|
||||||
|
|
||||||
Dependencies :
|
|
||||||
* [github.com/xeipuuv/gojsonpointer](https://github.com/xeipuuv/gojsonpointer)
|
|
||||||
* [github.com/xeipuuv/gojsonreference](https://github.com/xeipuuv/gojsonreference)
|
|
||||||
* [github.com/stretchr/testify/assert](https://github.com/stretchr/testify#assert-package)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
```go
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/xeipuuv/gojsonschema"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
schemaLoader := gojsonschema.NewReferenceLoader("file:///home/me/schema.json")
|
|
||||||
documentLoader := gojsonschema.NewReferenceLoader("file:///home/me/document.json")
|
|
||||||
|
|
||||||
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if result.Valid() {
|
|
||||||
fmt.Printf("The document is valid\n")
|
|
||||||
} else {
|
|
||||||
fmt.Printf("The document is not valid. see errors :\n")
|
|
||||||
for _, desc := range result.Errors() {
|
|
||||||
fmt.Printf("- %s\n", desc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Loaders
|
|
||||||
|
|
||||||
There are various ways to load your JSON data.
|
|
||||||
In order to load your schemas and documents,
|
|
||||||
first declare an appropriate loader :
|
|
||||||
|
|
||||||
* Web / HTTP, using a reference :
|
|
||||||
|
|
||||||
```go
|
|
||||||
loader := gojsonschema.NewReferenceLoader("http://www.some_host.com/schema.json")
|
|
||||||
```
|
|
||||||
|
|
||||||
* Local file, using a reference :
|
|
||||||
|
|
||||||
```go
|
|
||||||
loader := gojsonschema.NewReferenceLoader("file:///home/me/schema.json")
|
|
||||||
```
|
|
||||||
|
|
||||||
References use the URI scheme, the prefix (file://) and a full path to the file are required.
|
|
||||||
|
|
||||||
* JSON strings :
|
|
||||||
|
|
||||||
```go
|
|
||||||
loader := gojsonschema.NewStringLoader(`{"type": "string"}`)
|
|
||||||
```
|
|
||||||
|
|
||||||
* Custom Go types :
|
|
||||||
|
|
||||||
```go
|
|
||||||
m := map[string]interface{}{"type": "string"}
|
|
||||||
loader := gojsonschema.NewGoLoader(m)
|
|
||||||
```
|
|
||||||
|
|
||||||
And
|
|
||||||
|
|
||||||
```go
|
|
||||||
type Root struct {
|
|
||||||
Users []User `json:"users"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type User struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
data := Root{}
|
|
||||||
data.Users = append(data.Users, User{"John"})
|
|
||||||
data.Users = append(data.Users, User{"Sophia"})
|
|
||||||
data.Users = append(data.Users, User{"Bill"})
|
|
||||||
|
|
||||||
loader := gojsonschema.NewGoLoader(data)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Validation
|
|
||||||
|
|
||||||
Once the loaders are set, validation is easy :
|
|
||||||
|
|
||||||
```go
|
|
||||||
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively, you might want to load a schema only once and process to multiple validations :
|
|
||||||
|
|
||||||
```go
|
|
||||||
schema, err := gojsonschema.NewSchema(schemaLoader)
|
|
||||||
...
|
|
||||||
result1, err := schema.Validate(documentLoader1)
|
|
||||||
...
|
|
||||||
result2, err := schema.Validate(documentLoader2)
|
|
||||||
...
|
|
||||||
// etc ...
|
|
||||||
```
|
|
||||||
|
|
||||||
To check the result :
|
|
||||||
|
|
||||||
```go
|
|
||||||
if result.Valid() {
|
|
||||||
fmt.Printf("The document is valid\n")
|
|
||||||
} else {
|
|
||||||
fmt.Printf("The document is not valid. see errors :\n")
|
|
||||||
for _, err := range result.Errors() {
|
|
||||||
// Err implements the ResultError interface
|
|
||||||
fmt.Printf("- %s\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Loading local schemas
|
|
||||||
|
|
||||||
By default `file` and `http(s)` references to external schemas are loaded automatically via the file system or via http(s). An external schema can also be loaded using a `SchemaLoader`.
|
|
||||||
|
|
||||||
```go
|
|
||||||
sl := gojsonschema.NewSchemaLoader()
|
|
||||||
loader1 := gojsonschema.NewStringLoader(`{ "type" : "string" }`)
|
|
||||||
err := sl.AddSchema("http://some_host.com/string.json", loader1)
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively if your schema already has an `$id` you can use the `AddSchemas` function
|
|
||||||
```go
|
|
||||||
loader2 := gojsonschema.NewStringLoader(`{
|
|
||||||
"$id" : "http://some_host.com/maxlength.json",
|
|
||||||
"maxLength" : 5
|
|
||||||
}`)
|
|
||||||
err = sl.AddSchemas(loader2)
|
|
||||||
```
|
|
||||||
|
|
||||||
The main schema should be passed to the `Compile` function. This main schema can then directly reference the added schemas without needing to download them.
|
|
||||||
```go
|
|
||||||
loader3 := gojsonschema.NewStringLoader(`{
|
|
||||||
"$id" : "http://some_host.com/main.json",
|
|
||||||
"allOf" : [
|
|
||||||
{ "$ref" : "http://some_host.com/string.json" },
|
|
||||||
{ "$ref" : "http://some_host.com/maxlength.json" }
|
|
||||||
]
|
|
||||||
}`)
|
|
||||||
|
|
||||||
schema, err := sl.Compile(loader3)
|
|
||||||
|
|
||||||
documentLoader := gojsonschema.NewStringLoader(`"hello world"`)
|
|
||||||
|
|
||||||
result, err := schema.Validate(documentLoader)
|
|
||||||
```
|
|
||||||
|
|
||||||
It's also possible to pass a `ReferenceLoader` to the `Compile` function that references a loaded schema.
|
|
||||||
|
|
||||||
```go
|
|
||||||
err = sl.AddSchemas(loader3)
|
|
||||||
schema, err := sl.Compile(gojsonschema.NewReferenceLoader("http://some_host.com/main.json"))
|
|
||||||
```
|
|
||||||
|
|
||||||
Schemas added by `AddSchema` and `AddSchemas` are only validated when the entire schema is compiled, unless meta-schema validation is used.
|
|
||||||
|
|
||||||
## Using a specific draft
|
|
||||||
By default `gojsonschema` will try to detect the draft of a schema by using the `$schema` keyword and parse it in a strict draft-04, draft-06 or draft-07 mode. If `$schema` is missing, or the draft version is not explicitely set, a hybrid mode is used which merges together functionality of all drafts into one mode.
|
|
||||||
|
|
||||||
Autodectection can be turned off with the `AutoDetect` property. Specific draft versions can be specified with the `Draft` property.
|
|
||||||
|
|
||||||
```go
|
|
||||||
sl := gojsonschema.NewSchemaLoader()
|
|
||||||
sl.Draft = gojsonschema.Draft7
|
|
||||||
sl.AutoDetect = false
|
|
||||||
```
|
|
||||||
|
|
||||||
If autodetection is on (default), a draft-07 schema can savely reference draft-04 schemas and vice-versa, as long as `$schema` is specified in all schemas.
|
|
||||||
|
|
||||||
## Meta-schema validation
|
|
||||||
Schemas that are added using the `AddSchema`, `AddSchemas` and `Compile` can be validated against their meta-schema by setting the `Validate` property.
|
|
||||||
|
|
||||||
The following example will produce an error as `multipleOf` must be a number. If `Validate` is off (default), this error is only returned at the `Compile` step.
|
|
||||||
|
|
||||||
```go
|
|
||||||
sl := gojsonschema.NewSchemaLoader()
|
|
||||||
sl.Validate = true
|
|
||||||
err := sl.AddSchemas(gojsonschema.NewStringLoader(`{
|
|
||||||
$id" : "http://some_host.com/invalid.json",
|
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
||||||
"multipleOf" : true
|
|
||||||
}`))
|
|
||||||
```
|
|
||||||
```
|
|
||||||
```
|
|
||||||
|
|
||||||
Errors returned by meta-schema validation are more readable and contain more information, which helps significantly if you are developing a schema.
|
|
||||||
|
|
||||||
Meta-schema validation also works with a custom `$schema`. In case `$schema` is missing, or `AutoDetect` is set to `false`, the meta-schema of the used draft is used.
|
|
||||||
|
|
||||||
|
|
||||||
## Working with Errors
|
|
||||||
|
|
||||||
The library handles string error codes which you can customize by creating your own gojsonschema.locale and setting it
|
|
||||||
```go
|
|
||||||
gojsonschema.Locale = YourCustomLocale{}
|
|
||||||
```
|
|
||||||
|
|
||||||
However, each error contains additional contextual information.
|
|
||||||
|
|
||||||
Newer versions of `gojsonschema` may have new additional errors, so code that uses a custom locale will need to be updated when this happens.
|
|
||||||
|
|
||||||
**err.Type()**: *string* Returns the "type" of error that occurred. Note you can also type check. See below
|
|
||||||
|
|
||||||
Note: An error of RequiredType has an err.Type() return value of "required"
|
|
||||||
|
|
||||||
"required": RequiredError
|
|
||||||
"invalid_type": InvalidTypeError
|
|
||||||
"number_any_of": NumberAnyOfError
|
|
||||||
"number_one_of": NumberOneOfError
|
|
||||||
"number_all_of": NumberAllOfError
|
|
||||||
"number_not": NumberNotError
|
|
||||||
"missing_dependency": MissingDependencyError
|
|
||||||
"internal": InternalError
|
|
||||||
"const": ConstEror
|
|
||||||
"enum": EnumError
|
|
||||||
"array_no_additional_items": ArrayNoAdditionalItemsError
|
|
||||||
"array_min_items": ArrayMinItemsError
|
|
||||||
"array_max_items": ArrayMaxItemsError
|
|
||||||
"unique": ItemsMustBeUniqueError
|
|
||||||
"contains" : ArrayContainsError
|
|
||||||
"array_min_properties": ArrayMinPropertiesError
|
|
||||||
"array_max_properties": ArrayMaxPropertiesError
|
|
||||||
"additional_property_not_allowed": AdditionalPropertyNotAllowedError
|
|
||||||
"invalid_property_pattern": InvalidPropertyPatternError
|
|
||||||
"invalid_property_name": InvalidPropertyNameError
|
|
||||||
"string_gte": StringLengthGTEError
|
|
||||||
"string_lte": StringLengthLTEError
|
|
||||||
"pattern": DoesNotMatchPatternError
|
|
||||||
"multiple_of": MultipleOfError
|
|
||||||
"number_gte": NumberGTEError
|
|
||||||
"number_gt": NumberGTError
|
|
||||||
"number_lte": NumberLTEError
|
|
||||||
"number_lt": NumberLTError
|
|
||||||
"condition_then" : ConditionThenError
|
|
||||||
"condition_else" : ConditionElseError
|
|
||||||
|
|
||||||
**err.Value()**: *interface{}* Returns the value given
|
|
||||||
|
|
||||||
**err.Context()**: *gojsonschema.JsonContext* Returns the context. This has a String() method that will print something like this: (root).firstName
|
|
||||||
|
|
||||||
**err.Field()**: *string* Returns the fieldname in the format firstName, or for embedded properties, person.firstName. This returns the same as the String() method on *err.Context()* but removes the (root). prefix.
|
|
||||||
|
|
||||||
**err.Description()**: *string* The error description. This is based on the locale you are using. See the beginning of this section for overwriting the locale with a custom implementation.
|
|
||||||
|
|
||||||
**err.DescriptionFormat()**: *string* The error description format. This is relevant if you are adding custom validation errors afterwards to the result.
|
|
||||||
|
|
||||||
**err.Details()**: *gojsonschema.ErrorDetails* Returns a map[string]interface{} of additional error details specific to the error. For example, GTE errors will have a "min" value, LTE will have a "max" value. See errors.go for a full description of all the error details. Every error always contains a "field" key that holds the value of *err.Field()*
|
|
||||||
|
|
||||||
Note in most cases, the err.Details() will be used to generate replacement strings in your locales, and not used directly. These strings follow the text/template format i.e.
|
|
||||||
```
|
|
||||||
{{.field}} must be greater than or equal to {{.min}}
|
|
||||||
```
|
|
||||||
|
|
||||||
The library allows you to specify custom template functions, should you require more complex error message handling.
|
|
||||||
```go
|
|
||||||
gojsonschema.ErrorTemplateFuncs = map[string]interface{}{
|
|
||||||
"allcaps": func(s string) string {
|
|
||||||
return strings.ToUpper(s)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Given the above definition, you can use the custom function `"allcaps"` in your localization templates:
|
|
||||||
```
|
|
||||||
{{allcaps .field}} must be greater than or equal to {{.min}}
|
|
||||||
```
|
|
||||||
|
|
||||||
The above error message would then be rendered with the `field` value in capital letters. For example:
|
|
||||||
```
|
|
||||||
"PASSWORD must be greater than or equal to 8"
|
|
||||||
```
|
|
||||||
|
|
||||||
Learn more about what types of template functions you can use in `ErrorTemplateFuncs` by referring to Go's [text/template FuncMap](https://golang.org/pkg/text/template/#FuncMap) type.
|
|
||||||
|
|
||||||
## Formats
|
|
||||||
JSON Schema allows for optional "format" property to validate instances against well-known formats. gojsonschema ships with all of the formats defined in the spec that you can use like this:
|
|
||||||
|
|
||||||
````json
|
|
||||||
{"type": "string", "format": "email"}
|
|
||||||
````
|
|
||||||
|
|
||||||
Not all formats defined in draft-07 are available. Implemented formats are:
|
|
||||||
|
|
||||||
* `date`
|
|
||||||
* `time`
|
|
||||||
* `date-time`
|
|
||||||
* `hostname`. Subdomains that start with a number are also supported, but this means that it doesn't strictly follow [RFC1034](http://tools.ietf.org/html/rfc1034#section-3.5) and has the implication that ipv4 addresses are also recognized as valid hostnames.
|
|
||||||
* `email`. Go's email parser deviates slightly from [RFC5322](https://tools.ietf.org/html/rfc5322). Includes unicode support.
|
|
||||||
* `idn-email`. Same caveat as `email`.
|
|
||||||
* `ipv4`
|
|
||||||
* `ipv6`
|
|
||||||
* `uri`. Includes unicode support.
|
|
||||||
* `uri-reference`. Includes unicode support.
|
|
||||||
* `iri`
|
|
||||||
* `iri-reference`
|
|
||||||
* `uri-template`
|
|
||||||
* `uuid`
|
|
||||||
* `regex`. Go uses the [RE2](https://github.com/google/re2/wiki/Syntax) engine and is not [ECMA262](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf) compatible.
|
|
||||||
* `json-pointer`
|
|
||||||
* `relative-json-pointer`
|
|
||||||
|
|
||||||
`email`, `uri` and `uri-reference` use the same validation code as their unicode counterparts `idn-email`, `iri` and `iri-reference`. If you rely on unicode support you should use the specific
|
|
||||||
unicode enabled formats for the sake of interoperability as other implementations might not support unicode in the regular formats.
|
|
||||||
|
|
||||||
The validation code for `uri`, `idn-email` and their relatives use mostly standard library code.
|
|
||||||
|
|
||||||
For repetitive or more complex formats, you can create custom format checkers and add them to gojsonschema like this:
|
|
||||||
|
|
||||||
```go
|
|
||||||
// Define the format checker
|
|
||||||
type RoleFormatChecker struct {}
|
|
||||||
|
|
||||||
// Ensure it meets the gojsonschema.FormatChecker interface
|
|
||||||
func (f RoleFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if ok == false {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.HasPrefix("ROLE_", asString)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add it to the library
|
|
||||||
gojsonschema.FormatCheckers.Add("role", RoleFormatChecker{})
|
|
||||||
````
|
|
||||||
|
|
||||||
Now to use in your json schema:
|
|
||||||
````json
|
|
||||||
{"type": "string", "format": "role"}
|
|
||||||
````
|
|
||||||
|
|
||||||
Another example would be to check if the provided integer matches an id on database:
|
|
||||||
|
|
||||||
JSON schema:
|
|
||||||
```json
|
|
||||||
{"type": "integer", "format": "ValidUserId"}
|
|
||||||
```
|
|
||||||
|
|
||||||
```go
|
|
||||||
// Define the format checker
|
|
||||||
type ValidUserIdFormatChecker struct {}
|
|
||||||
|
|
||||||
// Ensure it meets the gojsonschema.FormatChecker interface
|
|
||||||
func (f ValidUserIdFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
|
|
||||||
asFloat64, ok := input.(float64) // Numbers are always float64 here
|
|
||||||
if ok == false {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX
|
|
||||||
// do the magic on the database looking for the int(asFloat64)
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add it to the library
|
|
||||||
gojsonschema.FormatCheckers.Add("ValidUserId", ValidUserIdFormatChecker{})
|
|
||||||
````
|
|
||||||
|
|
||||||
Formats can also be removed, for example if you want to override one of the formats that is defined by default.
|
|
||||||
|
|
||||||
```go
|
|
||||||
gojsonschema.FormatCheckers.Remove("hostname")
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Additional custom validation
|
|
||||||
After the validation has run and you have the results, you may add additional
|
|
||||||
errors using `Result.AddError`. This is useful to maintain the same format within the resultset instead
|
|
||||||
of having to add special exceptions for your own errors. Below is an example.
|
|
||||||
|
|
||||||
```go
|
|
||||||
type AnswerInvalidError struct {
|
|
||||||
gojsonschema.ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
func newAnswerInvalidError(context *gojsonschema.JsonContext, value interface{}, details gojsonschema.ErrorDetails) *AnswerInvalidError {
|
|
||||||
err := AnswerInvalidError{}
|
|
||||||
err.SetContext(context)
|
|
||||||
err.SetType("custom_invalid_error")
|
|
||||||
// it is important to use SetDescriptionFormat() as this is used to call SetDescription() after it has been parsed
|
|
||||||
// using the description of err will be overridden by this.
|
|
||||||
err.SetDescriptionFormat("Answer to the Ultimate Question of Life, the Universe, and Everything is {{.answer}}")
|
|
||||||
err.SetValue(value)
|
|
||||||
err.SetDetails(details)
|
|
||||||
|
|
||||||
return &err
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// ...
|
|
||||||
schema, err := gojsonschema.NewSchema(schemaLoader)
|
|
||||||
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
|
|
||||||
|
|
||||||
if true { // some validation
|
|
||||||
jsonContext := gojsonschema.NewJsonContext("question", nil)
|
|
||||||
errDetail := gojsonschema.ErrorDetails{
|
|
||||||
"answer": 42,
|
|
||||||
}
|
|
||||||
result.AddError(
|
|
||||||
newAnswerInvalidError(
|
|
||||||
gojsonschema.NewJsonContext("answer", jsonContext),
|
|
||||||
52,
|
|
||||||
errDetail,
|
|
||||||
),
|
|
||||||
errDetail,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, err
|
|
||||||
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This is especially useful if you want to add validation beyond what the
|
|
||||||
json schema drafts can provide such business specific logic.
|
|
||||||
|
|
||||||
## Uses
|
|
||||||
|
|
||||||
gojsonschema uses the following test suite :
|
|
||||||
|
|
||||||
https://github.com/json-schema/JSON-Schema-Test-Suite
|
|
125
vendor/github.com/xeipuuv/gojsonschema/draft.go
generated
vendored
125
vendor/github.com/xeipuuv/gojsonschema/draft.go
generated
vendored
@ -1,125 +0,0 @@
|
|||||||
// Copyright 2018 johandorland ( https://github.com/johandorland )
|
|
||||||
//
|
|
||||||
// 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 gojsonschema
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/xeipuuv/gojsonreference"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Draft is a JSON-schema draft version
|
|
||||||
type Draft int
|
|
||||||
|
|
||||||
// Supported Draft versions
|
|
||||||
const (
|
|
||||||
Draft4 Draft = 4
|
|
||||||
Draft6 Draft = 6
|
|
||||||
Draft7 Draft = 7
|
|
||||||
Hybrid Draft = math.MaxInt32
|
|
||||||
)
|
|
||||||
|
|
||||||
type draftConfig struct {
|
|
||||||
Version Draft
|
|
||||||
MetaSchemaURL string
|
|
||||||
MetaSchema string
|
|
||||||
}
|
|
||||||
type draftConfigs []draftConfig
|
|
||||||
|
|
||||||
var drafts draftConfigs
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
drafts = []draftConfig{
|
|
||||||
{
|
|
||||||
Version: Draft4,
|
|
||||||
MetaSchemaURL: "http://json-schema.org/draft-04/schema",
|
|
||||||
MetaSchema: `{"id":"http://json-schema.org/draft-04/schema#","$schema":"http://json-schema.org/draft-04/schema#","description":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"positiveInteger":{"type":"integer","minimum":0},"positiveIntegerDefault0":{"allOf":[{"$ref":"#/definitions/positiveInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"minItems":1,"uniqueItems":true}},"type":"object","properties":{"id":{"type":"string"},"$schema":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":{},"multipleOf":{"type":"number","minimum":0,"exclusiveMinimum":true},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"boolean","default":false},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"boolean","default":false},"maxLength":{"$ref":"#/definitions/positiveInteger"},"minLength":{"$ref":"#/definitions/positiveIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":{}},"maxItems":{"$ref":"#/definitions/positiveInteger"},"minItems":{"$ref":"#/definitions/positiveIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"maxProperties":{"$ref":"#/definitions/positiveInteger"},"minProperties":{"$ref":"#/definitions/positiveIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"enum":{"type":"array","minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"dependencies":{"exclusiveMaximum":["maximum"],"exclusiveMinimum":["minimum"]},"default":{}}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Version: Draft6,
|
|
||||||
MetaSchemaURL: "http://json-schema.org/draft-06/schema",
|
|
||||||
MetaSchema: `{"$schema":"http://json-schema.org/draft-06/schema#","$id":"http://json-schema.org/draft-06/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"title":{"type":"string"},"description":{"type":"string"},"default":{},"examples":{"type":"array","items":{}},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":{}},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":{},"enum":{"type":"array","minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":{}}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Version: Draft7,
|
|
||||||
MetaSchemaURL: "http://json-schema.org/draft-07/schema",
|
|
||||||
MetaSchema: `{"$schema":"http://json-schema.org/draft-07/schema#","$id":"http://json-schema.org/draft-07/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"$comment":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":true,"readOnly":{"type":"boolean","default":false},"examples":{"type":"array","items":true},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":true},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"propertyNames":{"format":"regex"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":true,"enum":{"type":"array","items":true,"minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"contentMediaType":{"type":"string"},"contentEncoding":{"type":"string"},"if":{"$ref":"#"},"then":{"$ref":"#"},"else":{"$ref":"#"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":true}`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc draftConfigs) GetMetaSchema(url string) string {
|
|
||||||
for _, config := range dc {
|
|
||||||
if config.MetaSchemaURL == url {
|
|
||||||
return config.MetaSchema
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
func (dc draftConfigs) GetDraftVersion(url string) *Draft {
|
|
||||||
for _, config := range dc {
|
|
||||||
if config.MetaSchemaURL == url {
|
|
||||||
return &config.Version
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (dc draftConfigs) GetSchemaURL(draft Draft) string {
|
|
||||||
for _, config := range dc {
|
|
||||||
if config.Version == draft {
|
|
||||||
return config.MetaSchemaURL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseSchemaURL(documentNode interface{}) (string, *Draft, error) {
|
|
||||||
|
|
||||||
if isKind(documentNode, reflect.Bool) {
|
|
||||||
return "", nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isKind(documentNode, reflect.Map) {
|
|
||||||
return "", nil, errors.New("schema is invalid")
|
|
||||||
}
|
|
||||||
|
|
||||||
m := documentNode.(map[string]interface{})
|
|
||||||
|
|
||||||
if existsMapKey(m, KEY_SCHEMA) {
|
|
||||||
if !isKind(m[KEY_SCHEMA], reflect.String) {
|
|
||||||
return "", nil, errors.New(formatErrorDescription(
|
|
||||||
Locale.MustBeOfType(),
|
|
||||||
ErrorDetails{
|
|
||||||
"key": KEY_SCHEMA,
|
|
||||||
"type": TYPE_STRING,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
schemaReference, err := gojsonreference.NewJsonReference(m[KEY_SCHEMA].(string))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
schema := schemaReference.String()
|
|
||||||
|
|
||||||
return schema, drafts.GetDraftVersion(schema), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", nil, nil
|
|
||||||
}
|
|
364
vendor/github.com/xeipuuv/gojsonschema/errors.go
generated
vendored
364
vendor/github.com/xeipuuv/gojsonschema/errors.go
generated
vendored
@ -1,364 +0,0 @@
|
|||||||
package gojsonschema
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"sync"
|
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
var errorTemplates = errorTemplate{template.New("errors-new"), sync.RWMutex{}}
|
|
||||||
|
|
||||||
// template.Template is not thread-safe for writing, so some locking is done
|
|
||||||
// sync.RWMutex is used for efficiently locking when new templates are created
|
|
||||||
type errorTemplate struct {
|
|
||||||
*template.Template
|
|
||||||
sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
type (
|
|
||||||
|
|
||||||
// FalseError. ErrorDetails: -
|
|
||||||
FalseError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// RequiredError indicates that a required field is missing
|
|
||||||
// ErrorDetails: property string
|
|
||||||
RequiredError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvalidTypeError indicates that a field has the incorrect type
|
|
||||||
// ErrorDetails: expected, given
|
|
||||||
InvalidTypeError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumberAnyOfError is produced in case of a failing "anyOf" validation
|
|
||||||
// ErrorDetails: -
|
|
||||||
NumberAnyOfError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumberOneOfError is produced in case of a failing "oneOf" validation
|
|
||||||
// ErrorDetails: -
|
|
||||||
NumberOneOfError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumberAllOfError is produced in case of a failing "allOf" validation
|
|
||||||
// ErrorDetails: -
|
|
||||||
NumberAllOfError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumberNotError is produced if a "not" validation failed
|
|
||||||
// ErrorDetails: -
|
|
||||||
NumberNotError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// MissingDependencyError is produced in case of a "missing dependency" problem
|
|
||||||
// ErrorDetails: dependency
|
|
||||||
MissingDependencyError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// InternalError indicates an internal error
|
|
||||||
// ErrorDetails: error
|
|
||||||
InternalError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConstError indicates a const error
|
|
||||||
// ErrorDetails: allowed
|
|
||||||
ConstError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnumError indicates an enum error
|
|
||||||
// ErrorDetails: allowed
|
|
||||||
EnumError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArrayNoAdditionalItemsError is produced if additional items were found, but not allowed
|
|
||||||
// ErrorDetails: -
|
|
||||||
ArrayNoAdditionalItemsError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArrayMinItemsError is produced if an array contains less items than the allowed minimum
|
|
||||||
// ErrorDetails: min
|
|
||||||
ArrayMinItemsError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArrayMaxItemsError is produced if an array contains more items than the allowed maximum
|
|
||||||
// ErrorDetails: max
|
|
||||||
ArrayMaxItemsError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// ItemsMustBeUniqueError is produced if an array requires unique items, but contains non-unique items
|
|
||||||
// ErrorDetails: type, i, j
|
|
||||||
ItemsMustBeUniqueError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArrayContainsError is produced if an array contains invalid items
|
|
||||||
// ErrorDetails:
|
|
||||||
ArrayContainsError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArrayMinPropertiesError is produced if an object contains less properties than the allowed minimum
|
|
||||||
// ErrorDetails: min
|
|
||||||
ArrayMinPropertiesError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArrayMaxPropertiesError is produced if an object contains more properties than the allowed maximum
|
|
||||||
// ErrorDetails: max
|
|
||||||
ArrayMaxPropertiesError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// AdditionalPropertyNotAllowedError is produced if an object has additional properties, but not allowed
|
|
||||||
// ErrorDetails: property
|
|
||||||
AdditionalPropertyNotAllowedError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvalidPropertyPatternError is produced if an pattern was found
|
|
||||||
// ErrorDetails: property, pattern
|
|
||||||
InvalidPropertyPatternError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvalidPropertyNameError is produced if an invalid-named property was found
|
|
||||||
// ErrorDetails: property
|
|
||||||
InvalidPropertyNameError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringLengthGTEError is produced if a string is shorter than the minimum required length
|
|
||||||
// ErrorDetails: min
|
|
||||||
StringLengthGTEError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringLengthLTEError is produced if a string is longer than the maximum allowed length
|
|
||||||
// ErrorDetails: max
|
|
||||||
StringLengthLTEError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoesNotMatchPatternError is produced if a string does not match the defined pattern
|
|
||||||
// ErrorDetails: pattern
|
|
||||||
DoesNotMatchPatternError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// DoesNotMatchFormatError is produced if a string does not match the defined format
|
|
||||||
// ErrorDetails: format
|
|
||||||
DoesNotMatchFormatError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// MultipleOfError is produced if a number is not a multiple of the defined multipleOf
|
|
||||||
// ErrorDetails: multiple
|
|
||||||
MultipleOfError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumberGTEError is produced if a number is lower than the allowed minimum
|
|
||||||
// ErrorDetails: min
|
|
||||||
NumberGTEError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumberGTError is produced if a number is lower than, or equal to the specified minimum, and exclusiveMinimum is set
|
|
||||||
// ErrorDetails: min
|
|
||||||
NumberGTError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumberLTEError is produced if a number is higher than the allowed maximum
|
|
||||||
// ErrorDetails: max
|
|
||||||
NumberLTEError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumberLTError is produced if a number is higher than, or equal to the specified maximum, and exclusiveMaximum is set
|
|
||||||
// ErrorDetails: max
|
|
||||||
NumberLTError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConditionThenError is produced if a condition's "then" validation is invalid
|
|
||||||
// ErrorDetails: -
|
|
||||||
ConditionThenError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConditionElseError is produced if a condition's "else" condition is invalid
|
|
||||||
// ErrorDetails: -
|
|
||||||
ConditionElseError struct {
|
|
||||||
ResultErrorFields
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// newError takes a ResultError type and sets the type, context, description, details, value, and field
|
|
||||||
func newError(err ResultError, context *JsonContext, value interface{}, locale locale, details ErrorDetails) {
|
|
||||||
var t string
|
|
||||||
var d string
|
|
||||||
switch err.(type) {
|
|
||||||
case *FalseError:
|
|
||||||
t = "false"
|
|
||||||
d = locale.False()
|
|
||||||
case *RequiredError:
|
|
||||||
t = "required"
|
|
||||||
d = locale.Required()
|
|
||||||
case *InvalidTypeError:
|
|
||||||
t = "invalid_type"
|
|
||||||
d = locale.InvalidType()
|
|
||||||
case *NumberAnyOfError:
|
|
||||||
t = "number_any_of"
|
|
||||||
d = locale.NumberAnyOf()
|
|
||||||
case *NumberOneOfError:
|
|
||||||
t = "number_one_of"
|
|
||||||
d = locale.NumberOneOf()
|
|
||||||
case *NumberAllOfError:
|
|
||||||
t = "number_all_of"
|
|
||||||
d = locale.NumberAllOf()
|
|
||||||
case *NumberNotError:
|
|
||||||
t = "number_not"
|
|
||||||
d = locale.NumberNot()
|
|
||||||
case *MissingDependencyError:
|
|
||||||
t = "missing_dependency"
|
|
||||||
d = locale.MissingDependency()
|
|
||||||
case *InternalError:
|
|
||||||
t = "internal"
|
|
||||||
d = locale.Internal()
|
|
||||||
case *ConstError:
|
|
||||||
t = "const"
|
|
||||||
d = locale.Const()
|
|
||||||
case *EnumError:
|
|
||||||
t = "enum"
|
|
||||||
d = locale.Enum()
|
|
||||||
case *ArrayNoAdditionalItemsError:
|
|
||||||
t = "array_no_additional_items"
|
|
||||||
d = locale.ArrayNoAdditionalItems()
|
|
||||||
case *ArrayMinItemsError:
|
|
||||||
t = "array_min_items"
|
|
||||||
d = locale.ArrayMinItems()
|
|
||||||
case *ArrayMaxItemsError:
|
|
||||||
t = "array_max_items"
|
|
||||||
d = locale.ArrayMaxItems()
|
|
||||||
case *ItemsMustBeUniqueError:
|
|
||||||
t = "unique"
|
|
||||||
d = locale.Unique()
|
|
||||||
case *ArrayContainsError:
|
|
||||||
t = "contains"
|
|
||||||
d = locale.ArrayContains()
|
|
||||||
case *ArrayMinPropertiesError:
|
|
||||||
t = "array_min_properties"
|
|
||||||
d = locale.ArrayMinProperties()
|
|
||||||
case *ArrayMaxPropertiesError:
|
|
||||||
t = "array_max_properties"
|
|
||||||
d = locale.ArrayMaxProperties()
|
|
||||||
case *AdditionalPropertyNotAllowedError:
|
|
||||||
t = "additional_property_not_allowed"
|
|
||||||
d = locale.AdditionalPropertyNotAllowed()
|
|
||||||
case *InvalidPropertyPatternError:
|
|
||||||
t = "invalid_property_pattern"
|
|
||||||
d = locale.InvalidPropertyPattern()
|
|
||||||
case *InvalidPropertyNameError:
|
|
||||||
t = "invalid_property_name"
|
|
||||||
d = locale.InvalidPropertyName()
|
|
||||||
case *StringLengthGTEError:
|
|
||||||
t = "string_gte"
|
|
||||||
d = locale.StringGTE()
|
|
||||||
case *StringLengthLTEError:
|
|
||||||
t = "string_lte"
|
|
||||||
d = locale.StringLTE()
|
|
||||||
case *DoesNotMatchPatternError:
|
|
||||||
t = "pattern"
|
|
||||||
d = locale.DoesNotMatchPattern()
|
|
||||||
case *DoesNotMatchFormatError:
|
|
||||||
t = "format"
|
|
||||||
d = locale.DoesNotMatchFormat()
|
|
||||||
case *MultipleOfError:
|
|
||||||
t = "multiple_of"
|
|
||||||
d = locale.MultipleOf()
|
|
||||||
case *NumberGTEError:
|
|
||||||
t = "number_gte"
|
|
||||||
d = locale.NumberGTE()
|
|
||||||
case *NumberGTError:
|
|
||||||
t = "number_gt"
|
|
||||||
d = locale.NumberGT()
|
|
||||||
case *NumberLTEError:
|
|
||||||
t = "number_lte"
|
|
||||||
d = locale.NumberLTE()
|
|
||||||
case *NumberLTError:
|
|
||||||
t = "number_lt"
|
|
||||||
d = locale.NumberLT()
|
|
||||||
case *ConditionThenError:
|
|
||||||
t = "condition_then"
|
|
||||||
d = locale.ConditionThen()
|
|
||||||
case *ConditionElseError:
|
|
||||||
t = "condition_else"
|
|
||||||
d = locale.ConditionElse()
|
|
||||||
}
|
|
||||||
|
|
||||||
err.SetType(t)
|
|
||||||
err.SetContext(context)
|
|
||||||
err.SetValue(value)
|
|
||||||
err.SetDetails(details)
|
|
||||||
err.SetDescriptionFormat(d)
|
|
||||||
details["field"] = err.Field()
|
|
||||||
|
|
||||||
if _, exists := details["context"]; !exists && context != nil {
|
|
||||||
details["context"] = context.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
err.SetDescription(formatErrorDescription(err.DescriptionFormat(), details))
|
|
||||||
}
|
|
||||||
|
|
||||||
// formatErrorDescription takes a string in the default text/template
|
|
||||||
// format and converts it to a string with replacements. The fields come
|
|
||||||
// from the ErrorDetails struct and vary for each type of error.
|
|
||||||
func formatErrorDescription(s string, details ErrorDetails) string {
|
|
||||||
|
|
||||||
var tpl *template.Template
|
|
||||||
var descrAsBuffer bytes.Buffer
|
|
||||||
var err error
|
|
||||||
|
|
||||||
errorTemplates.RLock()
|
|
||||||
tpl = errorTemplates.Lookup(s)
|
|
||||||
errorTemplates.RUnlock()
|
|
||||||
|
|
||||||
if tpl == nil {
|
|
||||||
errorTemplates.Lock()
|
|
||||||
tpl = errorTemplates.New(s)
|
|
||||||
|
|
||||||
if ErrorTemplateFuncs != nil {
|
|
||||||
tpl.Funcs(ErrorTemplateFuncs)
|
|
||||||
}
|
|
||||||
|
|
||||||
tpl, err = tpl.Parse(s)
|
|
||||||
errorTemplates.Unlock()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tpl.Execute(&descrAsBuffer, details)
|
|
||||||
if err != nil {
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
return descrAsBuffer.String()
|
|
||||||
}
|
|
368
vendor/github.com/xeipuuv/gojsonschema/format_checkers.go
generated
vendored
368
vendor/github.com/xeipuuv/gojsonschema/format_checkers.go
generated
vendored
@ -1,368 +0,0 @@
|
|||||||
package gojsonschema
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"net/mail"
|
|
||||||
"net/url"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
// FormatChecker is the interface all formatters added to FormatCheckerChain must implement
|
|
||||||
FormatChecker interface {
|
|
||||||
// IsFormat checks if input has the correct format and type
|
|
||||||
IsFormat(input interface{}) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormatCheckerChain holds the formatters
|
|
||||||
FormatCheckerChain struct {
|
|
||||||
formatters map[string]FormatChecker
|
|
||||||
}
|
|
||||||
|
|
||||||
// EmailFormatChecker verifies email address formats
|
|
||||||
EmailFormatChecker struct{}
|
|
||||||
|
|
||||||
// IPV4FormatChecker verifies IP addresses in the IPv4 format
|
|
||||||
IPV4FormatChecker struct{}
|
|
||||||
|
|
||||||
// IPV6FormatChecker verifies IP addresses in the IPv6 format
|
|
||||||
IPV6FormatChecker struct{}
|
|
||||||
|
|
||||||
// DateTimeFormatChecker verifies date/time formats per RFC3339 5.6
|
|
||||||
//
|
|
||||||
// Valid formats:
|
|
||||||
// Partial Time: HH:MM:SS
|
|
||||||
// Full Date: YYYY-MM-DD
|
|
||||||
// Full Time: HH:MM:SSZ-07:00
|
|
||||||
// Date Time: YYYY-MM-DDTHH:MM:SSZ-0700
|
|
||||||
//
|
|
||||||
// Where
|
|
||||||
// YYYY = 4DIGIT year
|
|
||||||
// MM = 2DIGIT month ; 01-12
|
|
||||||
// DD = 2DIGIT day-month ; 01-28, 01-29, 01-30, 01-31 based on month/year
|
|
||||||
// HH = 2DIGIT hour ; 00-23
|
|
||||||
// MM = 2DIGIT ; 00-59
|
|
||||||
// SS = 2DIGIT ; 00-58, 00-60 based on leap second rules
|
|
||||||
// T = Literal
|
|
||||||
// Z = Literal
|
|
||||||
//
|
|
||||||
// Note: Nanoseconds are also suported in all formats
|
|
||||||
//
|
|
||||||
// http://tools.ietf.org/html/rfc3339#section-5.6
|
|
||||||
DateTimeFormatChecker struct{}
|
|
||||||
|
|
||||||
// DateFormatChecker verifies date formats
|
|
||||||
//
|
|
||||||
// Valid format:
|
|
||||||
// Full Date: YYYY-MM-DD
|
|
||||||
//
|
|
||||||
// Where
|
|
||||||
// YYYY = 4DIGIT year
|
|
||||||
// MM = 2DIGIT month ; 01-12
|
|
||||||
// DD = 2DIGIT day-month ; 01-28, 01-29, 01-30, 01-31 based on month/year
|
|
||||||
DateFormatChecker struct{}
|
|
||||||
|
|
||||||
// TimeFormatChecker verifies time formats
|
|
||||||
//
|
|
||||||
// Valid formats:
|
|
||||||
// Partial Time: HH:MM:SS
|
|
||||||
// Full Time: HH:MM:SSZ-07:00
|
|
||||||
//
|
|
||||||
// Where
|
|
||||||
// HH = 2DIGIT hour ; 00-23
|
|
||||||
// MM = 2DIGIT ; 00-59
|
|
||||||
// SS = 2DIGIT ; 00-58, 00-60 based on leap second rules
|
|
||||||
// T = Literal
|
|
||||||
// Z = Literal
|
|
||||||
TimeFormatChecker struct{}
|
|
||||||
|
|
||||||
// URIFormatChecker validates a URI with a valid Scheme per RFC3986
|
|
||||||
URIFormatChecker struct{}
|
|
||||||
|
|
||||||
// URIReferenceFormatChecker validates a URI or relative-reference per RFC3986
|
|
||||||
URIReferenceFormatChecker struct{}
|
|
||||||
|
|
||||||
// URITemplateFormatChecker validates a URI template per RFC6570
|
|
||||||
URITemplateFormatChecker struct{}
|
|
||||||
|
|
||||||
// HostnameFormatChecker validates a hostname is in the correct format
|
|
||||||
HostnameFormatChecker struct{}
|
|
||||||
|
|
||||||
// UUIDFormatChecker validates a UUID is in the correct format
|
|
||||||
UUIDFormatChecker struct{}
|
|
||||||
|
|
||||||
// RegexFormatChecker validates a regex is in the correct format
|
|
||||||
RegexFormatChecker struct{}
|
|
||||||
|
|
||||||
// JSONPointerFormatChecker validates a JSON Pointer per RFC6901
|
|
||||||
JSONPointerFormatChecker struct{}
|
|
||||||
|
|
||||||
// RelativeJSONPointerFormatChecker validates a relative JSON Pointer is in the correct format
|
|
||||||
RelativeJSONPointerFormatChecker struct{}
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// FormatCheckers holds the valid formatters, and is a public variable
|
|
||||||
// so library users can add custom formatters
|
|
||||||
FormatCheckers = FormatCheckerChain{
|
|
||||||
formatters: map[string]FormatChecker{
|
|
||||||
"date": DateFormatChecker{},
|
|
||||||
"time": TimeFormatChecker{},
|
|
||||||
"date-time": DateTimeFormatChecker{},
|
|
||||||
"hostname": HostnameFormatChecker{},
|
|
||||||
"email": EmailFormatChecker{},
|
|
||||||
"idn-email": EmailFormatChecker{},
|
|
||||||
"ipv4": IPV4FormatChecker{},
|
|
||||||
"ipv6": IPV6FormatChecker{},
|
|
||||||
"uri": URIFormatChecker{},
|
|
||||||
"uri-reference": URIReferenceFormatChecker{},
|
|
||||||
"iri": URIFormatChecker{},
|
|
||||||
"iri-reference": URIReferenceFormatChecker{},
|
|
||||||
"uri-template": URITemplateFormatChecker{},
|
|
||||||
"uuid": UUIDFormatChecker{},
|
|
||||||
"regex": RegexFormatChecker{},
|
|
||||||
"json-pointer": JSONPointerFormatChecker{},
|
|
||||||
"relative-json-pointer": RelativeJSONPointerFormatChecker{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regex credit: https://www.socketloop.com/tutorials/golang-validate-hostname
|
|
||||||
rxHostname = regexp.MustCompile(`^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$`)
|
|
||||||
|
|
||||||
// Use a regex to make sure curly brackets are balanced properly after validating it as a AURI
|
|
||||||
rxURITemplate = regexp.MustCompile("^([^{]*({[^}]*})?)*$")
|
|
||||||
|
|
||||||
rxUUID = regexp.MustCompile("^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")
|
|
||||||
|
|
||||||
rxJSONPointer = regexp.MustCompile("^(?:/(?:[^~/]|~0|~1)*)*$")
|
|
||||||
|
|
||||||
rxRelJSONPointer = regexp.MustCompile("^(?:0|[1-9][0-9]*)(?:#|(?:/(?:[^~/]|~0|~1)*)*)$")
|
|
||||||
|
|
||||||
lock = new(sync.RWMutex)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Add adds a FormatChecker to the FormatCheckerChain
|
|
||||||
// The name used will be the value used for the format key in your json schema
|
|
||||||
func (c *FormatCheckerChain) Add(name string, f FormatChecker) *FormatCheckerChain {
|
|
||||||
lock.Lock()
|
|
||||||
c.formatters[name] = f
|
|
||||||
lock.Unlock()
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove deletes a FormatChecker from the FormatCheckerChain (if it exists)
|
|
||||||
func (c *FormatCheckerChain) Remove(name string) *FormatCheckerChain {
|
|
||||||
lock.Lock()
|
|
||||||
delete(c.formatters, name)
|
|
||||||
lock.Unlock()
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has checks to see if the FormatCheckerChain holds a FormatChecker with the given name
|
|
||||||
func (c *FormatCheckerChain) Has(name string) bool {
|
|
||||||
lock.RLock()
|
|
||||||
_, ok := c.formatters[name]
|
|
||||||
lock.RUnlock()
|
|
||||||
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat will check an input against a FormatChecker with the given name
|
|
||||||
// to see if it is the correct format
|
|
||||||
func (c *FormatCheckerChain) IsFormat(name string, input interface{}) bool {
|
|
||||||
lock.RLock()
|
|
||||||
f, ok := c.formatters[name]
|
|
||||||
lock.RUnlock()
|
|
||||||
|
|
||||||
// If a format is unrecognized it should always pass validation
|
|
||||||
if !ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return f.IsFormat(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input is a correctly formatted e-mail address
|
|
||||||
func (f EmailFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := mail.ParseAddress(asString)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input is a correctly formatted IPv4-address
|
|
||||||
func (f IPV4FormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Credit: https://github.com/asaskevich/govalidator
|
|
||||||
ip := net.ParseIP(asString)
|
|
||||||
return ip != nil && strings.Contains(asString, ".")
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input is a correctly formatted IPv6=address
|
|
||||||
func (f IPV6FormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Credit: https://github.com/asaskevich/govalidator
|
|
||||||
ip := net.ParseIP(asString)
|
|
||||||
return ip != nil && strings.Contains(asString, ":")
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input is a correctly formatted date/time per RFC3339 5.6
|
|
||||||
func (f DateTimeFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
formats := []string{
|
|
||||||
"15:04:05",
|
|
||||||
"15:04:05Z07:00",
|
|
||||||
"2006-01-02",
|
|
||||||
time.RFC3339,
|
|
||||||
time.RFC3339Nano,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, format := range formats {
|
|
||||||
if _, err := time.Parse(format, asString); err == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input is a correctly formatted date (YYYY-MM-DD)
|
|
||||||
func (f DateFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
_, err := time.Parse("2006-01-02", asString)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input correctly formatted time (HH:MM:SS or HH:MM:SSZ-07:00)
|
|
||||||
func (f TimeFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := time.Parse("15:04:05Z07:00", asString); err == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := time.Parse("15:04:05", asString)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input is correctly formatted URI with a valid Scheme per RFC3986
|
|
||||||
func (f URIFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
u, err := url.Parse(asString)
|
|
||||||
|
|
||||||
if err != nil || u.Scheme == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return !strings.Contains(asString, `\`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input is a correctly formatted URI or relative-reference per RFC3986
|
|
||||||
func (f URIReferenceFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := url.Parse(asString)
|
|
||||||
return err == nil && !strings.Contains(asString, `\`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input is a correctly formatted URI template per RFC6570
|
|
||||||
func (f URITemplateFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
u, err := url.Parse(asString)
|
|
||||||
if err != nil || strings.Contains(asString, `\`) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return rxURITemplate.MatchString(u.Path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input is a correctly formatted hostname
|
|
||||||
func (f HostnameFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return rxHostname.MatchString(asString) && len(asString) < 256
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input is a correctly formatted UUID
|
|
||||||
func (f UUIDFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return rxUUID.MatchString(asString)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input is a correctly formatted regular expression
|
|
||||||
func (f RegexFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if asString == "" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
_, err := regexp.Compile(asString)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input is a correctly formatted JSON Pointer per RFC6901
|
|
||||||
func (f JSONPointerFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return rxJSONPointer.MatchString(asString)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFormat checks if input is a correctly formatted relative JSON Pointer
|
|
||||||
func (f RelativeJSONPointerFormatChecker) IsFormat(input interface{}) bool {
|
|
||||||
asString, ok := input.(string)
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return rxRelJSONPointer.MatchString(asString)
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user