Merge pull request #838 from Random-Liu/add-auth-config
Add auth config
This commit is contained in:
commit
ca32566575
@ -1,4 +1,3 @@
|
|||||||
<!-- TODO(now) -->
|
|
||||||
# Install Containerd with Release Tarball
|
# Install Containerd with Release Tarball
|
||||||
This document provides the steps to install `containerd` and its dependencies with the release tarball, and bring up a Kubernetes cluster using kubeadm.
|
This document provides the steps to install `containerd` and its dependencies with the release tarball, and bring up a Kubernetes cluster using kubeadm.
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# Configure Image Registry
|
# Configure Image Registry
|
||||||
This document describes the method to configure the image registry for `containerd` for use with the `cri` plugin.
|
This document describes the method to configure the image registry for `containerd` for use with the `cri` plugin.
|
||||||
|
|
||||||
|
## Configure Registry Endpoint
|
||||||
With containerd, `docker.io` is the default image registry. You can also set up other image registries similar to docker.
|
With containerd, `docker.io` is the default image registry. You can also set up other image registries similar to docker.
|
||||||
|
|
||||||
To configure image registries create/modify the `/etc/containerd/config.toml` as follows:
|
To configure image registries create/modify the `/etc/containerd/config.toml` as follows:
|
||||||
@ -19,4 +20,26 @@ The default configuration can be generated by `containerd config default > /etc/
|
|||||||
The endpoint is a list that can contain multiple image registry URLs split by commas. When pulling an image
|
The endpoint is a list that can contain multiple image registry URLs split by commas. When pulling an image
|
||||||
from a registry, containerd will try these endpoint URLs one by one, and use the first working one.
|
from a registry, containerd will try these endpoint URLs one by one, and use the first working one.
|
||||||
|
|
||||||
After modify the config file, you need restart the `containerd` service.
|
After modify this config, you need restart the `containerd` service.
|
||||||
|
|
||||||
|
## Configure Registry Credentials
|
||||||
|
|
||||||
|
`cri` plugin also supports docker like registry credential config.
|
||||||
|
|
||||||
|
To configure a credential for a specific registry endpoint, create/modify the
|
||||||
|
`/etc/containerd/config.toml` as follows:
|
||||||
|
```toml
|
||||||
|
[plugins.cri.registry.auths]
|
||||||
|
[plugins.cri.registry.auths."https://gcr.io"]
|
||||||
|
username = ""
|
||||||
|
password = ""
|
||||||
|
auth = ""
|
||||||
|
identitytoken = ""
|
||||||
|
```
|
||||||
|
The meaning of each field is the same with the corresponding field in `.docker/config.json`.
|
||||||
|
|
||||||
|
Please note that auth config passed by CRI takes precedence over this config.
|
||||||
|
The registry credential in this config will only be used when auth config is
|
||||||
|
not specified by Kubernetes via CRI.
|
||||||
|
|
||||||
|
After modify this config, you need restart the `containerd` service.
|
||||||
|
@ -20,7 +20,7 @@ set -o pipefail
|
|||||||
for d in $(find . -type d -a \( -iwholename './pkg*' -o -iwholename './cmd*' \) -not -iwholename './pkg/api*'); do
|
for d in $(find . -type d -a \( -iwholename './pkg*' -o -iwholename './cmd*' \) -not -iwholename './pkg/api*'); do
|
||||||
echo for directory ${d} ...
|
echo for directory ${d} ...
|
||||||
gometalinter \
|
gometalinter \
|
||||||
--exclude='error return value not checked.*(Close|Log|Print).*\(errcheck\)$' \
|
--exclude='error return value not checked.*(Close|Log|Print|Fprint).*\(errcheck\)$' \
|
||||||
--exclude='.*_test\.go:.*error return value not checked.*\(errcheck\)$' \
|
--exclude='.*_test\.go:.*error return value not checked.*\(errcheck\)$' \
|
||||||
--exclude='duplicate of.*_test.go.*\(dupl\)$' \
|
--exclude='duplicate of.*_test.go.*\(dupl\)$' \
|
||||||
--exclude='.*/mock_.*\.go:.*\(golint\)$' \
|
--exclude='.*/mock_.*\.go:.*\(golint\)$' \
|
||||||
|
@ -61,16 +61,32 @@ type CniConfig struct {
|
|||||||
// Mirror contains the config related to the registry mirror
|
// Mirror contains the config related to the registry mirror
|
||||||
type Mirror struct {
|
type Mirror struct {
|
||||||
// Endpoints are endpoints for a namespace. CRI plugin will try the endpoints
|
// Endpoints are endpoints for a namespace. CRI plugin will try the endpoints
|
||||||
// one by one until a working one is found.
|
// one by one until a working one is found. The endpoint must be a valid url
|
||||||
|
// with host specified.
|
||||||
Endpoints []string `toml:"endpoint" json:"endpoint"`
|
Endpoints []string `toml:"endpoint" json:"endpoint"`
|
||||||
// TODO (Abhi) We might need to add auth per namespace. Looks like
|
}
|
||||||
// image auth information is passed by kube itself.
|
|
||||||
|
// AuthConfig contains the config related to authentication to a specific registry
|
||||||
|
type AuthConfig struct {
|
||||||
|
// Username is the username to login the registry.
|
||||||
|
Username string `toml:"username" json:"username"`
|
||||||
|
// Password is the password to login the registry.
|
||||||
|
Password string `toml:"password" json:"password"`
|
||||||
|
// Auth is a base64 encoded string from the concatenation of the username,
|
||||||
|
// a colon, and the password.
|
||||||
|
Auth string `toml:"auth" json:"auth"`
|
||||||
|
// IdentityToken is used to authenticate the user and get
|
||||||
|
// an access token for the registry.
|
||||||
|
IdentityToken string `toml:"identitytoken" json:"identitytoken"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Registry is registry settings configured
|
// Registry is registry settings configured
|
||||||
type Registry struct {
|
type Registry struct {
|
||||||
// Mirrors are namespace to mirror mapping for all namespaces.
|
// Mirrors are namespace to mirror mapping for all namespaces.
|
||||||
Mirrors map[string]Mirror `toml:"mirrors" json:"mirrors"`
|
Mirrors map[string]Mirror `toml:"mirrors" json:"mirrors"`
|
||||||
|
// Auths are registry endpoint to auth config mapping. The registry endpoint must
|
||||||
|
// be a valid url with host specified.
|
||||||
|
Auths map[string]AuthConfig `toml:"auths" json:"auths"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PluginConfig contains toml config related to CRI plugin,
|
// PluginConfig contains toml config related to CRI plugin,
|
||||||
@ -81,7 +97,7 @@ type PluginConfig struct {
|
|||||||
// CniConfig contains config related to cni
|
// CniConfig contains config related to cni
|
||||||
CniConfig `toml:"cni" json:"cni"`
|
CniConfig `toml:"cni" json:"cni"`
|
||||||
// Registry contains config related to the registry
|
// Registry contains config related to the registry
|
||||||
Registry `toml:"registry" json:"registry"`
|
Registry Registry `toml:"registry" json:"registry"`
|
||||||
// StreamServerAddress is the ip address streaming server is listening on.
|
// StreamServerAddress is the ip address streaming server is listening on.
|
||||||
StreamServerAddress string `toml:"stream_server_address" json:"streamServerAddress"`
|
StreamServerAddress string `toml:"stream_server_address" json:"streamServerAddress"`
|
||||||
// StreamServerPort is the port streaming server is listening on.
|
// StreamServerPort is the port streaming server is listening on.
|
||||||
|
@ -1,202 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// The corresponding file is in containerd/remote/docker/
|
|
||||||
// This package can be removed once a more feasible and hollistic resolver
|
|
||||||
// is finalized in containerd.
|
|
||||||
|
|
||||||
package resolver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type authenticationScheme byte
|
|
||||||
|
|
||||||
const (
|
|
||||||
basicAuth authenticationScheme = 1 << iota // Defined in RFC 7617
|
|
||||||
digestAuth // Defined in RFC 7616
|
|
||||||
bearerAuth // Defined in RFC 6750
|
|
||||||
)
|
|
||||||
|
|
||||||
// challenge carries information from a WWW-Authenticate response header.
|
|
||||||
// See RFC 2617.
|
|
||||||
type challenge struct {
|
|
||||||
// scheme is the auth-scheme according to RFC 2617
|
|
||||||
scheme authenticationScheme
|
|
||||||
|
|
||||||
// parameters are the auth-params according to RFC 2617
|
|
||||||
parameters map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
type byScheme []challenge
|
|
||||||
|
|
||||||
func (bs byScheme) Len() int { return len(bs) }
|
|
||||||
func (bs byScheme) Swap(i, j int) { bs[i], bs[j] = bs[j], bs[i] }
|
|
||||||
|
|
||||||
// Sort in priority order: token > digest > basic
|
|
||||||
func (bs byScheme) Less(i, j int) bool { return bs[i].scheme > bs[j].scheme }
|
|
||||||
|
|
||||||
// Octet types from RFC 2616.
|
|
||||||
type octetType byte
|
|
||||||
|
|
||||||
var octetTypes [256]octetType
|
|
||||||
|
|
||||||
const (
|
|
||||||
isToken octetType = 1 << iota
|
|
||||||
isSpace
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// OCTET = <any 8-bit sequence of data>
|
|
||||||
// CHAR = <any US-ASCII character (octets 0 - 127)>
|
|
||||||
// CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
|
|
||||||
// CR = <US-ASCII CR, carriage return (13)>
|
|
||||||
// LF = <US-ASCII LF, linefeed (10)>
|
|
||||||
// SP = <US-ASCII SP, space (32)>
|
|
||||||
// HT = <US-ASCII HT, horizontal-tab (9)>
|
|
||||||
// <"> = <US-ASCII double-quote mark (34)>
|
|
||||||
// CRLF = CR LF
|
|
||||||
// LWS = [CRLF] 1*( SP | HT )
|
|
||||||
// TEXT = <any OCTET except CTLs, but including LWS>
|
|
||||||
// separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <">
|
|
||||||
// | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
|
|
||||||
// token = 1*<any CHAR except CTLs or separators>
|
|
||||||
// qdtext = <any TEXT except <">>
|
|
||||||
|
|
||||||
for c := 0; c < 256; c++ {
|
|
||||||
var t octetType
|
|
||||||
isCtl := c <= 31 || c == 127
|
|
||||||
isChar := 0 <= c && c <= 127
|
|
||||||
isSeparator := strings.ContainsRune(" \t\"(),/:;<=>?@[]\\{}", rune(c))
|
|
||||||
if strings.ContainsRune(" \t\r\n", rune(c)) {
|
|
||||||
t |= isSpace
|
|
||||||
}
|
|
||||||
if isChar && !isCtl && !isSeparator {
|
|
||||||
t |= isToken
|
|
||||||
}
|
|
||||||
octetTypes[c] = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseAuthHeader(header http.Header) []challenge {
|
|
||||||
challenges := []challenge{}
|
|
||||||
for _, h := range header[http.CanonicalHeaderKey("WWW-Authenticate")] {
|
|
||||||
v, p := parseValueAndParams(h)
|
|
||||||
var s authenticationScheme
|
|
||||||
switch v {
|
|
||||||
case "basic":
|
|
||||||
s = basicAuth
|
|
||||||
case "digest":
|
|
||||||
s = digestAuth
|
|
||||||
case "bearer":
|
|
||||||
s = bearerAuth
|
|
||||||
default:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
challenges = append(challenges, challenge{scheme: s, parameters: p})
|
|
||||||
}
|
|
||||||
sort.Stable(byScheme(challenges))
|
|
||||||
return challenges
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseValueAndParams(header string) (value string, params map[string]string) {
|
|
||||||
params = make(map[string]string)
|
|
||||||
value, s := expectToken(header)
|
|
||||||
if value == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
value = strings.ToLower(value)
|
|
||||||
for {
|
|
||||||
var pkey string
|
|
||||||
pkey, s = expectToken(skipSpace(s))
|
|
||||||
if pkey == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(s, "=") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var pvalue string
|
|
||||||
pvalue, s = expectTokenOrQuoted(s[1:])
|
|
||||||
if pvalue == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pkey = strings.ToLower(pkey)
|
|
||||||
params[pkey] = pvalue
|
|
||||||
s = skipSpace(s)
|
|
||||||
if !strings.HasPrefix(s, ",") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s = s[1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func skipSpace(s string) (rest string) {
|
|
||||||
i := 0
|
|
||||||
for ; i < len(s); i++ {
|
|
||||||
if octetTypes[s[i]]&isSpace == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s[i:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func expectToken(s string) (token, rest string) {
|
|
||||||
i := 0
|
|
||||||
for ; i < len(s); i++ {
|
|
||||||
if octetTypes[s[i]]&isToken == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s[:i], s[i:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func expectTokenOrQuoted(s string) (value string, rest string) {
|
|
||||||
if !strings.HasPrefix(s, "\"") {
|
|
||||||
return expectToken(s)
|
|
||||||
}
|
|
||||||
s = s[1:]
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
switch s[i] {
|
|
||||||
case '"':
|
|
||||||
return s[:i], s[i+1:]
|
|
||||||
case '\\':
|
|
||||||
p := make([]byte, len(s)-1)
|
|
||||||
j := copy(p, s[:i])
|
|
||||||
escape := true
|
|
||||||
for i = i + 1; i < len(s); i++ {
|
|
||||||
b := s[i]
|
|
||||||
switch {
|
|
||||||
case escape:
|
|
||||||
escape = false
|
|
||||||
p[j] = b
|
|
||||||
j++
|
|
||||||
case b == '\\':
|
|
||||||
escape = true
|
|
||||||
case b == '"':
|
|
||||||
return string(p[:j]), s[i+1:]
|
|
||||||
default:
|
|
||||||
p[j] = b
|
|
||||||
j++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", ""
|
|
||||||
}
|
|
@ -1,172 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// The corresponding file is in containerd/remote/docker/
|
|
||||||
// This package can be removed once a more feasible and hollistic resolver
|
|
||||||
// is finalized in containerd.
|
|
||||||
|
|
||||||
package resolver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
|
||||||
"github.com/containerd/containerd/images"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type dockerFetcher struct {
|
|
||||||
*dockerBase
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.ReadCloser, error) {
|
|
||||||
var bases []string
|
|
||||||
for _, b := range r.base {
|
|
||||||
bases = append(bases, b.String())
|
|
||||||
}
|
|
||||||
ctx = log.WithLogger(ctx, log.G(ctx).WithFields(
|
|
||||||
logrus.Fields{
|
|
||||||
"base": bases,
|
|
||||||
"digest": desc.Digest,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
|
|
||||||
urls, err := r.getV2URLPaths(ctx, desc)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, err = contextWithRepositoryScope(ctx, r.refspec, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return newHTTPReadSeeker(desc.Size, func(offset int64) (io.ReadCloser, error) {
|
|
||||||
for _, u := range urls {
|
|
||||||
rc, err := r.open(ctx, u, desc.MediaType, offset)
|
|
||||||
if err != nil {
|
|
||||||
if errdefs.IsNotFound(err) {
|
|
||||||
continue // try one of the other urls.
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errors.Wrapf(errdefs.ErrNotFound,
|
|
||||||
"could not fetch content descriptor %v (%v) from remote",
|
|
||||||
desc.Digest, desc.MediaType)
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r dockerFetcher) open(ctx context.Context, u, mediatype string, offset int64) (io.ReadCloser, error) {
|
|
||||||
req, err := http.NewRequest(http.MethodGet, u, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set("Accept", strings.Join([]string{mediatype, `*`}, ", "))
|
|
||||||
|
|
||||||
if offset > 0 {
|
|
||||||
// Note: "Accept-Ranges: bytes" cannot be trusted as some endpoints
|
|
||||||
// will return the header without supporting the range. The content
|
|
||||||
// range must always be checked.
|
|
||||||
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", offset))
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := r.doRequestWithRetries(ctx, req, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode > 299 {
|
|
||||||
// TODO(stevvooe): When doing a offset specific request, we should
|
|
||||||
// really distinguish between a 206 and a 200. In the case of 200, we
|
|
||||||
// can discard the bytes, hiding the seek behavior from the
|
|
||||||
// implementation.
|
|
||||||
|
|
||||||
resp.Body.Close()
|
|
||||||
if resp.StatusCode == http.StatusNotFound {
|
|
||||||
return nil, errors.Wrapf(errdefs.ErrNotFound, "content at %v not found", u)
|
|
||||||
}
|
|
||||||
return nil, errors.Errorf("unexpected status code %v: %v", u, resp.Status)
|
|
||||||
}
|
|
||||||
if offset > 0 {
|
|
||||||
cr := resp.Header.Get("content-range")
|
|
||||||
if cr != "" {
|
|
||||||
if !strings.HasPrefix(cr, fmt.Sprintf("bytes %d-", offset)) {
|
|
||||||
return nil, errors.Errorf("unhandled content range in response: %v", cr)
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// TODO: Should any cases where use of content range
|
|
||||||
// without the proper header be considerd?
|
|
||||||
// 206 responses?
|
|
||||||
|
|
||||||
// Discard up to offset
|
|
||||||
// Could use buffer pool here but this case should be rare
|
|
||||||
n, err := io.Copy(ioutil.Discard, io.LimitReader(resp.Body, offset))
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to discard to offset")
|
|
||||||
}
|
|
||||||
if n != offset {
|
|
||||||
return nil, errors.Errorf("unable to discard to offset")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp.Body, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getV2URLPaths generates the candidate urls paths for the object based on the
|
|
||||||
// set of hints and the provided object id. URLs are returned in the order of
|
|
||||||
// most to least likely succeed.
|
|
||||||
func (r *dockerFetcher) getV2URLPaths(ctx context.Context, desc ocispec.Descriptor) ([]string, error) {
|
|
||||||
var urls []string
|
|
||||||
|
|
||||||
if len(desc.URLs) > 0 {
|
|
||||||
// handle fetch via external urls.
|
|
||||||
for _, u := range desc.URLs {
|
|
||||||
log.G(ctx).WithField("url", u).Debug("adding alternative url")
|
|
||||||
urls = append(urls, u)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch desc.MediaType {
|
|
||||||
case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList,
|
|
||||||
images.MediaTypeDockerSchema1Manifest,
|
|
||||||
ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex:
|
|
||||||
urls = append(urls, r.urls(path.Join("manifests", desc.Digest.String()))...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// always fallback to attempting to get the object out of the blobs store.
|
|
||||||
urls = append(urls, r.urls(path.Join("blobs", desc.Digest.String()))...)
|
|
||||||
|
|
||||||
return urls, nil
|
|
||||||
}
|
|
@ -1,94 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 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 resolver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"math/rand"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFetcherOpen(t *testing.T) {
|
|
||||||
content := make([]byte, 128)
|
|
||||||
rand.New(rand.NewSource(1)).Read(content)
|
|
||||||
start := 0
|
|
||||||
|
|
||||||
s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
if start > 0 {
|
|
||||||
rw.Header().Set("content-range", fmt.Sprintf("bytes %d-127/128", start))
|
|
||||||
}
|
|
||||||
rw.Header().Set("content-length", fmt.Sprintf("%d", len(content[start:])))
|
|
||||||
rw.Write(content[start:])
|
|
||||||
}))
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
f := dockerFetcher{&dockerBase{
|
|
||||||
client: s.Client(),
|
|
||||||
}}
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
checkReader := func(o int64) {
|
|
||||||
t.Helper()
|
|
||||||
rc, err := f.open(ctx, s.URL, "", o)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to open: %+v", err)
|
|
||||||
}
|
|
||||||
b, err := ioutil.ReadAll(rc)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
expected := content[o:]
|
|
||||||
if len(b) != len(expected) {
|
|
||||||
t.Errorf("unexpected length %d, expected %d", len(b), len(expected))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i, c := range expected {
|
|
||||||
if b[i] != c {
|
|
||||||
t.Errorf("unexpected byte %x at %d, expected %x", b[i], i, c)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
checkReader(0)
|
|
||||||
|
|
||||||
// Test server ignores content range
|
|
||||||
checkReader(25)
|
|
||||||
|
|
||||||
// Use content range on server
|
|
||||||
start = 20
|
|
||||||
checkReader(20)
|
|
||||||
|
|
||||||
// Check returning just last byte and no bytes
|
|
||||||
start = 127
|
|
||||||
checkReader(127)
|
|
||||||
start = 128
|
|
||||||
checkReader(128)
|
|
||||||
|
|
||||||
// Check that server returning a different content range
|
|
||||||
// then requested errors
|
|
||||||
start = 30
|
|
||||||
_, err := f.open(ctx, s.URL, "", 20)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected error opening with invalid server response")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,148 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// The corresponding file is in containerd/remote/docker/.
|
|
||||||
// This package can be removed once a more feasible and hollistic resolver
|
|
||||||
// is finalized in containerd.
|
|
||||||
|
|
||||||
package resolver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
type httpReadSeeker struct {
|
|
||||||
size int64
|
|
||||||
offset int64
|
|
||||||
rc io.ReadCloser
|
|
||||||
open func(offset int64) (io.ReadCloser, error)
|
|
||||||
closed bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newHTTPReadSeeker(size int64, open func(offset int64) (io.ReadCloser, error)) (io.ReadCloser, error) {
|
|
||||||
return &httpReadSeeker{
|
|
||||||
size: size,
|
|
||||||
open: open,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hrs *httpReadSeeker) Read(p []byte) (n int, err error) {
|
|
||||||
if hrs.closed {
|
|
||||||
return 0, io.EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
rd, err := hrs.reader()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err = rd.Read(p)
|
|
||||||
hrs.offset += int64(n)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hrs *httpReadSeeker) Close() error {
|
|
||||||
if hrs.closed {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
hrs.closed = true
|
|
||||||
if hrs.rc != nil {
|
|
||||||
return hrs.rc.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hrs *httpReadSeeker) Seek(offset int64, whence int) (int64, error) {
|
|
||||||
if hrs.closed {
|
|
||||||
return 0, errors.Wrap(errdefs.ErrUnavailable, "Fetcher.Seek: closed")
|
|
||||||
}
|
|
||||||
|
|
||||||
abs := hrs.offset
|
|
||||||
switch whence {
|
|
||||||
case io.SeekStart:
|
|
||||||
abs = offset
|
|
||||||
case io.SeekCurrent:
|
|
||||||
abs += offset
|
|
||||||
case io.SeekEnd:
|
|
||||||
if hrs.size == -1 {
|
|
||||||
return 0, errors.Wrap(errdefs.ErrUnavailable, "Fetcher.Seek: unknown size, cannot seek from end")
|
|
||||||
}
|
|
||||||
abs = hrs.size + offset
|
|
||||||
default:
|
|
||||||
return 0, errors.Wrap(errdefs.ErrInvalidArgument, "Fetcher.Seek: invalid whence")
|
|
||||||
}
|
|
||||||
|
|
||||||
if abs < 0 {
|
|
||||||
return 0, errors.Wrapf(errdefs.ErrInvalidArgument, "Fetcher.Seek: negative offset")
|
|
||||||
}
|
|
||||||
|
|
||||||
if abs != hrs.offset {
|
|
||||||
if hrs.rc != nil {
|
|
||||||
if err := hrs.rc.Close(); err != nil {
|
|
||||||
log.L.WithError(err).Errorf("Fetcher.Seek: failed to close ReadCloser")
|
|
||||||
}
|
|
||||||
|
|
||||||
hrs.rc = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
hrs.offset = abs
|
|
||||||
}
|
|
||||||
|
|
||||||
return hrs.offset, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hrs *httpReadSeeker) reader() (io.Reader, error) {
|
|
||||||
if hrs.rc != nil {
|
|
||||||
return hrs.rc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if hrs.size == -1 || hrs.offset < hrs.size {
|
|
||||||
// only try to reopen the body request if we are seeking to a value
|
|
||||||
// less than the actual size.
|
|
||||||
if hrs.open == nil {
|
|
||||||
return nil, errors.Wrapf(errdefs.ErrNotImplemented, "cannot open")
|
|
||||||
}
|
|
||||||
|
|
||||||
rc, err := hrs.open(hrs.offset)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "httpReaderSeeker: failed open")
|
|
||||||
}
|
|
||||||
|
|
||||||
if hrs.rc != nil {
|
|
||||||
if err := hrs.rc.Close(); err != nil {
|
|
||||||
log.L.WithError(err).Errorf("httpReadSeeker: failed to close ReadCloser")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hrs.rc = rc
|
|
||||||
} else {
|
|
||||||
// There is an edge case here where offset == size of the content. If
|
|
||||||
// we seek, we will probably get an error for content that cannot be
|
|
||||||
// sought (?). In that case, we should err on committing the content,
|
|
||||||
// as the length is already satisified but we just return the empty
|
|
||||||
// reader instead.
|
|
||||||
|
|
||||||
hrs.rc = ioutil.NopCloser(bytes.NewReader([]byte{}))
|
|
||||||
}
|
|
||||||
|
|
||||||
return hrs.rc, nil
|
|
||||||
}
|
|
@ -1,622 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 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 resolver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"path"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/images"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/containerd/containerd/reference"
|
|
||||||
"github.com/containerd/containerd/remotes"
|
|
||||||
digest "github.com/opencontainers/go-digest"
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/net/context/ctxhttp"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This file is a modified copy of containerd/remote/docker/resolver.go.
|
|
||||||
// The changes carried over by this file includes support for image ref
|
|
||||||
// resolution and fetching image using multiple registry mirror urls. A new
|
|
||||||
// ResolverOption called Registry is added. Registry will contain a map
|
|
||||||
// of namespace relevant mirror urls. The client will use the ResolverOptions
|
|
||||||
// to set the urls associated with the namespace of the image reference.
|
|
||||||
// This package can be removed once a more feasible and hollistic resolver
|
|
||||||
// is finalized in containerd. The specific changes are made to the base
|
|
||||||
// function to calculate the base urls for the image location. urls() is
|
|
||||||
// added to fetch the mirror urls associated with the namespace of the image
|
|
||||||
// ResolverOptions are changed for client to set the namespace and mirror urls
|
|
||||||
// for to pull the image.
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrNoToken is returned if a request is successful but the body does not
|
|
||||||
// contain an authorization token.
|
|
||||||
ErrNoToken = errors.New("authorization server did not include a token in the response")
|
|
||||||
|
|
||||||
// ErrInvalidAuthorization is used when credentials are passed to a server but
|
|
||||||
// those credentials are rejected.
|
|
||||||
ErrInvalidAuthorization = errors.New("authorization failed")
|
|
||||||
)
|
|
||||||
|
|
||||||
type containerdResolver struct {
|
|
||||||
credentials func(string) (string, string, error)
|
|
||||||
plainHTTP bool
|
|
||||||
client *http.Client
|
|
||||||
tracker StatusTracker
|
|
||||||
registry map[string][]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Options are used to configured a new Docker register resolver
|
|
||||||
type Options struct {
|
|
||||||
// Credentials provides username and secret given a host.
|
|
||||||
// If username is empty but a secret is given, that secret
|
|
||||||
// is interpretted as a long lived token.
|
|
||||||
Credentials func(string) (string, string, error)
|
|
||||||
|
|
||||||
// PlainHTTP specifies to use plain http and not https
|
|
||||||
PlainHTTP bool
|
|
||||||
|
|
||||||
// Client is the http client to used when making registry requests
|
|
||||||
Client *http.Client
|
|
||||||
|
|
||||||
// Tracker is used to track uploads to the registry. This is used
|
|
||||||
// since the registry does not have upload tracking and the existing
|
|
||||||
// mechanism for getting blob upload status is expensive.
|
|
||||||
Tracker StatusTracker
|
|
||||||
|
|
||||||
Registry map[string][]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewResolver returns a new resolver to a Docker registry
|
|
||||||
func NewResolver(options Options) remotes.Resolver {
|
|
||||||
tracker := options.Tracker
|
|
||||||
if tracker == nil {
|
|
||||||
tracker = NewInMemoryTracker()
|
|
||||||
}
|
|
||||||
|
|
||||||
return &containerdResolver{
|
|
||||||
credentials: options.Credentials,
|
|
||||||
plainHTTP: options.PlainHTTP,
|
|
||||||
client: options.Client,
|
|
||||||
tracker: tracker,
|
|
||||||
registry: options.Registry,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ remotes.Resolver = &containerdResolver{}
|
|
||||||
|
|
||||||
func (r *containerdResolver) Resolve(ctx context.Context, ref string) (string, ocispec.Descriptor, error) {
|
|
||||||
refspec, err := reference.Parse(ref)
|
|
||||||
if err != nil {
|
|
||||||
return "", ocispec.Descriptor{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if refspec.Object == "" {
|
|
||||||
return "", ocispec.Descriptor{}, reference.ErrObjectRequired
|
|
||||||
}
|
|
||||||
|
|
||||||
base, err := r.base(refspec)
|
|
||||||
if err != nil {
|
|
||||||
return "", ocispec.Descriptor{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fetcher := dockerFetcher{
|
|
||||||
dockerBase: base,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
urls []string
|
|
||||||
dgst = refspec.Digest()
|
|
||||||
)
|
|
||||||
|
|
||||||
if dgst != "" {
|
|
||||||
if err := dgst.Validate(); err != nil {
|
|
||||||
// need to fail here, since we can't actually resolve the invalid
|
|
||||||
// digest.
|
|
||||||
return "", ocispec.Descriptor{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// turns out, we have a valid digest, make a url.
|
|
||||||
urls = append(urls, fetcher.urls("manifests", dgst.String())...)
|
|
||||||
|
|
||||||
// fallback to blobs on not found.
|
|
||||||
urls = append(urls, fetcher.urls("blobs", dgst.String())...)
|
|
||||||
} else {
|
|
||||||
urls = append(urls, fetcher.urls("manifests", refspec.Object)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, err = contextWithRepositoryScope(ctx, refspec, false)
|
|
||||||
if err != nil {
|
|
||||||
return "", ocispec.Descriptor{}, err
|
|
||||||
}
|
|
||||||
for _, u := range urls {
|
|
||||||
log.G(ctx).WithFields(logrus.Fields{
|
|
||||||
"url": u,
|
|
||||||
}).Debug("Trying to fetch from url")
|
|
||||||
req, err := http.NewRequest(http.MethodHead, u, nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", ocispec.Descriptor{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// set headers for all the types we support for resolution.
|
|
||||||
req.Header.Set("Accept", strings.Join([]string{
|
|
||||||
images.MediaTypeDockerSchema2Manifest,
|
|
||||||
images.MediaTypeDockerSchema2ManifestList,
|
|
||||||
ocispec.MediaTypeImageManifest,
|
|
||||||
ocispec.MediaTypeImageIndex, "*"}, ", "))
|
|
||||||
|
|
||||||
log.G(ctx).Info("resolving")
|
|
||||||
resp, err := fetcher.doRequestWithRetries(ctx, req, nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", ocispec.Descriptor{}, err
|
|
||||||
}
|
|
||||||
resp.Body.Close() // don't care about body contents.
|
|
||||||
|
|
||||||
if resp.StatusCode > 299 {
|
|
||||||
if resp.StatusCode == http.StatusNotFound {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return "", ocispec.Descriptor{}, errors.Errorf("unexpected status code %v: %v", u, resp.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is the only point at which we trust the registry. we use the
|
|
||||||
// content headers to assemble a descriptor for the name. when this becomes
|
|
||||||
// more robust, we mostly get this information from a secure trust store.
|
|
||||||
dgstHeader := digest.Digest(resp.Header.Get("Docker-Content-Digest"))
|
|
||||||
|
|
||||||
if dgstHeader != "" {
|
|
||||||
if err := dgstHeader.Validate(); err != nil {
|
|
||||||
return "", ocispec.Descriptor{}, errors.Wrapf(err, "%q in header not a valid digest", dgstHeader)
|
|
||||||
}
|
|
||||||
dgst = dgstHeader
|
|
||||||
}
|
|
||||||
|
|
||||||
if dgst == "" {
|
|
||||||
return "", ocispec.Descriptor{}, errors.Errorf("could not resolve digest for %v", ref)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
size int64
|
|
||||||
sizeHeader = resp.Header.Get("Content-Length")
|
|
||||||
)
|
|
||||||
|
|
||||||
size, err = strconv.ParseInt(sizeHeader, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
|
|
||||||
return "", ocispec.Descriptor{}, errors.Wrapf(err, "invalid size header: %q", sizeHeader)
|
|
||||||
}
|
|
||||||
if size < 0 {
|
|
||||||
return "", ocispec.Descriptor{}, errors.Errorf("%q in header not a valid size", sizeHeader)
|
|
||||||
}
|
|
||||||
|
|
||||||
desc := ocispec.Descriptor{
|
|
||||||
Digest: dgst,
|
|
||||||
MediaType: resp.Header.Get("Content-Type"), // need to strip disposition?
|
|
||||||
Size: size,
|
|
||||||
}
|
|
||||||
|
|
||||||
log.G(ctx).WithField("desc.digest", desc.Digest).Debug("resolved")
|
|
||||||
return ref, desc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", ocispec.Descriptor{}, errors.Errorf("%v not found", ref)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *containerdResolver) Fetcher(ctx context.Context, ref string) (remotes.Fetcher, error) {
|
|
||||||
refspec, err := reference.Parse(ref)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
base, err := r.base(refspec)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return dockerFetcher{
|
|
||||||
dockerBase: base,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *containerdResolver) Pusher(ctx context.Context, ref string) (remotes.Pusher, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type dockerBase struct {
|
|
||||||
refspec reference.Spec
|
|
||||||
base []url.URL
|
|
||||||
|
|
||||||
client *http.Client
|
|
||||||
useBasic bool
|
|
||||||
username, secret string
|
|
||||||
token string
|
|
||||||
mu sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *containerdResolver) base(refspec reference.Spec) (*dockerBase, error) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
base []url.URL
|
|
||||||
username, secret string
|
|
||||||
)
|
|
||||||
|
|
||||||
host := refspec.Hostname()
|
|
||||||
prefix := strings.TrimPrefix(refspec.Locator, host+"/")
|
|
||||||
|
|
||||||
if urls, ok := r.registry[host]; ok {
|
|
||||||
urls, err := r.getV2Urls(urls, prefix)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to fetch v2 urls")
|
|
||||||
}
|
|
||||||
base = append(base, urls...)
|
|
||||||
} else if host == "docker.io" {
|
|
||||||
base = append(base, []url.URL{{Host: "registry-1.docker.io", Scheme: "https", Path: path.Join("/v2", prefix)}}...)
|
|
||||||
} else {
|
|
||||||
scheme := "https"
|
|
||||||
if r.plainHTTP || strings.HasPrefix(host, "localhost:") {
|
|
||||||
scheme = "http"
|
|
||||||
}
|
|
||||||
base = append(base, []url.URL{{Host: host, Scheme: scheme, Path: path.Join("/v2", prefix)}}...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.credentials != nil {
|
|
||||||
username, secret, err = r.credentials(base[0].Host)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &dockerBase{
|
|
||||||
refspec: refspec,
|
|
||||||
base: base,
|
|
||||||
client: r.client,
|
|
||||||
username: username,
|
|
||||||
secret: secret,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dockerBase) getToken() string {
|
|
||||||
r.mu.Lock()
|
|
||||||
defer r.mu.Unlock()
|
|
||||||
|
|
||||||
return r.token
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dockerBase) setToken(token string) bool {
|
|
||||||
r.mu.Lock()
|
|
||||||
defer r.mu.Unlock()
|
|
||||||
|
|
||||||
changed := r.token != token
|
|
||||||
r.token = token
|
|
||||||
|
|
||||||
return changed
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dockerBase) urls(ps ...string) []string {
|
|
||||||
urls := []string{}
|
|
||||||
for _, url := range r.base {
|
|
||||||
url.Path = path.Join(url.Path, path.Join(ps...))
|
|
||||||
urls = append(urls, url.String())
|
|
||||||
}
|
|
||||||
return urls
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dockerBase) authorize(req *http.Request) {
|
|
||||||
token := r.getToken()
|
|
||||||
if r.useBasic {
|
|
||||||
req.SetBasicAuth(r.username, r.secret)
|
|
||||||
} else if token != "" {
|
|
||||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dockerBase) doRequest(ctx context.Context, req *http.Request) (*http.Response, error) {
|
|
||||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("url", req.URL.String()))
|
|
||||||
log.G(ctx).WithField("request.headers", req.Header).WithField("request.method", req.Method).Debug("do request")
|
|
||||||
r.authorize(req)
|
|
||||||
resp, err := ctxhttp.Do(ctx, r.client, req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to do request")
|
|
||||||
}
|
|
||||||
log.G(ctx).WithFields(logrus.Fields{
|
|
||||||
"status": resp.Status,
|
|
||||||
"response.headers": resp.Header,
|
|
||||||
}).Debug("fetch response received")
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dockerBase) doRequestWithRetries(ctx context.Context, req *http.Request, responses []*http.Response) (*http.Response, error) {
|
|
||||||
resp, err := r.doRequest(ctx, req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
responses = append(responses, resp)
|
|
||||||
req, err = r.retryRequest(ctx, req, responses)
|
|
||||||
if err != nil {
|
|
||||||
resp.Body.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if req != nil {
|
|
||||||
resp.Body.Close()
|
|
||||||
return r.doRequestWithRetries(ctx, req, responses)
|
|
||||||
}
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dockerBase) retryRequest(ctx context.Context, req *http.Request, responses []*http.Response) (*http.Request, error) {
|
|
||||||
if len(responses) > 5 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
last := responses[len(responses)-1]
|
|
||||||
if last.StatusCode == http.StatusUnauthorized {
|
|
||||||
log.G(ctx).WithField("header", last.Header.Get("WWW-Authenticate")).Debug("Unauthorized")
|
|
||||||
for _, c := range parseAuthHeader(last.Header) {
|
|
||||||
if c.scheme == bearerAuth {
|
|
||||||
if err := invalidAuthorization(c, responses); err != nil {
|
|
||||||
r.setToken("")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := r.setTokenAuth(ctx, c.parameters); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return copyRequest(req)
|
|
||||||
} else if c.scheme == basicAuth {
|
|
||||||
if r.username != "" && r.secret != "" {
|
|
||||||
r.useBasic = true
|
|
||||||
}
|
|
||||||
return copyRequest(req)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
} else if last.StatusCode == http.StatusMethodNotAllowed && req.Method == http.MethodHead {
|
|
||||||
// Support registries which have not properly implemented the HEAD method for
|
|
||||||
// manifests endpoint
|
|
||||||
if strings.Contains(req.URL.Path, "/manifests/") {
|
|
||||||
// TODO: copy request?
|
|
||||||
req.Method = http.MethodGet
|
|
||||||
return copyRequest(req)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Handle 50x errors accounting for attempt history
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func invalidAuthorization(c challenge, responses []*http.Response) error {
|
|
||||||
errStr := c.parameters["error"]
|
|
||||||
if errStr == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
n := len(responses)
|
|
||||||
if n == 1 || (n > 1 && !sameRequest(responses[n-2].Request, responses[n-1].Request)) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors.Wrapf(ErrInvalidAuthorization, "server message: %s", errStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func sameRequest(r1, r2 *http.Request) bool {
|
|
||||||
if r1.Method != r2.Method {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if *r1.URL != *r2.URL {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyRequest(req *http.Request) (*http.Request, error) {
|
|
||||||
ireq := *req
|
|
||||||
if ireq.GetBody != nil {
|
|
||||||
var err error
|
|
||||||
ireq.Body, err = ireq.GetBody()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &ireq, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dockerBase) setTokenAuth(ctx context.Context, params map[string]string) error {
|
|
||||||
realm, ok := params["realm"]
|
|
||||||
if !ok {
|
|
||||||
return errors.New("no realm specified for token auth challenge")
|
|
||||||
}
|
|
||||||
|
|
||||||
realmURL, err := url.Parse(realm)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "invalid token auth challenge realm")
|
|
||||||
}
|
|
||||||
|
|
||||||
to := tokenOptions{
|
|
||||||
realm: realmURL.String(),
|
|
||||||
service: params["service"],
|
|
||||||
}
|
|
||||||
|
|
||||||
to.scopes = getTokenScopes(ctx, params)
|
|
||||||
if len(to.scopes) == 0 {
|
|
||||||
return errors.New("no scope specified for token auth challenge")
|
|
||||||
}
|
|
||||||
|
|
||||||
var token string
|
|
||||||
if r.secret != "" {
|
|
||||||
// Credential information is provided, use oauth POST endpoint
|
|
||||||
token, err = r.fetchTokenWithOAuth(ctx, to)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to fetch oauth token")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Do request anonymously
|
|
||||||
token, err = r.fetchToken(ctx, to)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to fetch anonymous token")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.setToken(token)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type tokenOptions struct {
|
|
||||||
realm string
|
|
||||||
service string
|
|
||||||
scopes []string
|
|
||||||
}
|
|
||||||
|
|
||||||
type postTokenResponse struct {
|
|
||||||
AccessToken string `json:"access_token"`
|
|
||||||
RefreshToken string `json:"refresh_token"`
|
|
||||||
ExpiresIn int `json:"expires_in"`
|
|
||||||
IssuedAt time.Time `json:"issued_at"`
|
|
||||||
Scope string `json:"scope"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dockerBase) fetchTokenWithOAuth(ctx context.Context, to tokenOptions) (string, error) {
|
|
||||||
form := url.Values{}
|
|
||||||
form.Set("scope", strings.Join(to.scopes, " "))
|
|
||||||
form.Set("service", to.service)
|
|
||||||
// TODO: Allow setting client_id
|
|
||||||
form.Set("client_id", "containerd-dist-tool")
|
|
||||||
|
|
||||||
if r.username == "" {
|
|
||||||
form.Set("grant_type", "refresh_token")
|
|
||||||
form.Set("refresh_token", r.secret)
|
|
||||||
} else {
|
|
||||||
form.Set("grant_type", "password")
|
|
||||||
form.Set("username", r.username)
|
|
||||||
form.Set("password", r.secret)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := ctxhttp.PostForm(ctx, r.client, to.realm, form)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
// Registries without support for POST may return 404 for POST /v2/token.
|
|
||||||
// As of September 2017, GCR is known to return 404.
|
|
||||||
if (resp.StatusCode == 405 && r.username != "") || resp.StatusCode == 404 || resp.StatusCode == 401 {
|
|
||||||
return r.fetchToken(ctx, to)
|
|
||||||
} else if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
|
||||||
b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB
|
|
||||||
log.G(ctx).WithFields(logrus.Fields{
|
|
||||||
"status": resp.Status,
|
|
||||||
"body": string(b),
|
|
||||||
}).Debugf("token request failed")
|
|
||||||
// TODO: handle error body and write debug output
|
|
||||||
return "", errors.Errorf("unexpected status: %s", resp.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
decoder := json.NewDecoder(resp.Body)
|
|
||||||
|
|
||||||
var tr postTokenResponse
|
|
||||||
if err = decoder.Decode(&tr); err != nil {
|
|
||||||
return "", errors.Wrap(err, "unable to decode token response")
|
|
||||||
}
|
|
||||||
|
|
||||||
return tr.AccessToken, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type getTokenResponse struct {
|
|
||||||
Token string `json:"token"`
|
|
||||||
AccessToken string `json:"access_token"`
|
|
||||||
ExpiresIn int `json:"expires_in"`
|
|
||||||
IssuedAt time.Time `json:"issued_at"`
|
|
||||||
RefreshToken string `json:"refresh_token"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetchToken fetches a token using a GET request
|
|
||||||
func (r *dockerBase) fetchToken(ctx context.Context, to tokenOptions) (string, error) {
|
|
||||||
req, err := http.NewRequest("GET", to.realm, nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
reqParams := req.URL.Query()
|
|
||||||
|
|
||||||
if to.service != "" {
|
|
||||||
reqParams.Add("service", to.service)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, scope := range to.scopes {
|
|
||||||
reqParams.Add("scope", scope)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.secret != "" {
|
|
||||||
req.SetBasicAuth(r.username, r.secret)
|
|
||||||
}
|
|
||||||
|
|
||||||
req.URL.RawQuery = reqParams.Encode()
|
|
||||||
|
|
||||||
resp, err := ctxhttp.Do(ctx, r.client, req)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
|
||||||
// TODO: handle error body and write debug output
|
|
||||||
return "", errors.Errorf("unexpected status: %s", resp.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
decoder := json.NewDecoder(resp.Body)
|
|
||||||
|
|
||||||
var tr getTokenResponse
|
|
||||||
if err = decoder.Decode(&tr); err != nil {
|
|
||||||
return "", errors.Wrap(err, "unable to decode token response")
|
|
||||||
}
|
|
||||||
|
|
||||||
// `access_token` is equivalent to `token` and if both are specified
|
|
||||||
// the choice is undefined. Canonicalize `access_token` by sticking
|
|
||||||
// things in `token`.
|
|
||||||
if tr.AccessToken != "" {
|
|
||||||
tr.Token = tr.AccessToken
|
|
||||||
}
|
|
||||||
|
|
||||||
if tr.Token == "" {
|
|
||||||
return "", ErrNoToken
|
|
||||||
}
|
|
||||||
|
|
||||||
return tr.Token, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *containerdResolver) getV2Urls(urls []string, imagePath string) ([]url.URL, error) {
|
|
||||||
v2Urls := []url.URL{}
|
|
||||||
for _, u := range urls {
|
|
||||||
v2Url, err := url.Parse(u)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to parse url during getv2 urls: %+v", u)
|
|
||||||
}
|
|
||||||
v2Url.Path = path.Join("/v2", imagePath)
|
|
||||||
v2Urls = append(v2Urls, *v2Url)
|
|
||||||
}
|
|
||||||
return v2Urls, nil
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// The corresponding file is in containerd/remote/docker/.
|
|
||||||
// This package can be removed once a more feasible and hollistic resolver
|
|
||||||
// is finalized in containerd.
|
|
||||||
|
|
||||||
package resolver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/url"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/reference"
|
|
||||||
)
|
|
||||||
|
|
||||||
// repositoryScope returns a repository scope string such as "repository:foo/bar:pull"
|
|
||||||
// for "host/foo/bar:baz".
|
|
||||||
// When push is true, both pull and push are added to the scope.
|
|
||||||
func repositoryScope(refspec reference.Spec, push bool) (string, error) {
|
|
||||||
u, err := url.Parse("dummy://" + refspec.Locator)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
s := "repository:" + strings.TrimPrefix(u.Path, "/") + ":pull"
|
|
||||||
if push {
|
|
||||||
s += ",push"
|
|
||||||
}
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// tokenScopesKey is used for the key for context.WithValue().
|
|
||||||
// value: []string (e.g. {"registry:foo/bar:pull"})
|
|
||||||
type tokenScopesKey struct{}
|
|
||||||
|
|
||||||
// contextWithRepositoryScope returns a context with tokenScopesKey{} and the repository scope value.
|
|
||||||
func contextWithRepositoryScope(ctx context.Context, refspec reference.Spec, push bool) (context.Context, error) {
|
|
||||||
s, err := repositoryScope(refspec, push)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return context.WithValue(ctx, tokenScopesKey{}, []string{s}), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getTokenScopes returns deduplicated and sorted scopes from ctx.Value(tokenScopesKey{}) and params["scope"].
|
|
||||||
func getTokenScopes(ctx context.Context, params map[string]string) []string {
|
|
||||||
var scopes []string
|
|
||||||
if x := ctx.Value(tokenScopesKey{}); x != nil {
|
|
||||||
scopes = append(scopes, x.([]string)...)
|
|
||||||
}
|
|
||||||
if scope, ok := params["scope"]; ok {
|
|
||||||
for _, s := range scopes {
|
|
||||||
// Note: this comparison is unaware of the scope grammar (https://docs.docker.com/registry/spec/auth/scope/)
|
|
||||||
// So, "repository:foo/bar:pull,push" != "repository:foo/bar:push,pull", although semantically they are equal.
|
|
||||||
if s == scope {
|
|
||||||
// already appended
|
|
||||||
goto Sort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scopes = append(scopes, scope)
|
|
||||||
}
|
|
||||||
Sort:
|
|
||||||
sort.Strings(scopes)
|
|
||||||
return scopes
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// The corresponding file is in containerd/remote/docker/.
|
|
||||||
// This package can be removed once a more feasible and hollistic resolver
|
|
||||||
// is finalized in containerd.
|
|
||||||
|
|
||||||
package resolver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/reference"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRepositoryScope(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
refspec reference.Spec
|
|
||||||
push bool
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
refspec: reference.Spec{
|
|
||||||
Locator: "host/foo/bar",
|
|
||||||
Object: "ignored",
|
|
||||||
},
|
|
||||||
push: false,
|
|
||||||
expected: "repository:foo/bar:pull",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
refspec: reference.Spec{
|
|
||||||
Locator: "host:4242/foo/bar",
|
|
||||||
Object: "ignored",
|
|
||||||
},
|
|
||||||
push: true,
|
|
||||||
expected: "repository:foo/bar:pull,push",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, x := range testCases {
|
|
||||||
actual, err := repositoryScope(x.refspec, x.push)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, x.expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// The corresponding file is in containerd/remote/docker/.
|
|
||||||
// This package can be removed once a more feasible and hollistic resolver
|
|
||||||
// is finalized in containerd.
|
|
||||||
|
|
||||||
package resolver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Status of a content operation
|
|
||||||
type Status struct {
|
|
||||||
content.Status
|
|
||||||
|
|
||||||
// UploadUUID is used by the Docker registry to reference blob uploads
|
|
||||||
UploadUUID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// StatusTracker to track status of operations
|
|
||||||
type StatusTracker interface {
|
|
||||||
GetStatus(string) (Status, error)
|
|
||||||
SetStatus(string, Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
type memoryStatusTracker struct {
|
|
||||||
statuses map[string]Status
|
|
||||||
m sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewInMemoryTracker returns a StatusTracker that tracks content status in-memory
|
|
||||||
func NewInMemoryTracker() StatusTracker {
|
|
||||||
return &memoryStatusTracker{
|
|
||||||
statuses: map[string]Status{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *memoryStatusTracker) GetStatus(ref string) (Status, error) {
|
|
||||||
t.m.Lock()
|
|
||||||
defer t.m.Unlock()
|
|
||||||
status, ok := t.statuses[ref]
|
|
||||||
if !ok {
|
|
||||||
return Status{}, errors.Wrapf(errdefs.ErrNotFound, "status for ref %v", ref)
|
|
||||||
}
|
|
||||||
return status, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *memoryStatusTracker) SetStatus(ref string, status Status) {
|
|
||||||
t.m.Lock()
|
|
||||||
t.statuses[ref] = status
|
|
||||||
t.m.Unlock()
|
|
||||||
}
|
|
@ -444,3 +444,13 @@ func getRuntimeConfigFromContainerInfo(c containers.Container) (criconfig.Runtim
|
|||||||
r.Root = runtimeOpts.RuntimeRoot
|
r.Root = runtimeOpts.RuntimeRoot
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toRuntimeAuthConfig converts cri plugin auth config to runtime auth config.
|
||||||
|
func toRuntimeAuthConfig(a criconfig.AuthConfig) *runtime.AuthConfig {
|
||||||
|
return &runtime.AuthConfig{
|
||||||
|
Username: a.Username,
|
||||||
|
Password: a.Password,
|
||||||
|
Auth: a.Auth,
|
||||||
|
IdentityToken: a.IdentityToken,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -19,18 +19,21 @@ package server
|
|||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
containerdimages "github.com/containerd/containerd/images"
|
containerdimages "github.com/containerd/containerd/images"
|
||||||
|
"github.com/containerd/containerd/reference"
|
||||||
|
"github.com/containerd/containerd/remotes"
|
||||||
|
"github.com/containerd/containerd/remotes/docker"
|
||||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
||||||
|
|
||||||
containerdresolver "github.com/containerd/cri/pkg/containerd/resolver"
|
|
||||||
imagestore "github.com/containerd/cri/pkg/store/image"
|
imagestore "github.com/containerd/cri/pkg/store/image"
|
||||||
"github.com/containerd/cri/pkg/util"
|
"github.com/containerd/cri/pkg/util"
|
||||||
)
|
)
|
||||||
@ -87,12 +90,7 @@ func (c *criService) PullImage(ctx context.Context, r *runtime.PullImageRequest)
|
|||||||
if ref != imageRef {
|
if ref != imageRef {
|
||||||
logrus.Debugf("PullImage using normalized image ref: %q", ref)
|
logrus.Debugf("PullImage using normalized image ref: %q", ref)
|
||||||
}
|
}
|
||||||
resolver := containerdresolver.NewResolver(containerdresolver.Options{
|
resolver, desc, err := c.getResolver(ctx, ref, c.credentials(r.GetAuth()))
|
||||||
Credentials: func(string) (string, string, error) { return ParseAuth(r.GetAuth()) },
|
|
||||||
Client: http.DefaultClient,
|
|
||||||
Registry: c.getResolverOptions(),
|
|
||||||
})
|
|
||||||
_, desc, err := resolver.Resolve(ctx, ref)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to resolve image %q", ref)
|
return nil, errors.Wrapf(err, "failed to resolve image %q", ref)
|
||||||
}
|
}
|
||||||
@ -206,10 +204,59 @@ func (c *criService) createImageReference(ctx context.Context, name string, desc
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *criService) getResolverOptions() map[string][]string {
|
// credentials returns a credential function for docker resolver to use.
|
||||||
options := make(map[string][]string)
|
func (c *criService) credentials(auth *runtime.AuthConfig) func(string) (string, string, error) {
|
||||||
for ns, mirror := range c.config.Mirrors {
|
return func(host string) (string, string, error) {
|
||||||
options[ns] = append(options[ns], mirror.Endpoints...)
|
if auth == nil {
|
||||||
|
// Get default auth from config.
|
||||||
|
for h, ac := range c.config.Registry.Auths {
|
||||||
|
u, err := url.Parse(h)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", errors.Wrapf(err, "parse auth host %q", h)
|
||||||
|
}
|
||||||
|
if u.Host == host {
|
||||||
|
auth = toRuntimeAuthConfig(ac)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ParseAuth(auth)
|
||||||
}
|
}
|
||||||
return options
|
}
|
||||||
|
|
||||||
|
// getResolver tries registry mirrors and the default registry, and returns the resolver and descriptor
|
||||||
|
// from the first working registry.
|
||||||
|
func (c *criService) getResolver(ctx context.Context, ref string, cred func(string) (string, string, error)) (remotes.Resolver, imagespec.Descriptor, error) {
|
||||||
|
refspec, err := reference.Parse(ref)
|
||||||
|
if err != nil {
|
||||||
|
return nil, imagespec.Descriptor{}, errors.Wrap(err, "parse image reference")
|
||||||
|
}
|
||||||
|
// Try mirrors in order first, and then try default host name.
|
||||||
|
for _, e := range c.config.Registry.Mirrors[refspec.Hostname()].Endpoints {
|
||||||
|
u, err := url.Parse(e)
|
||||||
|
if err != nil {
|
||||||
|
return nil, imagespec.Descriptor{}, errors.Wrapf(err, "parse registry endpoint %q", e)
|
||||||
|
}
|
||||||
|
resolver := docker.NewResolver(docker.ResolverOptions{
|
||||||
|
Credentials: cred,
|
||||||
|
Client: http.DefaultClient,
|
||||||
|
Host: func(string) (string, error) { return u.Host, nil },
|
||||||
|
// By default use "https".
|
||||||
|
PlainHTTP: u.Scheme == "http",
|
||||||
|
})
|
||||||
|
_, desc, err := resolver.Resolve(ctx, ref)
|
||||||
|
if err == nil {
|
||||||
|
return resolver, desc, nil
|
||||||
|
}
|
||||||
|
// Continue to try next endpoint
|
||||||
|
}
|
||||||
|
resolver := docker.NewResolver(docker.ResolverOptions{
|
||||||
|
Credentials: cred,
|
||||||
|
Client: http.DefaultClient,
|
||||||
|
})
|
||||||
|
_, desc, err := resolver.Resolve(ctx, ref)
|
||||||
|
if err != nil {
|
||||||
|
return nil, imagespec.Descriptor{}, errors.Wrap(err, "no available registry endpoint")
|
||||||
|
}
|
||||||
|
return resolver, desc, nil
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,8 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
||||||
|
|
||||||
|
criconfig "github.com/containerd/cri/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseAuth(t *testing.T) {
|
func TestParseAuth(t *testing.T) {
|
||||||
@ -72,3 +74,58 @@ func TestParseAuth(t *testing.T) {
|
|||||||
assert.Equal(t, test.expectedSecret, s)
|
assert.Equal(t, test.expectedSecret, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCredentials(t *testing.T) {
|
||||||
|
c := newTestCRIService()
|
||||||
|
c.config.Registry.Auths = map[string]criconfig.AuthConfig{
|
||||||
|
"https://test1.io": {
|
||||||
|
Username: "username1",
|
||||||
|
Password: "password1",
|
||||||
|
},
|
||||||
|
"http://test2.io": {
|
||||||
|
Username: "username2",
|
||||||
|
Password: "password2",
|
||||||
|
},
|
||||||
|
"//test3.io": {
|
||||||
|
Username: "username3",
|
||||||
|
Password: "password3",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for desc, test := range map[string]struct {
|
||||||
|
auth *runtime.AuthConfig
|
||||||
|
host string
|
||||||
|
expectedUsername string
|
||||||
|
expectedPassword string
|
||||||
|
}{
|
||||||
|
"auth config from CRI should take precedence": {
|
||||||
|
auth: &runtime.AuthConfig{
|
||||||
|
Username: "username",
|
||||||
|
Password: "password",
|
||||||
|
},
|
||||||
|
host: "test1.io",
|
||||||
|
expectedUsername: "username",
|
||||||
|
expectedPassword: "password",
|
||||||
|
},
|
||||||
|
"should support https host": {
|
||||||
|
host: "test1.io",
|
||||||
|
expectedUsername: "username1",
|
||||||
|
expectedPassword: "password1",
|
||||||
|
},
|
||||||
|
"should support http host": {
|
||||||
|
host: "test2.io",
|
||||||
|
expectedUsername: "username2",
|
||||||
|
expectedPassword: "password2",
|
||||||
|
},
|
||||||
|
"should support hostname only": {
|
||||||
|
host: "test3.io",
|
||||||
|
expectedUsername: "username3",
|
||||||
|
expectedPassword: "password3",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Logf("TestCase %q", desc)
|
||||||
|
username, password, err := c.credentials(test.auth)(test.host)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, test.expectedUsername, username)
|
||||||
|
assert.Equal(t, test.expectedPassword, password)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
10
vendor.conf
10
vendor.conf
@ -3,13 +3,14 @@ github.com/blang/semver v3.1.0
|
|||||||
github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd
|
github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd
|
||||||
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
|
github.com/BurntSushi/toml a368813c5e648fee92e5f6c30e3944ff9d5e8895
|
||||||
github.com/containerd/cgroups fe281dd265766145e943a034aa41086474ea6130
|
github.com/containerd/cgroups fe281dd265766145e943a034aa41086474ea6130
|
||||||
github.com/containerd/console 9290d21dc56074581f619579c43d970b4514bc08
|
github.com/containerd/console 5d1b48d6114b8c9666f0c8b916f871af97b0a761
|
||||||
github.com/containerd/containerd 84bebdd91d347c99069d1705b7d4e6d6f746160c
|
github.com/containerd/containerd b382b6fe0bdbf7604c0a4f5c2089c0b159ad58b2
|
||||||
github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b
|
github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b
|
||||||
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
|
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
|
||||||
github.com/containerd/go-cni 5882530828ecf62032409b298a3e8b19e08b6534
|
github.com/containerd/go-cni 5882530828ecf62032409b298a3e8b19e08b6534
|
||||||
github.com/containerd/go-runc f271fa2021de855d4d918dbef83c5fe19db1bdd5
|
github.com/containerd/go-runc f271fa2021de855d4d918dbef83c5fe19db1bdd5
|
||||||
github.com/containerd/typeurl f6943554a7e7e88b3c14aad190bf05932da84788
|
github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d
|
||||||
|
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
||||||
github.com/containernetworking/cni v0.6.0
|
github.com/containernetworking/cni v0.6.0
|
||||||
github.com/containernetworking/plugins v0.7.0
|
github.com/containernetworking/plugins v0.7.0
|
||||||
github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6
|
github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6
|
||||||
@ -35,8 +36,8 @@ github.com/json-iterator/go f2b4162afba35581b6d4a50d3b8f34e33c144682
|
|||||||
github.com/matttproud/golang_protobuf_extensions v1.0.0
|
github.com/matttproud/golang_protobuf_extensions v1.0.0
|
||||||
github.com/Microsoft/go-winio v0.4.7
|
github.com/Microsoft/go-winio v0.4.7
|
||||||
github.com/Microsoft/hcsshim v0.6.11
|
github.com/Microsoft/hcsshim v0.6.11
|
||||||
github.com/modern-go/reflect2 05fbef0ca5da472bbf96c9322b84a53edc03c9fd
|
|
||||||
github.com/modern-go/concurrent 1.0.3
|
github.com/modern-go/concurrent 1.0.3
|
||||||
|
github.com/modern-go/reflect2 05fbef0ca5da472bbf96c9322b84a53edc03c9fd
|
||||||
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
||||||
github.com/opencontainers/image-spec v1.0.1
|
github.com/opencontainers/image-spec v1.0.1
|
||||||
github.com/opencontainers/runc 69663f0bd4b60df09991c08812a60108003fa340
|
github.com/opencontainers/runc 69663f0bd4b60df09991c08812a60108003fa340
|
||||||
@ -51,7 +52,6 @@ github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563
|
|||||||
github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd
|
github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd
|
||||||
github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
|
github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
|
||||||
github.com/sirupsen/logrus v1.0.0
|
github.com/sirupsen/logrus v1.0.0
|
||||||
github.com/stevvooe/ttrpc d4528379866b0ce7e9d71f3eb96f0582fc374577
|
|
||||||
github.com/stretchr/testify v1.1.4
|
github.com/stretchr/testify v1.1.4
|
||||||
github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
|
github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
|
||||||
github.com/tchap/go-patricia 5ad6cdb7538b0097d5598c7e57f0a24072adf7dc
|
github.com/tchap/go-patricia 5ad6cdb7538b0097d5598c7e57f0a24072adf7dc
|
||||||
|
4
vendor/github.com/containerd/console/console_linux.go
generated
vendored
4
vendor/github.com/containerd/console/console_linux.go
generated
vendored
@ -262,10 +262,14 @@ func (ec *EpollConsole) Shutdown(close func(int) error) error {
|
|||||||
|
|
||||||
// signalRead signals that the console is readable.
|
// signalRead signals that the console is readable.
|
||||||
func (ec *EpollConsole) signalRead() {
|
func (ec *EpollConsole) signalRead() {
|
||||||
|
ec.readc.L.Lock()
|
||||||
ec.readc.Signal()
|
ec.readc.Signal()
|
||||||
|
ec.readc.L.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// signalWrite signals that the console is writable.
|
// signalWrite signals that the console is writable.
|
||||||
func (ec *EpollConsole) signalWrite() {
|
func (ec *EpollConsole) signalWrite() {
|
||||||
|
ec.writec.L.Lock()
|
||||||
ec.writec.Signal()
|
ec.writec.Signal()
|
||||||
|
ec.writec.L.Unlock()
|
||||||
}
|
}
|
||||||
|
11
vendor/github.com/containerd/containerd/cio/io.go
generated
vendored
11
vendor/github.com/containerd/containerd/cio/io.go
generated
vendored
@ -255,3 +255,14 @@ func (l *logIO) Wait() {
|
|||||||
func (l *logIO) Close() error {
|
func (l *logIO) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load the io for a container but do not attach
|
||||||
|
//
|
||||||
|
// Allows io to be loaded on the task for deletion without
|
||||||
|
// starting copy routines
|
||||||
|
func Load(set *FIFOSet) (IO, error) {
|
||||||
|
return &cio{
|
||||||
|
config: set.Config,
|
||||||
|
closers: []io.Closer{set},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
1
vendor/github.com/containerd/containerd/cmd/containerd/command/main.go
generated
vendored
1
vendor/github.com/containerd/containerd/cmd/containerd/command/main.go
generated
vendored
@ -88,6 +88,7 @@ func App() *cli.App {
|
|||||||
app.Commands = []cli.Command{
|
app.Commands = []cli.Command{
|
||||||
configCommand,
|
configCommand,
|
||||||
publishCommand,
|
publishCommand,
|
||||||
|
ociHook,
|
||||||
}
|
}
|
||||||
app.Action = func(context *cli.Context) error {
|
app.Action = func(context *cli.Context) error {
|
||||||
var (
|
var (
|
||||||
|
136
vendor/github.com/containerd/containerd/cmd/containerd/command/oci-hook.go
generated
vendored
Normal file
136
vendor/github.com/containerd/containerd/cmd/containerd/command/oci-hook.go
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
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 command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ociHook = cli.Command{
|
||||||
|
Name: "oci-hook",
|
||||||
|
Usage: "provides a base for OCI runtime hooks to allow arguments to be injected.",
|
||||||
|
Action: func(context *cli.Context) error {
|
||||||
|
state, err := loadHookState(os.Stdin)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
ctx = newTemplateContext(state)
|
||||||
|
args = []string(context.Args())
|
||||||
|
env = os.Environ()
|
||||||
|
)
|
||||||
|
if err := newList(&args).render(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := newList(&env).render(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return syscall.Exec(args[0], args, env)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadHookState(r io.Reader) (*specs.State, error) {
|
||||||
|
var s specs.State
|
||||||
|
if err := json.NewDecoder(r).Decode(&s); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTemplateContext(state *specs.State) *templateContext {
|
||||||
|
t := &templateContext{
|
||||||
|
state: state,
|
||||||
|
}
|
||||||
|
t.funcs = template.FuncMap{
|
||||||
|
"id": t.id,
|
||||||
|
"bundle": t.bundle,
|
||||||
|
"rootfs": t.rootfs,
|
||||||
|
"pid": t.pid,
|
||||||
|
"annotation": t.annotation,
|
||||||
|
"status": t.status,
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
type templateContext struct {
|
||||||
|
state *specs.State
|
||||||
|
funcs template.FuncMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *templateContext) id() string {
|
||||||
|
return t.state.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *templateContext) bundle() string {
|
||||||
|
return t.state.Bundle
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *templateContext) rootfs() string {
|
||||||
|
return filepath.Join(t.state.Bundle, "rootfs")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *templateContext) pid() int {
|
||||||
|
return t.state.Pid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *templateContext) annotation(k string) string {
|
||||||
|
return t.state.Annotations[k]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *templateContext) status() string {
|
||||||
|
return t.state.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
func render(ctx *templateContext, source string, out io.Writer) error {
|
||||||
|
t, err := template.New("oci-hook").Funcs(ctx.funcs).Parse(source)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return t.Execute(out, ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newList(l *[]string) *templateList {
|
||||||
|
return &templateList{
|
||||||
|
l: l,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type templateList struct {
|
||||||
|
l *[]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *templateList) render(ctx *templateContext) error {
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
for i, s := range *l.l {
|
||||||
|
buf.Reset()
|
||||||
|
if err := render(ctx, s, buf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
(*l.l)[i] = buf.String()
|
||||||
|
}
|
||||||
|
buf.Reset()
|
||||||
|
return nil
|
||||||
|
}
|
62
vendor/github.com/containerd/containerd/cmd/ctr/commands/commands.go
generated
vendored
62
vendor/github.com/containerd/containerd/cmd/ctr/commands/commands.go
generated
vendored
@ -21,6 +21,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
@ -63,6 +64,67 @@ var (
|
|||||||
Usage: "refresh token for authorization server",
|
Usage: "refresh token for authorization server",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ContainerFlags are cli flags specifying container options
|
||||||
|
ContainerFlags = []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "config,c",
|
||||||
|
Usage: "path to the runtime-specific spec config file",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "checkpoint",
|
||||||
|
Usage: "provide the checkpoint digest to restore the container",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "cwd",
|
||||||
|
Usage: "specify the working directory of the process",
|
||||||
|
},
|
||||||
|
cli.StringSliceFlag{
|
||||||
|
Name: "env",
|
||||||
|
Usage: "specify additional container environment variables (i.e. FOO=bar)",
|
||||||
|
},
|
||||||
|
cli.StringSliceFlag{
|
||||||
|
Name: "label",
|
||||||
|
Usage: "specify additional labels (i.e. foo=bar)",
|
||||||
|
},
|
||||||
|
cli.StringSliceFlag{
|
||||||
|
Name: "mount",
|
||||||
|
Usage: "specify additional container mount (ex: type=bind,src=/tmp,dst=/host,options=rbind:ro)",
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "net-host",
|
||||||
|
Usage: "enable host networking for the container",
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "privileged",
|
||||||
|
Usage: "run privileged container",
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "read-only",
|
||||||
|
Usage: "set the containers filesystem as readonly",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "runtime",
|
||||||
|
Usage: "runtime name (io.containerd.runtime.v1.linux, io.containerd.runtime.v1.windows, io.containerd.runtime.v1.com.vmware.linux)",
|
||||||
|
Value: fmt.Sprintf("io.containerd.runtime.v1.%s", runtime.GOOS),
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "tty,t",
|
||||||
|
Usage: "allocate a TTY for the container",
|
||||||
|
},
|
||||||
|
cli.StringSliceFlag{
|
||||||
|
Name: "with-ns",
|
||||||
|
Usage: "specify existing Linux namespaces to join at container runtime (format '<nstype>:<path>')",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "pid-file",
|
||||||
|
Usage: "file path to write the task's pid",
|
||||||
|
},
|
||||||
|
cli.IntFlag{
|
||||||
|
Name: "gpus",
|
||||||
|
Usage: "add gpus to the container",
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// ObjectWithLabelArgs returns the first arg and a LabelArgs object
|
// ObjectWithLabelArgs returns the first arg and a LabelArgs object
|
||||||
|
33
vendor/github.com/containerd/containerd/cmd/ctr/commands/commands_unix.go
generated
vendored
Normal file
33
vendor/github.com/containerd/containerd/cmd/ctr/commands/commands_unix.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// +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 commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ContainerFlags = append(ContainerFlags, cli.BoolFlag{
|
||||||
|
Name: "rootfs",
|
||||||
|
Usage: "use custom rootfs that is not managed by containerd snapshotter",
|
||||||
|
}, cli.BoolFlag{
|
||||||
|
Name: "no-pivot",
|
||||||
|
Usage: "disable use of pivot-root (linux only)",
|
||||||
|
})
|
||||||
|
}
|
6
vendor/github.com/containerd/containerd/cmd/ctr/commands/containers/containers.go
generated
vendored
6
vendor/github.com/containerd/containerd/cmd/ctr/commands/containers/containers.go
generated
vendored
@ -25,6 +25,7 @@ import (
|
|||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/containerd/containerd/cio"
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/run"
|
"github.com/containerd/containerd/cmd/ctr/commands/run"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
@ -49,7 +50,7 @@ var createCommand = cli.Command{
|
|||||||
Name: "create",
|
Name: "create",
|
||||||
Usage: "create container",
|
Usage: "create container",
|
||||||
ArgsUsage: "[flags] Image|RootFS CONTAINER",
|
ArgsUsage: "[flags] Image|RootFS CONTAINER",
|
||||||
Flags: append(commands.SnapshotterFlags, run.ContainerFlags...),
|
Flags: append(commands.SnapshotterFlags, commands.ContainerFlags...),
|
||||||
Action: func(context *cli.Context) error {
|
Action: func(context *cli.Context) error {
|
||||||
var (
|
var (
|
||||||
id = context.Args().Get(1)
|
id = context.Args().Get(1)
|
||||||
@ -162,7 +163,6 @@ var deleteCommand = cli.Command{
|
|||||||
log.G(ctx).WithError(err).Errorf("failed to delete container %q", arg)
|
log.G(ctx).WithError(err).Errorf("failed to delete container %q", arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return exitErr
|
return exitErr
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ func deleteContainer(ctx context.Context, client *containerd.Client, id string,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
task, err := container.Task(ctx, nil)
|
task, err := container.Task(ctx, cio.Load)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return container.Delete(ctx, opts...)
|
return container.Delete(ctx, opts...)
|
||||||
}
|
}
|
||||||
|
9
vendor/github.com/containerd/containerd/cmd/ctr/commands/plugins/plugins.go
generated
vendored
9
vendor/github.com/containerd/containerd/cmd/ctr/commands/plugins/plugins.go
generated
vendored
@ -37,6 +37,15 @@ var Command = cli.Command{
|
|||||||
Name: "plugins",
|
Name: "plugins",
|
||||||
Aliases: []string{"plugin"},
|
Aliases: []string{"plugin"},
|
||||||
Usage: "provides information about containerd plugins",
|
Usage: "provides information about containerd plugins",
|
||||||
|
Subcommands: []cli.Command{
|
||||||
|
listCommand,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var listCommand = cli.Command{
|
||||||
|
Name: "list",
|
||||||
|
Aliases: []string{"ls"},
|
||||||
|
Usage: "lists containerd plugins",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "quiet,q",
|
Name: "quiet,q",
|
||||||
|
60
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run.go
generated
vendored
60
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run.go
generated
vendored
@ -22,7 +22,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/console"
|
"github.com/containerd/console"
|
||||||
@ -38,63 +37,6 @@ import (
|
|||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ContainerFlags are cli flags specifying container options
|
|
||||||
var ContainerFlags = []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config,c",
|
|
||||||
Usage: "path to the runtime-specific spec config file",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "checkpoint",
|
|
||||||
Usage: "provide the checkpoint digest to restore the container",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "cwd",
|
|
||||||
Usage: "specify the working directory of the process",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "env",
|
|
||||||
Usage: "specify additional container environment variables (i.e. FOO=bar)",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "label",
|
|
||||||
Usage: "specify additional labels (i.e. foo=bar)",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "mount",
|
|
||||||
Usage: "specify additional container mount (ex: type=bind,src=/tmp,dst=/host,options=rbind:ro)",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "net-host",
|
|
||||||
Usage: "enable host networking for the container",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "privileged",
|
|
||||||
Usage: "run privileged container",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "read-only",
|
|
||||||
Usage: "set the containers filesystem as readonly",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "runtime",
|
|
||||||
Usage: "runtime name (io.containerd.runtime.v1.linux, io.containerd.runtime.v1.windows, io.containerd.runtime.v1.com.vmware.linux)",
|
|
||||||
Value: fmt.Sprintf("io.containerd.runtime.v1.%s", runtime.GOOS),
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "tty,t",
|
|
||||||
Usage: "allocate a TTY for the container",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "with-ns",
|
|
||||||
Usage: "specify existing Linux namespaces to join at container runtime (format '<nstype>:<path>')",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "pid-file",
|
|
||||||
Usage: "file path to write the task's pid",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadSpec(path string, s *specs.Spec) error {
|
func loadSpec(path string, s *specs.Spec) error {
|
||||||
raw, err := ioutil.ReadFile(path)
|
raw, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -177,7 +119,7 @@ var Command = cli.Command{
|
|||||||
Name: "fifo-dir",
|
Name: "fifo-dir",
|
||||||
Usage: "directory used for storing IO FIFOs",
|
Usage: "directory used for storing IO FIFOs",
|
||||||
},
|
},
|
||||||
}, append(commands.SnapshotterFlags, ContainerFlags...)...),
|
}, append(commands.SnapshotterFlags, commands.ContainerFlags...)...),
|
||||||
Action: func(context *cli.Context) error {
|
Action: func(context *cli.Context) error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
|
14
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_unix.go
generated
vendored
14
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_unix.go
generated
vendored
@ -24,22 +24,13 @@ import (
|
|||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||||
|
"github.com/containerd/containerd/contrib/nvidia"
|
||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
ContainerFlags = append(ContainerFlags, cli.BoolFlag{
|
|
||||||
Name: "rootfs",
|
|
||||||
Usage: "use custom rootfs that is not managed by containerd snapshotter",
|
|
||||||
}, cli.BoolFlag{
|
|
||||||
Name: "no-pivot",
|
|
||||||
Usage: "disable use of pivot-root (linux only)",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewContainer creates a new container
|
// NewContainer creates a new container
|
||||||
func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli.Context) (containerd.Container, error) {
|
func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli.Context) (containerd.Container, error) {
|
||||||
var (
|
var (
|
||||||
@ -123,6 +114,9 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli
|
|||||||
Path: parts[1],
|
Path: parts[1],
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
if context.IsSet("gpus") {
|
||||||
|
opts = append(opts, nvidia.WithGPUs(nvidia.WithDevices(context.Int("gpus")), nvidia.WithAllCapabilities))
|
||||||
|
}
|
||||||
if context.IsSet("config") {
|
if context.IsSet("config") {
|
||||||
var s specs.Spec
|
var s specs.Spec
|
||||||
if err := loadSpec(context.String("config"), &s); err != nil {
|
if err := loadSpec(context.String("config"), &s); err != nil {
|
||||||
|
4
vendor/github.com/containerd/containerd/cmd/ctr/commands/shim/shim.go
generated
vendored
4
vendor/github.com/containerd/containerd/cmd/ctr/commands/shim/shim.go
generated
vendored
@ -26,13 +26,13 @@ import (
|
|||||||
|
|
||||||
"github.com/containerd/console"
|
"github.com/containerd/console"
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||||
shim "github.com/containerd/containerd/runtime/linux/shim/v1"
|
shim "github.com/containerd/containerd/runtime/shim/v1"
|
||||||
|
"github.com/containerd/ttrpc"
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
ptypes "github.com/gogo/protobuf/types"
|
ptypes "github.com/gogo/protobuf/types"
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/stevvooe/ttrpc"
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
4
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/delete.go
generated
vendored
4
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/delete.go
generated
vendored
@ -18,6 +18,7 @@ package tasks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/containerd/containerd/cio"
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
@ -42,8 +43,7 @@ var deleteCommand = cli.Command{
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
task, err := container.Task(ctx, cio.Load)
|
||||||
task, err := container.Task(ctx, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
9
vendor/github.com/containerd/containerd/container.go
generated
vendored
9
vendor/github.com/containerd/containerd/container.go
generated
vendored
@ -307,6 +307,12 @@ func (c *container) get(ctx context.Context) (containers.Container, error) {
|
|||||||
|
|
||||||
// get the existing fifo paths from the task information stored by the daemon
|
// get the existing fifo paths from the task information stored by the daemon
|
||||||
func attachExistingIO(response *tasks.GetResponse, ioAttach cio.Attach) (cio.IO, error) {
|
func attachExistingIO(response *tasks.GetResponse, ioAttach cio.Attach) (cio.IO, error) {
|
||||||
|
fifoSet := loadFifos(response)
|
||||||
|
return ioAttach(fifoSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadFifos loads the containers fifos
|
||||||
|
func loadFifos(response *tasks.GetResponse) *cio.FIFOSet {
|
||||||
path := getFifoDir([]string{
|
path := getFifoDir([]string{
|
||||||
response.Process.Stdin,
|
response.Process.Stdin,
|
||||||
response.Process.Stdout,
|
response.Process.Stdout,
|
||||||
@ -315,13 +321,12 @@ func attachExistingIO(response *tasks.GetResponse, ioAttach cio.Attach) (cio.IO,
|
|||||||
closer := func() error {
|
closer := func() error {
|
||||||
return os.RemoveAll(path)
|
return os.RemoveAll(path)
|
||||||
}
|
}
|
||||||
fifoSet := cio.NewFIFOSet(cio.Config{
|
return cio.NewFIFOSet(cio.Config{
|
||||||
Stdin: response.Process.Stdin,
|
Stdin: response.Process.Stdin,
|
||||||
Stdout: response.Process.Stdout,
|
Stdout: response.Process.Stdout,
|
||||||
Stderr: response.Process.Stderr,
|
Stderr: response.Process.Stderr,
|
||||||
Terminal: response.Process.Terminal,
|
Terminal: response.Process.Terminal,
|
||||||
}, closer)
|
}, closer)
|
||||||
return ioAttach(fifoSet)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getFifoDir looks for any non-empty path for a stdio fifo
|
// getFifoDir looks for any non-empty path for a stdio fifo
|
||||||
|
185
vendor/github.com/containerd/containerd/contrib/nvidia/nvidia.go
generated
vendored
Normal file
185
vendor/github.com/containerd/containerd/contrib/nvidia/nvidia.go
generated
vendored
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
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 nvidia
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/containers"
|
||||||
|
"github.com/containerd/containerd/oci"
|
||||||
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
const nvidiaCLI = "nvidia-container-cli"
|
||||||
|
|
||||||
|
// Capability specifies capabilities for the gpu inside the container
|
||||||
|
// Detailed explaination of options can be found:
|
||||||
|
// https://github.com/nvidia/nvidia-container-runtime#supported-driver-capabilities
|
||||||
|
type Capability int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Compute capability
|
||||||
|
Compute Capability = iota + 1
|
||||||
|
// Compat32 capability
|
||||||
|
Compat32
|
||||||
|
// Graphics capability
|
||||||
|
Graphics
|
||||||
|
// Utility capability
|
||||||
|
Utility
|
||||||
|
// Video capability
|
||||||
|
Video
|
||||||
|
// Display capability
|
||||||
|
Display
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithGPUs adds NVIDIA gpu support to a container
|
||||||
|
func WithGPUs(opts ...Opts) oci.SpecOpts {
|
||||||
|
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
|
||||||
|
c := &config{}
|
||||||
|
for _, o := range opts {
|
||||||
|
if err := o(c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path, err := exec.LookPath("containerd")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nvidiaPath, err := exec.LookPath(nvidiaCLI)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if s.Hooks == nil {
|
||||||
|
s.Hooks = &specs.Hooks{}
|
||||||
|
}
|
||||||
|
s.Hooks.Prestart = append(s.Hooks.Prestart, specs.Hook{
|
||||||
|
Path: path,
|
||||||
|
Args: append([]string{
|
||||||
|
"containerd",
|
||||||
|
"oci-hook",
|
||||||
|
"--",
|
||||||
|
nvidiaPath,
|
||||||
|
}, c.args()...),
|
||||||
|
Env: os.Environ(),
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
Devices []int
|
||||||
|
DeviceUUID string
|
||||||
|
Capabilities []Capability
|
||||||
|
LoadKmods bool
|
||||||
|
LDCache string
|
||||||
|
LDConfig string
|
||||||
|
Requirements []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *config) args() []string {
|
||||||
|
var args []string
|
||||||
|
|
||||||
|
if c.LoadKmods {
|
||||||
|
args = append(args, "--load-kmods")
|
||||||
|
}
|
||||||
|
if c.LDCache != "" {
|
||||||
|
args = append(args, fmt.Sprintf("--ldcache=%s", c.LDCache))
|
||||||
|
}
|
||||||
|
args = append(args,
|
||||||
|
"configure",
|
||||||
|
)
|
||||||
|
if len(c.Devices) > 0 {
|
||||||
|
args = append(args, fmt.Sprintf("--device=%s", strings.Join(toStrings(c.Devices), ",")))
|
||||||
|
}
|
||||||
|
if c.DeviceUUID != "" {
|
||||||
|
args = append(args, fmt.Sprintf("--device=%s", c.DeviceUUID))
|
||||||
|
}
|
||||||
|
for _, c := range c.Capabilities {
|
||||||
|
args = append(args, fmt.Sprintf("--%s", capFlags[c]))
|
||||||
|
}
|
||||||
|
if c.LDConfig != "" {
|
||||||
|
args = append(args, fmt.Sprintf("--ldconfig=%s", c.LDConfig))
|
||||||
|
}
|
||||||
|
for _, r := range c.Requirements {
|
||||||
|
args = append(args, fmt.Sprintf("--require=%s", r))
|
||||||
|
}
|
||||||
|
args = append(args, "--pid={{pid}}", "{{rootfs}}")
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
var capFlags = map[Capability]string{
|
||||||
|
Compute: "compute",
|
||||||
|
Compat32: "compat32",
|
||||||
|
Graphics: "graphics",
|
||||||
|
Utility: "utility",
|
||||||
|
Video: "video",
|
||||||
|
Display: "display",
|
||||||
|
}
|
||||||
|
|
||||||
|
func toStrings(ints []int) []string {
|
||||||
|
var s []string
|
||||||
|
for _, i := range ints {
|
||||||
|
s = append(s, strconv.Itoa(i))
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opts are options for configuring gpu support
|
||||||
|
type Opts func(*config) error
|
||||||
|
|
||||||
|
// WithDevices adds the provided device indexes to the container
|
||||||
|
func WithDevices(ids ...int) Opts {
|
||||||
|
return func(c *config) error {
|
||||||
|
c.Devices = ids
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithDeviceUUID adds the specific device UUID to the container
|
||||||
|
func WithDeviceUUID(guid string) Opts {
|
||||||
|
return func(c *config) error {
|
||||||
|
c.DeviceUUID = guid
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithAllDevices adds all gpus to the container
|
||||||
|
func WithAllDevices(c *config) error {
|
||||||
|
c.DeviceUUID = "all"
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithAllCapabilities adds all capabilities to the container for the gpus
|
||||||
|
func WithAllCapabilities(c *config) error {
|
||||||
|
for k := range capFlags {
|
||||||
|
c.Capabilities = append(c.Capabilities, k)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithRequiredCUDAVersion sets the required cuda version
|
||||||
|
func WithRequiredCUDAVersion(major, minor int) Opts {
|
||||||
|
return func(c *config) error {
|
||||||
|
c.Requirements = append(c.Requirements, fmt.Sprintf("cuda>=%d.%d", major, minor))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
13
vendor/github.com/containerd/containerd/images/image.go
generated
vendored
13
vendor/github.com/containerd/containerd/images/image.go
generated
vendored
@ -131,9 +131,12 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc
|
|||||||
var (
|
var (
|
||||||
matcher platforms.Matcher
|
matcher platforms.Matcher
|
||||||
m *ocispec.Manifest
|
m *ocispec.Manifest
|
||||||
|
p ocispec.Platform
|
||||||
|
wasIndex bool
|
||||||
)
|
)
|
||||||
if platform != "" {
|
if platform != "" {
|
||||||
p, err := platforms.Parse(platform)
|
var err error
|
||||||
|
p, err = platforms.Parse(platform)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ocispec.Manifest{}, err
|
return ocispec.Manifest{}, err
|
||||||
}
|
}
|
||||||
@ -201,6 +204,8 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wasIndex = true
|
||||||
|
|
||||||
return descs, nil
|
return descs, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -210,7 +215,11 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc
|
|||||||
}
|
}
|
||||||
|
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return ocispec.Manifest{}, errors.Wrapf(errdefs.ErrNotFound, "manifest %v", image.Digest)
|
err := errors.Wrapf(errdefs.ErrNotFound, "manifest %v", image.Digest)
|
||||||
|
if wasIndex {
|
||||||
|
err = errors.Wrapf(errdefs.ErrNotFound, "no match for current platform %s in manifest %v", platforms.Format(p), image.Digest)
|
||||||
|
}
|
||||||
|
return ocispec.Manifest{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return *m, nil
|
return *m, nil
|
||||||
|
2
vendor/github.com/containerd/containerd/oci/spec_unix.go
generated
vendored
2
vendor/github.com/containerd/containerd/oci/spec_unix.go
generated
vendored
@ -153,7 +153,9 @@ func createDefaultSpec(ctx context.Context, id string) (*Spec, error) {
|
|||||||
},
|
},
|
||||||
Linux: &specs.Linux{
|
Linux: &specs.Linux{
|
||||||
MaskedPaths: []string{
|
MaskedPaths: []string{
|
||||||
|
"/proc/acpi",
|
||||||
"/proc/kcore",
|
"/proc/kcore",
|
||||||
|
"/proc/keys",
|
||||||
"/proc/latency_stats",
|
"/proc/latency_stats",
|
||||||
"/proc/timer_list",
|
"/proc/timer_list",
|
||||||
"/proc/timer_stats",
|
"/proc/timer_stats",
|
||||||
|
11
vendor/github.com/containerd/containerd/platforms/database.go
generated
vendored
11
vendor/github.com/containerd/containerd/platforms/database.go
generated
vendored
@ -89,18 +89,21 @@ func normalizeArch(arch, variant string) (string, string) {
|
|||||||
case "x86_64", "x86-64":
|
case "x86_64", "x86-64":
|
||||||
arch = "amd64"
|
arch = "amd64"
|
||||||
variant = ""
|
variant = ""
|
||||||
case "aarch64":
|
case "aarch64", "arm64":
|
||||||
arch = "arm64"
|
arch = "arm64"
|
||||||
variant = "" // v8 is implied
|
switch variant {
|
||||||
|
case "8", "v8":
|
||||||
|
variant = ""
|
||||||
|
}
|
||||||
case "armhf":
|
case "armhf":
|
||||||
arch = "arm"
|
arch = "arm"
|
||||||
variant = ""
|
variant = "v7"
|
||||||
case "armel":
|
case "armel":
|
||||||
arch = "arm"
|
arch = "arm"
|
||||||
variant = "v6"
|
variant = "v6"
|
||||||
case "arm":
|
case "arm":
|
||||||
switch variant {
|
switch variant {
|
||||||
case "v7", "7":
|
case "", "7":
|
||||||
variant = "v7"
|
variant = "v7"
|
||||||
case "5", "6", "8":
|
case "5", "6", "8":
|
||||||
variant = "v" + variant
|
variant = "v" + variant
|
||||||
|
11
vendor/github.com/containerd/containerd/platforms/platforms.go
generated
vendored
11
vendor/github.com/containerd/containerd/platforms/platforms.go
generated
vendored
@ -135,7 +135,7 @@ type Matcher interface {
|
|||||||
// Applications should opt to use `Match` over directly parsing specifiers.
|
// Applications should opt to use `Match` over directly parsing specifiers.
|
||||||
func NewMatcher(platform specs.Platform) Matcher {
|
func NewMatcher(platform specs.Platform) Matcher {
|
||||||
return &matcher{
|
return &matcher{
|
||||||
Platform: platform,
|
Platform: Normalize(platform),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,6 +197,9 @@ func Parse(specifier string) (specs.Platform, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.Architecture, p.Variant = normalizeArch(parts[0], "")
|
p.Architecture, p.Variant = normalizeArch(parts[0], "")
|
||||||
|
if p.Architecture == "arm" && p.Variant == "v7" {
|
||||||
|
p.Variant = ""
|
||||||
|
}
|
||||||
if isKnownArch(p.Architecture) {
|
if isKnownArch(p.Architecture) {
|
||||||
p.OS = runtime.GOOS
|
p.OS = runtime.GOOS
|
||||||
return p, nil
|
return p, nil
|
||||||
@ -208,12 +211,18 @@ func Parse(specifier string) (specs.Platform, error) {
|
|||||||
// about whether or not we know of the platform.
|
// about whether or not we know of the platform.
|
||||||
p.OS = normalizeOS(parts[0])
|
p.OS = normalizeOS(parts[0])
|
||||||
p.Architecture, p.Variant = normalizeArch(parts[1], "")
|
p.Architecture, p.Variant = normalizeArch(parts[1], "")
|
||||||
|
if p.Architecture == "arm" && p.Variant == "v7" {
|
||||||
|
p.Variant = ""
|
||||||
|
}
|
||||||
|
|
||||||
return p, nil
|
return p, nil
|
||||||
case 3:
|
case 3:
|
||||||
// we have a fully specified variant, this is rare
|
// we have a fully specified variant, this is rare
|
||||||
p.OS = normalizeOS(parts[0])
|
p.OS = normalizeOS(parts[0])
|
||||||
p.Architecture, p.Variant = normalizeArch(parts[1], parts[2])
|
p.Architecture, p.Variant = normalizeArch(parts[1], parts[2])
|
||||||
|
if p.Architecture == "arm64" && p.Variant == "" {
|
||||||
|
p.Variant = "v8"
|
||||||
|
}
|
||||||
|
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
9
vendor/github.com/containerd/containerd/remotes/docker/pusher.go
generated
vendored
9
vendor/github.com/containerd/containerd/remotes/docker/pusher.go
generated
vendored
@ -155,10 +155,19 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
|||||||
location := resp.Header.Get("Location")
|
location := resp.Header.Get("Location")
|
||||||
// Support paths without host in location
|
// Support paths without host in location
|
||||||
if strings.HasPrefix(location, "/") {
|
if strings.HasPrefix(location, "/") {
|
||||||
|
// Support location string containing path and query
|
||||||
|
qmIndex := strings.Index(location, "?")
|
||||||
|
if qmIndex > 0 {
|
||||||
|
u := p.base
|
||||||
|
u.Path = location[:qmIndex]
|
||||||
|
u.RawQuery = location[qmIndex+1:]
|
||||||
|
location = u.String()
|
||||||
|
} else {
|
||||||
u := p.base
|
u := p.base
|
||||||
u.Path = location
|
u.Path = location
|
||||||
location = u.String()
|
location = u.String()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
req, err = http.NewRequest(http.MethodPut, location, nil)
|
req, err = http.NewRequest(http.MethodPut, location, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
34
vendor/github.com/containerd/containerd/remotes/docker/resolver.go
generated
vendored
34
vendor/github.com/containerd/containerd/remotes/docker/resolver.go
generated
vendored
@ -53,6 +53,7 @@ var (
|
|||||||
|
|
||||||
type dockerResolver struct {
|
type dockerResolver struct {
|
||||||
credentials func(string) (string, string, error)
|
credentials func(string) (string, string, error)
|
||||||
|
host func(string) (string, error)
|
||||||
plainHTTP bool
|
plainHTTP bool
|
||||||
client *http.Client
|
client *http.Client
|
||||||
tracker StatusTracker
|
tracker StatusTracker
|
||||||
@ -65,6 +66,9 @@ type ResolverOptions struct {
|
|||||||
// is interpretted as a long lived token.
|
// is interpretted as a long lived token.
|
||||||
Credentials func(string) (string, string, error)
|
Credentials func(string) (string, string, error)
|
||||||
|
|
||||||
|
// Host provides the hostname given a namespace.
|
||||||
|
Host func(string) (string, error)
|
||||||
|
|
||||||
// PlainHTTP specifies to use plain http and not https
|
// PlainHTTP specifies to use plain http and not https
|
||||||
PlainHTTP bool
|
PlainHTTP bool
|
||||||
|
|
||||||
@ -77,14 +81,27 @@ type ResolverOptions struct {
|
|||||||
Tracker StatusTracker
|
Tracker StatusTracker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultHost is the default host function.
|
||||||
|
func DefaultHost(ns string) (string, error) {
|
||||||
|
if ns == "docker.io" {
|
||||||
|
return "registry-1.docker.io", nil
|
||||||
|
}
|
||||||
|
return ns, nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewResolver returns a new resolver to a Docker registry
|
// NewResolver returns a new resolver to a Docker registry
|
||||||
func NewResolver(options ResolverOptions) remotes.Resolver {
|
func NewResolver(options ResolverOptions) remotes.Resolver {
|
||||||
tracker := options.Tracker
|
tracker := options.Tracker
|
||||||
if tracker == nil {
|
if tracker == nil {
|
||||||
tracker = NewInMemoryTracker()
|
tracker = NewInMemoryTracker()
|
||||||
}
|
}
|
||||||
|
host := options.Host
|
||||||
|
if host == nil {
|
||||||
|
host = DefaultHost
|
||||||
|
}
|
||||||
return &dockerResolver{
|
return &dockerResolver{
|
||||||
credentials: options.Credentials,
|
credentials: options.Credentials,
|
||||||
|
host: host,
|
||||||
plainHTTP: options.PlainHTTP,
|
plainHTTP: options.PlainHTTP,
|
||||||
client: options.Client,
|
client: options.Client,
|
||||||
tracker: tracker,
|
tracker: tracker,
|
||||||
@ -270,18 +287,19 @@ func (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
host := refspec.Hostname()
|
host := refspec.Hostname()
|
||||||
base.Scheme = "https"
|
|
||||||
|
|
||||||
if host == "docker.io" {
|
|
||||||
base.Host = "registry-1.docker.io"
|
|
||||||
} else {
|
|
||||||
base.Host = host
|
base.Host = host
|
||||||
|
if r.host != nil {
|
||||||
if r.plainHTTP || strings.HasPrefix(host, "localhost:") {
|
base.Host, err = r.host(host)
|
||||||
base.Scheme = "http"
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base.Scheme = "https"
|
||||||
|
if r.plainHTTP || strings.HasPrefix(base.Host, "localhost:") {
|
||||||
|
base.Scheme = "http"
|
||||||
|
}
|
||||||
|
|
||||||
if r.credentials != nil {
|
if r.credentials != nil {
|
||||||
username, secret, err = r.credentials(base.Host)
|
username, secret, err = r.credentials(base.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
10
vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go
generated
vendored
10
vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go
generated
vendored
@ -257,15 +257,15 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro
|
|||||||
var (
|
var (
|
||||||
ref = remotes.MakeRefKey(ctx, desc)
|
ref = remotes.MakeRefKey(ctx, desc)
|
||||||
calc = newBlobStateCalculator()
|
calc = newBlobStateCalculator()
|
||||||
size = desc.Size
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// size may be unknown, set to zero for content ingest
|
// size may be unknown, set to zero for content ingest
|
||||||
if size == -1 {
|
ingestDesc := desc
|
||||||
size = 0
|
if ingestDesc.Size == -1 {
|
||||||
|
ingestDesc.Size = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
cw, err := content.OpenWriter(ctx, c.contentStore, content.WithRef(ref), content.WithDescriptor(desc))
|
cw, err := content.OpenWriter(ctx, c.contentStore, content.WithRef(ref), content.WithDescriptor(ingestDesc))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errdefs.IsAlreadyExists(err) {
|
if !errdefs.IsAlreadyExists(err) {
|
||||||
return err
|
return err
|
||||||
@ -317,7 +317,7 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro
|
|||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
defer pw.Close()
|
defer pw.Close()
|
||||||
|
|
||||||
return content.Copy(ctx, cw, io.TeeReader(rc, pw), size, desc.Digest)
|
return content.Copy(ctx, cw, io.TeeReader(rc, pw), ingestDesc.Size, ingestDesc.Digest)
|
||||||
})
|
})
|
||||||
|
|
||||||
if err := eg.Wait(); err != nil {
|
if err := eg.Wait(); err != nil {
|
||||||
|
4
vendor/github.com/containerd/containerd/runtime/linux/bundle.go
generated
vendored
4
vendor/github.com/containerd/containerd/runtime/linux/bundle.go
generated
vendored
@ -26,8 +26,8 @@ import (
|
|||||||
|
|
||||||
"github.com/containerd/containerd/events/exchange"
|
"github.com/containerd/containerd/events/exchange"
|
||||||
"github.com/containerd/containerd/runtime/linux/runctypes"
|
"github.com/containerd/containerd/runtime/linux/runctypes"
|
||||||
"github.com/containerd/containerd/runtime/linux/shim"
|
"github.com/containerd/containerd/runtime/shim"
|
||||||
"github.com/containerd/containerd/runtime/linux/shim/client"
|
"github.com/containerd/containerd/runtime/shim/client"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
3
vendor/github.com/containerd/containerd/runtime/linux/proc/deleted_state.go
generated
vendored
3
vendor/github.com/containerd/containerd/runtime/linux/proc/deleted_state.go
generated
vendored
@ -22,6 +22,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/containerd/console"
|
"github.com/containerd/console"
|
||||||
|
"github.com/containerd/containerd/runtime/proc"
|
||||||
google_protobuf "github.com/gogo/protobuf/types"
|
google_protobuf "github.com/gogo/protobuf/types"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -65,6 +66,6 @@ func (s *deletedState) SetExited(status int) {
|
|||||||
// no op
|
// no op
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||||
return nil, errors.Errorf("cannot exec in a deleted state")
|
return nil, errors.Errorf("cannot exec in a deleted state")
|
||||||
}
|
}
|
||||||
|
7
vendor/github.com/containerd/containerd/runtime/linux/proc/exec.go
generated
vendored
7
vendor/github.com/containerd/containerd/runtime/linux/proc/exec.go
generated
vendored
@ -31,6 +31,7 @@ import (
|
|||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
"github.com/containerd/console"
|
"github.com/containerd/console"
|
||||||
|
"github.com/containerd/containerd/runtime/proc"
|
||||||
"github.com/containerd/fifo"
|
"github.com/containerd/fifo"
|
||||||
runc "github.com/containerd/go-runc"
|
runc "github.com/containerd/go-runc"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
@ -40,7 +41,7 @@ import (
|
|||||||
type execProcess struct {
|
type execProcess struct {
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
State
|
proc.State
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
id string
|
id string
|
||||||
@ -51,7 +52,7 @@ type execProcess struct {
|
|||||||
pid int
|
pid int
|
||||||
closers []io.Closer
|
closers []io.Closer
|
||||||
stdin io.Closer
|
stdin io.Closer
|
||||||
stdio Stdio
|
stdio proc.Stdio
|
||||||
path string
|
path string
|
||||||
spec specs.Process
|
spec specs.Process
|
||||||
|
|
||||||
@ -127,7 +128,7 @@ func (e *execProcess) Stdin() io.Closer {
|
|||||||
return e.stdin
|
return e.stdin
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *execProcess) Stdio() Stdio {
|
func (e *execProcess) Stdio() proc.Stdio {
|
||||||
return e.stdio
|
return e.stdio
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
vendor/github.com/containerd/containerd/runtime/linux/proc/init.go
generated
vendored
15
vendor/github.com/containerd/containerd/runtime/linux/proc/init.go
generated
vendored
@ -34,6 +34,7 @@ import (
|
|||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
"github.com/containerd/containerd/runtime/linux/runctypes"
|
"github.com/containerd/containerd/runtime/linux/runctypes"
|
||||||
|
"github.com/containerd/containerd/runtime/proc"
|
||||||
"github.com/containerd/fifo"
|
"github.com/containerd/fifo"
|
||||||
runc "github.com/containerd/go-runc"
|
runc "github.com/containerd/go-runc"
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
@ -63,7 +64,7 @@ type Init struct {
|
|||||||
id string
|
id string
|
||||||
bundle string
|
bundle string
|
||||||
console console.Console
|
console console.Console
|
||||||
platform Platform
|
platform proc.Platform
|
||||||
io runc.IO
|
io runc.IO
|
||||||
runtime *runc.Runc
|
runtime *runc.Runc
|
||||||
status int
|
status int
|
||||||
@ -71,7 +72,7 @@ type Init struct {
|
|||||||
pid int
|
pid int
|
||||||
closers []io.Closer
|
closers []io.Closer
|
||||||
stdin io.Closer
|
stdin io.Closer
|
||||||
stdio Stdio
|
stdio proc.Stdio
|
||||||
rootfs string
|
rootfs string
|
||||||
IoUID int
|
IoUID int
|
||||||
IoGID int
|
IoGID int
|
||||||
@ -94,7 +95,7 @@ func NewRunc(root, path, namespace, runtime, criu string, systemd bool) *runc.Ru
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new init process
|
// New returns a new init process
|
||||||
func New(context context.Context, path, workDir, runtimeRoot, namespace, criu string, systemdCgroup bool, platform Platform, r *CreateConfig) (*Init, error) {
|
func New(context context.Context, path, workDir, runtimeRoot, namespace, criu string, systemdCgroup bool, platform proc.Platform, r *CreateConfig) (*Init, error) {
|
||||||
var success bool
|
var success bool
|
||||||
|
|
||||||
var options runctypes.CreateOptions
|
var options runctypes.CreateOptions
|
||||||
@ -134,7 +135,7 @@ func New(context context.Context, path, workDir, runtimeRoot, namespace, criu st
|
|||||||
bundle: r.Bundle,
|
bundle: r.Bundle,
|
||||||
runtime: runtime,
|
runtime: runtime,
|
||||||
platform: platform,
|
platform: platform,
|
||||||
stdio: Stdio{
|
stdio: proc.Stdio{
|
||||||
Stdin: r.Stdin,
|
Stdin: r.Stdin,
|
||||||
Stdout: r.Stdout,
|
Stdout: r.Stdout,
|
||||||
Stderr: r.Stderr,
|
Stderr: r.Stderr,
|
||||||
@ -363,7 +364,7 @@ func (p *Init) Runtime() *runc.Runc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// exec returns a new exec'd process
|
// exec returns a new exec'd process
|
||||||
func (p *Init) exec(context context.Context, path string, r *ExecConfig) (Process, error) {
|
func (p *Init) exec(context context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||||
// process exec request
|
// process exec request
|
||||||
var spec specs.Process
|
var spec specs.Process
|
||||||
if err := json.Unmarshal(r.Spec.Value, &spec); err != nil {
|
if err := json.Unmarshal(r.Spec.Value, &spec); err != nil {
|
||||||
@ -376,7 +377,7 @@ func (p *Init) exec(context context.Context, path string, r *ExecConfig) (Proces
|
|||||||
path: path,
|
path: path,
|
||||||
parent: p,
|
parent: p,
|
||||||
spec: spec,
|
spec: spec,
|
||||||
stdio: Stdio{
|
stdio: proc.Stdio{
|
||||||
Stdin: r.Stdin,
|
Stdin: r.Stdin,
|
||||||
Stdout: r.Stdout,
|
Stdout: r.Stdout,
|
||||||
Stderr: r.Stderr,
|
Stderr: r.Stderr,
|
||||||
@ -430,7 +431,7 @@ func (p *Init) update(context context.Context, r *google_protobuf.Any) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stdio of the process
|
// Stdio of the process
|
||||||
func (p *Init) Stdio() Stdio {
|
func (p *Init) Stdio() proc.Stdio {
|
||||||
return p.stdio
|
return p.stdio
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
vendor/github.com/containerd/containerd/runtime/linux/proc/init_state.go
generated
vendored
15
vendor/github.com/containerd/containerd/runtime/linux/proc/init_state.go
generated
vendored
@ -25,6 +25,7 @@ import (
|
|||||||
|
|
||||||
"github.com/containerd/console"
|
"github.com/containerd/console"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/containerd/containerd/runtime/proc"
|
||||||
"github.com/containerd/fifo"
|
"github.com/containerd/fifo"
|
||||||
runc "github.com/containerd/go-runc"
|
runc "github.com/containerd/go-runc"
|
||||||
google_protobuf "github.com/gogo/protobuf/types"
|
google_protobuf "github.com/gogo/protobuf/types"
|
||||||
@ -32,13 +33,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type initState interface {
|
type initState interface {
|
||||||
State
|
proc.State
|
||||||
|
|
||||||
Pause(context.Context) error
|
Pause(context.Context) error
|
||||||
Resume(context.Context) error
|
Resume(context.Context) error
|
||||||
Update(context.Context, *google_protobuf.Any) error
|
Update(context.Context, *google_protobuf.Any) error
|
||||||
Checkpoint(context.Context, *CheckpointConfig) error
|
Checkpoint(context.Context, *CheckpointConfig) error
|
||||||
Exec(context.Context, string, *ExecConfig) (Process, error)
|
Exec(context.Context, string, *ExecConfig) (proc.Process, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type createdState struct {
|
type createdState struct {
|
||||||
@ -130,7 +131,7 @@ func (s *createdState) SetExited(status int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *createdState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
func (s *createdState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||||
s.p.mu.Lock()
|
s.p.mu.Lock()
|
||||||
defer s.p.mu.Unlock()
|
defer s.p.mu.Unlock()
|
||||||
return s.p.exec(ctx, path, r)
|
return s.p.exec(ctx, path, r)
|
||||||
@ -272,7 +273,7 @@ func (s *createdCheckpointState) SetExited(status int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *createdCheckpointState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
func (s *createdCheckpointState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||||
s.p.mu.Lock()
|
s.p.mu.Lock()
|
||||||
defer s.p.mu.Unlock()
|
defer s.p.mu.Unlock()
|
||||||
|
|
||||||
@ -364,7 +365,7 @@ func (s *runningState) SetExited(status int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *runningState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
func (s *runningState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||||
s.p.mu.Lock()
|
s.p.mu.Lock()
|
||||||
defer s.p.mu.Unlock()
|
defer s.p.mu.Unlock()
|
||||||
return s.p.exec(ctx, path, r)
|
return s.p.exec(ctx, path, r)
|
||||||
@ -456,7 +457,7 @@ func (s *pausedState) SetExited(status int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *pausedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
func (s *pausedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||||
s.p.mu.Lock()
|
s.p.mu.Lock()
|
||||||
defer s.p.mu.Unlock()
|
defer s.p.mu.Unlock()
|
||||||
|
|
||||||
@ -536,7 +537,7 @@ func (s *stoppedState) SetExited(status int) {
|
|||||||
// no op
|
// no op
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||||
s.p.mu.Lock()
|
s.p.mu.Lock()
|
||||||
defer s.p.mu.Unlock()
|
defer s.p.mu.Unlock()
|
||||||
|
|
||||||
|
63
vendor/github.com/containerd/containerd/runtime/linux/proc/process.go
generated
vendored
63
vendor/github.com/containerd/containerd/runtime/linux/proc/process.go
generated
vendored
@ -19,66 +19,12 @@
|
|||||||
package proc
|
package proc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/console"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RuncRoot is the path to the root runc state directory
|
// RuncRoot is the path to the root runc state directory
|
||||||
const RuncRoot = "/run/containerd/runc"
|
const RuncRoot = "/run/containerd/runc"
|
||||||
|
|
||||||
// Stdio of a process
|
|
||||||
type Stdio struct {
|
|
||||||
Stdin string
|
|
||||||
Stdout string
|
|
||||||
Stderr string
|
|
||||||
Terminal bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNull returns true if the stdio is not defined
|
|
||||||
func (s Stdio) IsNull() bool {
|
|
||||||
return s.Stdin == "" && s.Stdout == "" && s.Stderr == ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process on a linux system
|
|
||||||
type Process interface {
|
|
||||||
State
|
|
||||||
// ID returns the id for the process
|
|
||||||
ID() string
|
|
||||||
// Pid returns the pid for the process
|
|
||||||
Pid() int
|
|
||||||
// ExitStatus returns the exit status
|
|
||||||
ExitStatus() int
|
|
||||||
// ExitedAt is the time the process exited
|
|
||||||
ExitedAt() time.Time
|
|
||||||
// Stdin returns the process STDIN
|
|
||||||
Stdin() io.Closer
|
|
||||||
// Stdio returns io information for the container
|
|
||||||
Stdio() Stdio
|
|
||||||
// Status returns the process status
|
|
||||||
Status(context.Context) (string, error)
|
|
||||||
// Wait blocks until the process has exited
|
|
||||||
Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
// State of a process
|
|
||||||
type State interface {
|
|
||||||
// Resize resizes the process console
|
|
||||||
Resize(ws console.WinSize) error
|
|
||||||
// Start execution of the process
|
|
||||||
Start(context.Context) error
|
|
||||||
// Delete deletes the process and its resourcess
|
|
||||||
Delete(context.Context) error
|
|
||||||
// Kill kills the process
|
|
||||||
Kill(context.Context, uint32, bool) error
|
|
||||||
// SetExited sets the exit status for the process
|
|
||||||
SetExited(status int)
|
|
||||||
}
|
|
||||||
|
|
||||||
func stateName(v interface{}) string {
|
func stateName(v interface{}) string {
|
||||||
switch v.(type) {
|
switch v.(type) {
|
||||||
case *runningState, *execRunningState:
|
case *runningState, *execRunningState:
|
||||||
@ -94,12 +40,3 @@ func stateName(v interface{}) string {
|
|||||||
}
|
}
|
||||||
panic(errors.Errorf("invalid state %v", v))
|
panic(errors.Errorf("invalid state %v", v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Platform handles platform-specific behavior that may differs across
|
|
||||||
// platform implementations
|
|
||||||
type Platform interface {
|
|
||||||
CopyConsole(ctx context.Context, console console.Console, stdin, stdout, stderr string,
|
|
||||||
wg, cwg *sync.WaitGroup) (console.Console, error)
|
|
||||||
ShutdownConsole(ctx context.Context, console console.Console) error
|
|
||||||
Close() error
|
|
||||||
}
|
|
||||||
|
4
vendor/github.com/containerd/containerd/runtime/linux/process.go
generated
vendored
4
vendor/github.com/containerd/containerd/runtime/linux/process.go
generated
vendored
@ -25,9 +25,9 @@ import (
|
|||||||
"github.com/containerd/containerd/api/types/task"
|
"github.com/containerd/containerd/api/types/task"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/runtime"
|
"github.com/containerd/containerd/runtime"
|
||||||
shim "github.com/containerd/containerd/runtime/linux/shim/v1"
|
shim "github.com/containerd/containerd/runtime/shim/v1"
|
||||||
|
"github.com/containerd/ttrpc"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/stevvooe/ttrpc"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Process implements a linux process
|
// Process implements a linux process
|
||||||
|
2
vendor/github.com/containerd/containerd/runtime/linux/runtime.go
generated
vendored
2
vendor/github.com/containerd/containerd/runtime/linux/runtime.go
generated
vendored
@ -42,7 +42,7 @@ import (
|
|||||||
"github.com/containerd/containerd/runtime"
|
"github.com/containerd/containerd/runtime"
|
||||||
"github.com/containerd/containerd/runtime/linux/proc"
|
"github.com/containerd/containerd/runtime/linux/proc"
|
||||||
"github.com/containerd/containerd/runtime/linux/runctypes"
|
"github.com/containerd/containerd/runtime/linux/runctypes"
|
||||||
shim "github.com/containerd/containerd/runtime/linux/shim/v1"
|
shim "github.com/containerd/containerd/runtime/shim/v1"
|
||||||
runc "github.com/containerd/go-runc"
|
runc "github.com/containerd/go-runc"
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
ptypes "github.com/gogo/protobuf/types"
|
ptypes "github.com/gogo/protobuf/types"
|
||||||
|
6
vendor/github.com/containerd/containerd/runtime/linux/task.go
generated
vendored
6
vendor/github.com/containerd/containerd/runtime/linux/task.go
generated
vendored
@ -29,12 +29,12 @@ import (
|
|||||||
"github.com/containerd/containerd/events/exchange"
|
"github.com/containerd/containerd/events/exchange"
|
||||||
"github.com/containerd/containerd/identifiers"
|
"github.com/containerd/containerd/identifiers"
|
||||||
"github.com/containerd/containerd/runtime"
|
"github.com/containerd/containerd/runtime"
|
||||||
"github.com/containerd/containerd/runtime/linux/shim/client"
|
"github.com/containerd/containerd/runtime/shim/client"
|
||||||
shim "github.com/containerd/containerd/runtime/linux/shim/v1"
|
shim "github.com/containerd/containerd/runtime/shim/v1"
|
||||||
runc "github.com/containerd/go-runc"
|
runc "github.com/containerd/go-runc"
|
||||||
|
"github.com/containerd/ttrpc"
|
||||||
"github.com/gogo/protobuf/types"
|
"github.com/gogo/protobuf/types"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/stevvooe/ttrpc"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Task on a linux based system
|
// Task on a linux based system
|
||||||
|
83
vendor/github.com/containerd/containerd/runtime/proc/proc.go
generated
vendored
Normal file
83
vendor/github.com/containerd/containerd/runtime/proc/proc.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
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 proc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/console"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Stdio of a process
|
||||||
|
type Stdio struct {
|
||||||
|
Stdin string
|
||||||
|
Stdout string
|
||||||
|
Stderr string
|
||||||
|
Terminal bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNull returns true if the stdio is not defined
|
||||||
|
func (s Stdio) IsNull() bool {
|
||||||
|
return s.Stdin == "" && s.Stdout == "" && s.Stderr == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process on a system
|
||||||
|
type Process interface {
|
||||||
|
State
|
||||||
|
// ID returns the id for the process
|
||||||
|
ID() string
|
||||||
|
// Pid returns the pid for the process
|
||||||
|
Pid() int
|
||||||
|
// ExitStatus returns the exit status
|
||||||
|
ExitStatus() int
|
||||||
|
// ExitedAt is the time the process exited
|
||||||
|
ExitedAt() time.Time
|
||||||
|
// Stdin returns the process STDIN
|
||||||
|
Stdin() io.Closer
|
||||||
|
// Stdio returns io information for the container
|
||||||
|
Stdio() Stdio
|
||||||
|
// Status returns the process status
|
||||||
|
Status(context.Context) (string, error)
|
||||||
|
// Wait blocks until the process has exited
|
||||||
|
Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// State of a process
|
||||||
|
type State interface {
|
||||||
|
// Resize resizes the process console
|
||||||
|
Resize(ws console.WinSize) error
|
||||||
|
// Start execution of the process
|
||||||
|
Start(context.Context) error
|
||||||
|
// Delete deletes the process and its resourcess
|
||||||
|
Delete(context.Context) error
|
||||||
|
// Kill kills the process
|
||||||
|
Kill(context.Context, uint32, bool) error
|
||||||
|
// SetExited sets the exit status for the process
|
||||||
|
SetExited(status int)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Platform handles platform-specific behavior that may differs across
|
||||||
|
// platform implementations
|
||||||
|
type Platform interface {
|
||||||
|
CopyConsole(ctx context.Context, console console.Console, stdin, stdout, stderr string,
|
||||||
|
wg, cwg *sync.WaitGroup) (console.Console, error)
|
||||||
|
ShutdownConsole(ctx context.Context, console console.Console) error
|
||||||
|
Close() error
|
||||||
|
}
|
@ -31,14 +31,14 @@ import (
|
|||||||
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
|
"github.com/containerd/ttrpc"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/stevvooe/ttrpc"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/events"
|
"github.com/containerd/containerd/events"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/runtime/linux/shim"
|
"github.com/containerd/containerd/runtime/shim"
|
||||||
shimapi "github.com/containerd/containerd/runtime/linux/shim/v1"
|
shimapi "github.com/containerd/containerd/runtime/shim/v1"
|
||||||
"github.com/containerd/containerd/sys"
|
"github.com/containerd/containerd/sys"
|
||||||
ptypes "github.com/gogo/protobuf/types"
|
ptypes "github.com/gogo/protobuf/types"
|
||||||
)
|
)
|
||||||
@ -136,6 +136,7 @@ func newCommand(binary, daemonAddress string, debug bool, config shim.Config, so
|
|||||||
// will be mounted by the shim
|
// will be mounted by the shim
|
||||||
cmd.SysProcAttr = getSysProcAttr()
|
cmd.SysProcAttr = getSysProcAttr()
|
||||||
cmd.ExtraFiles = append(cmd.ExtraFiles, socket)
|
cmd.ExtraFiles = append(cmd.ExtraFiles, socket)
|
||||||
|
cmd.Env = append(os.Environ(), "GOMAXPROCS=2")
|
||||||
if debug {
|
if debug {
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
@ -23,7 +23,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
shimapi "github.com/containerd/containerd/runtime/linux/shim/v1"
|
shimapi "github.com/containerd/containerd/runtime/shim/v1"
|
||||||
ptypes "github.com/gogo/protobuf/types"
|
ptypes "github.com/gogo/protobuf/types"
|
||||||
)
|
)
|
||||||
|
|
@ -34,7 +34,8 @@ import (
|
|||||||
"github.com/containerd/containerd/runtime"
|
"github.com/containerd/containerd/runtime"
|
||||||
"github.com/containerd/containerd/runtime/linux/proc"
|
"github.com/containerd/containerd/runtime/linux/proc"
|
||||||
"github.com/containerd/containerd/runtime/linux/runctypes"
|
"github.com/containerd/containerd/runtime/linux/runctypes"
|
||||||
shimapi "github.com/containerd/containerd/runtime/linux/shim/v1"
|
rproc "github.com/containerd/containerd/runtime/proc"
|
||||||
|
shimapi "github.com/containerd/containerd/runtime/shim/v1"
|
||||||
runc "github.com/containerd/go-runc"
|
runc "github.com/containerd/go-runc"
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
ptypes "github.com/gogo/protobuf/types"
|
ptypes "github.com/gogo/protobuf/types"
|
||||||
@ -78,7 +79,7 @@ func NewService(config Config, publisher events.Publisher) (*Service, error) {
|
|||||||
s := &Service{
|
s := &Service{
|
||||||
config: config,
|
config: config,
|
||||||
context: ctx,
|
context: ctx,
|
||||||
processes: make(map[string]proc.Process),
|
processes: make(map[string]rproc.Process),
|
||||||
events: make(chan interface{}, 128),
|
events: make(chan interface{}, 128),
|
||||||
ec: Default.Subscribe(),
|
ec: Default.Subscribe(),
|
||||||
}
|
}
|
||||||
@ -96,9 +97,9 @@ type Service struct {
|
|||||||
|
|
||||||
config Config
|
config Config
|
||||||
context context.Context
|
context context.Context
|
||||||
processes map[string]proc.Process
|
processes map[string]rproc.Process
|
||||||
events chan interface{}
|
events chan interface{}
|
||||||
platform proc.Platform
|
platform rproc.Platform
|
||||||
ec chan runc.Exit
|
ec chan runc.Exit
|
||||||
|
|
||||||
// Filled by Create()
|
// Filled by Create()
|
@ -1,11 +1,11 @@
|
|||||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||||
// source: github.com/containerd/containerd/runtime/linux/shim/v1/shim.proto
|
// source: github.com/containerd/containerd/runtime/shim/v1/shim.proto
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Package shim is a generated protocol buffer package.
|
Package shim is a generated protocol buffer package.
|
||||||
|
|
||||||
It is generated from these files:
|
It is generated from these files:
|
||||||
github.com/containerd/containerd/runtime/linux/shim/v1/shim.proto
|
github.com/containerd/containerd/runtime/shim/v1/shim.proto
|
||||||
|
|
||||||
It has these top-level messages:
|
It has these top-level messages:
|
||||||
CreateTaskRequest
|
CreateTaskRequest
|
||||||
@ -50,7 +50,7 @@ import strings "strings"
|
|||||||
import reflect "reflect"
|
import reflect "reflect"
|
||||||
|
|
||||||
import context "context"
|
import context "context"
|
||||||
import ttrpc "github.com/stevvooe/ttrpc"
|
import ttrpc "github.com/containerd/ttrpc"
|
||||||
|
|
||||||
import io "io"
|
import io "io"
|
||||||
|
|
||||||
@ -4352,80 +4352,80 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterFile("github.com/containerd/containerd/runtime/linux/shim/v1/shim.proto", fileDescriptorShim)
|
proto.RegisterFile("github.com/containerd/containerd/runtime/shim/v1/shim.proto", fileDescriptorShim)
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileDescriptorShim = []byte{
|
var fileDescriptorShim = []byte{
|
||||||
// 1135 bytes of a gzipped FileDescriptorProto
|
// 1135 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x4f, 0x4f, 0xdc, 0x46,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0x4d, 0x6f, 0xdb, 0x46,
|
||||||
0x14, 0xc7, 0x66, 0xff, 0xbe, 0xcd, 0x52, 0x98, 0x12, 0xea, 0x6c, 0xa4, 0x65, 0x65, 0xa9, 0x11,
|
0x13, 0x36, 0x69, 0x7d, 0x8e, 0x22, 0xbf, 0xf6, 0xbe, 0x8e, 0xcb, 0x28, 0x80, 0x2c, 0x10, 0x68,
|
||||||
0x55, 0x15, 0xbb, 0x2c, 0x55, 0xd2, 0x36, 0x52, 0x24, 0x20, 0x51, 0x85, 0xda, 0x28, 0xc8, 0x40,
|
0xe0, 0xa2, 0x08, 0x55, 0xcb, 0x6d, 0xd2, 0x36, 0x40, 0x00, 0xdb, 0x09, 0x0a, 0xa3, 0x0d, 0x6c,
|
||||||
0x13, 0xb5, 0xaa, 0x90, 0x59, 0x0f, 0xbb, 0x23, 0x76, 0x6d, 0xc7, 0x33, 0xa6, 0xd0, 0x53, 0x4f,
|
0xd0, 0x4e, 0x13, 0xb4, 0x28, 0x0c, 0x5a, 0x5c, 0x4b, 0x0b, 0x4b, 0x24, 0xc3, 0x5d, 0xba, 0x76,
|
||||||
0x3d, 0xf7, 0xe3, 0xf4, 0x23, 0x70, 0xc8, 0xa1, 0xc7, 0x9e, 0xd2, 0x86, 0x7b, 0xbf, 0x43, 0x35,
|
0x4f, 0x3d, 0xf5, 0xdc, 0x9f, 0xd3, 0x9f, 0xe0, 0x43, 0x0e, 0x3d, 0xf6, 0x94, 0x36, 0xba, 0xf7,
|
||||||
0x7f, 0x16, 0x7b, 0x77, 0x71, 0x6c, 0xb8, 0xb0, 0x7e, 0x33, 0xbf, 0x37, 0xf3, 0xe6, 0xfd, 0x7e,
|
0x3f, 0x14, 0xfb, 0x21, 0x93, 0x92, 0xcc, 0x90, 0xf2, 0xc5, 0xe2, 0xec, 0x3e, 0xb3, 0x3b, 0x3b,
|
||||||
0xf3, 0xde, 0x00, 0x9b, 0x7d, 0xc2, 0x06, 0xf1, 0x91, 0xd5, 0x0b, 0x46, 0x76, 0x2f, 0xf0, 0x99,
|
0xcf, 0xb3, 0x33, 0x6b, 0x78, 0xd2, 0x23, 0xac, 0x1f, 0x9d, 0x58, 0x5d, 0x7f, 0xd8, 0xee, 0xfa,
|
||||||
0x4b, 0x7c, 0x1c, 0x79, 0xe9, 0xcf, 0x28, 0xf6, 0x19, 0x19, 0x61, 0x7b, 0x48, 0xfc, 0xf8, 0xcc,
|
0x1e, 0x73, 0x88, 0x87, 0x43, 0x37, 0xf9, 0x19, 0x46, 0x1e, 0x23, 0x43, 0xdc, 0xa6, 0x7d, 0x32,
|
||||||
0xa6, 0x03, 0x32, 0xb2, 0x4f, 0xd7, 0xc5, 0xaf, 0x15, 0x46, 0x01, 0x0b, 0x50, 0x27, 0x01, 0x5b,
|
0x6c, 0x9f, 0x6f, 0x8a, 0x5f, 0x2b, 0x08, 0x7d, 0xe6, 0xa3, 0x56, 0x0c, 0xb3, 0x14, 0xcc, 0x1a,
|
||||||
0x0a, 0x6c, 0x09, 0xb0, 0x25, 0x40, 0xa7, 0xeb, 0xad, 0x7b, 0xfd, 0x20, 0xe8, 0x0f, 0xb1, 0x2d,
|
0x10, 0x2f, 0xba, 0xb0, 0x04, 0xe8, 0x7c, 0xb3, 0x71, 0xaf, 0xe7, 0xfb, 0xbd, 0x01, 0x6e, 0x0b,
|
||||||
0xf0, 0x47, 0xf1, 0xb1, 0xed, 0xfa, 0xe7, 0xd2, 0xb9, 0x75, 0x7f, 0x7a, 0x0a, 0x8f, 0x42, 0x36,
|
0xfc, 0x49, 0x74, 0xda, 0x76, 0xbc, 0x4b, 0xe9, 0xdc, 0xb8, 0x3f, 0x3d, 0x85, 0x87, 0x01, 0x1b,
|
||||||
0x9e, 0x5c, 0xee, 0x07, 0xfd, 0x40, 0x7c, 0xda, 0xfc, 0x4b, 0x8d, 0xae, 0x4e, 0xbb, 0xf0, 0x1d,
|
0x4f, 0xae, 0xf6, 0xfc, 0x9e, 0x2f, 0x3e, 0xdb, 0xfc, 0x4b, 0x8d, 0xae, 0x4f, 0xbb, 0xf0, 0x1d,
|
||||||
0x29, 0x73, 0x47, 0xa1, 0x02, 0x3c, 0xca, 0x3d, 0x93, 0x1b, 0x12, 0x9b, 0x9d, 0x87, 0x98, 0xda,
|
0x29, 0x73, 0x86, 0x81, 0x02, 0x3c, 0xca, 0x3c, 0x8d, 0x13, 0x90, 0x36, 0xbb, 0x0c, 0x30, 0x6d,
|
||||||
0xa3, 0x20, 0xf6, 0x99, 0xf2, 0xfb, 0xe6, 0x06, 0x7e, 0xcc, 0xa5, 0x27, 0xe2, 0x8f, 0xf4, 0x35,
|
0x0f, 0xfd, 0xc8, 0x63, 0xca, 0xef, 0xeb, 0x39, 0xfc, 0x98, 0x43, 0xcf, 0xc4, 0x1f, 0xe9, 0x6b,
|
||||||
0xff, 0xd3, 0x61, 0x69, 0x3b, 0xc2, 0x2e, 0xc3, 0xfb, 0x2e, 0x3d, 0x71, 0xf0, 0x9b, 0x18, 0x53,
|
0xfe, 0xab, 0xc3, 0xca, 0x6e, 0x88, 0x1d, 0x86, 0x8f, 0x1c, 0x7a, 0x66, 0xe3, 0x37, 0x11, 0xa6,
|
||||||
0x86, 0x56, 0x40, 0x27, 0x9e, 0xa1, 0x75, 0xb4, 0xb5, 0xfa, 0x56, 0xe5, 0xf2, 0xdd, 0xaa, 0xbe,
|
0x0c, 0xad, 0x81, 0x4e, 0x5c, 0x43, 0x6b, 0x69, 0x1b, 0xd5, 0x9d, 0xd2, 0xe8, 0xdd, 0xba, 0xbe,
|
||||||
0xf3, 0xcc, 0xd1, 0x89, 0x87, 0x56, 0xa0, 0x72, 0x14, 0xfb, 0xde, 0x10, 0x1b, 0x3a, 0x9f, 0x73,
|
0xf7, 0xcc, 0xd6, 0x89, 0x8b, 0xd6, 0xa0, 0x74, 0x12, 0x79, 0xee, 0x00, 0x1b, 0x3a, 0x9f, 0xb3,
|
||||||
0x94, 0x85, 0x0c, 0xa8, 0xaa, 0x0c, 0x1a, 0xf3, 0x62, 0x62, 0x6c, 0x22, 0x1b, 0x2a, 0x51, 0x10,
|
0x95, 0x85, 0x0c, 0x28, 0xab, 0x0c, 0x1a, 0x8b, 0x62, 0x62, 0x6c, 0xa2, 0x36, 0x94, 0x42, 0xdf,
|
||||||
0xb0, 0x63, 0x6a, 0x94, 0x3a, 0xf3, 0x6b, 0x8d, 0xee, 0x27, 0x56, 0x2a, 0xeb, 0x22, 0x24, 0xeb,
|
0x67, 0xa7, 0xd4, 0x28, 0xb4, 0x16, 0x37, 0x6a, 0x9d, 0x8f, 0xac, 0x44, 0xd6, 0x45, 0x48, 0xd6,
|
||||||
0x05, 0x3f, 0x8a, 0xa3, 0x60, 0xa8, 0x05, 0x35, 0x86, 0xa3, 0x11, 0xf1, 0xdd, 0xa1, 0x51, 0xee,
|
0x0b, 0x7e, 0x14, 0x5b, 0xc1, 0x50, 0x03, 0x2a, 0x0c, 0x87, 0x43, 0xe2, 0x39, 0x03, 0xa3, 0xd8,
|
||||||
0x68, 0x6b, 0x35, 0xe7, 0xca, 0x46, 0xcb, 0x50, 0xa6, 0xcc, 0x23, 0xbe, 0x51, 0x11, 0x9b, 0x48,
|
0xd2, 0x36, 0x2a, 0xf6, 0xb5, 0x8d, 0x56, 0xa1, 0x48, 0x99, 0x4b, 0x3c, 0xa3, 0x24, 0x36, 0x91,
|
||||||
0x83, 0x07, 0x45, 0x99, 0x17, 0xc4, 0xcc, 0xa8, 0xca, 0xa0, 0xa4, 0xa5, 0xc6, 0x71, 0x14, 0x19,
|
0x06, 0x0f, 0x8a, 0x32, 0xd7, 0x8f, 0x98, 0x51, 0x96, 0x41, 0x49, 0x4b, 0x8d, 0xe3, 0x30, 0x34,
|
||||||
0xb5, 0xab, 0x71, 0x1c, 0x45, 0xa8, 0x0d, 0xd0, 0x1b, 0xe0, 0xde, 0x49, 0x18, 0x10, 0x9f, 0x19,
|
0x2a, 0xd7, 0xe3, 0x38, 0x0c, 0x51, 0x13, 0xa0, 0xdb, 0xc7, 0xdd, 0xb3, 0xc0, 0x27, 0x1e, 0x33,
|
||||||
0x75, 0x31, 0x97, 0x1a, 0x41, 0x9f, 0xc3, 0x52, 0xe8, 0x46, 0xd8, 0x67, 0x87, 0x29, 0x18, 0x08,
|
0xaa, 0x62, 0x2e, 0x31, 0x82, 0x3e, 0x85, 0x95, 0xc0, 0x09, 0xb1, 0xc7, 0x8e, 0x13, 0x30, 0x10,
|
||||||
0xd8, 0xa2, 0x9c, 0xd8, 0x4e, 0xc0, 0x16, 0x54, 0x83, 0x90, 0x91, 0xc0, 0xa7, 0x46, 0xa3, 0xa3,
|
0xb0, 0x65, 0x39, 0xb1, 0x1b, 0x83, 0x2d, 0x28, 0xfb, 0x01, 0x23, 0xbe, 0x47, 0x8d, 0x5a, 0x4b,
|
||||||
0xad, 0x35, 0xba, 0xcb, 0x96, 0xa4, 0xd9, 0x1a, 0xd3, 0x6c, 0x6d, 0xfa, 0xe7, 0xce, 0x18, 0x64,
|
0xdb, 0xa8, 0x75, 0x56, 0x2d, 0x49, 0xb3, 0x35, 0xa6, 0xd9, 0xda, 0xf6, 0x2e, 0xed, 0x31, 0xc8,
|
||||||
0x3e, 0x00, 0x94, 0x4e, 0x37, 0x0d, 0x03, 0x9f, 0x62, 0xb4, 0x08, 0xf3, 0xa1, 0x4a, 0x78, 0xd3,
|
0x7c, 0x00, 0x28, 0x99, 0x6e, 0x1a, 0xf8, 0x1e, 0xc5, 0x68, 0x19, 0x16, 0x03, 0x95, 0xf0, 0xba,
|
||||||
0xe1, 0x9f, 0xe6, 0xef, 0x1a, 0x2c, 0x3c, 0xc3, 0x43, 0xcc, 0x70, 0x36, 0x08, 0xad, 0x42, 0x03,
|
0xcd, 0x3f, 0xcd, 0xdf, 0x34, 0x58, 0x7a, 0x86, 0x07, 0x98, 0xe1, 0x74, 0x10, 0x5a, 0x87, 0x1a,
|
||||||
0x9f, 0x11, 0x76, 0x48, 0x99, 0xcb, 0x62, 0x2a, 0x38, 0x69, 0x3a, 0xc0, 0x87, 0xf6, 0xc4, 0x08,
|
0xbe, 0x20, 0xec, 0x98, 0x32, 0x87, 0x45, 0x54, 0x70, 0x52, 0xb7, 0x81, 0x0f, 0x1d, 0x8a, 0x11,
|
||||||
0xda, 0x84, 0x3a, 0xb7, 0xb0, 0x77, 0xe8, 0x32, 0xc1, 0x4c, 0xa3, 0xdb, 0x9a, 0x89, 0x6f, 0x7f,
|
0xb4, 0x0d, 0x55, 0x6e, 0x61, 0xf7, 0xd8, 0x61, 0x82, 0x99, 0x5a, 0xa7, 0x31, 0x13, 0xdf, 0xd1,
|
||||||
0x2c, 0xc3, 0xad, 0xda, 0xc5, 0xbb, 0xd5, 0xb9, 0x3f, 0xfe, 0x59, 0xd5, 0x9c, 0x9a, 0x74, 0xdb,
|
0x58, 0x86, 0x3b, 0x95, 0xab, 0x77, 0xeb, 0x0b, 0xbf, 0xff, 0xbd, 0xae, 0xd9, 0x15, 0xe9, 0xb6,
|
||||||
0x64, 0xa6, 0x05, 0xcb, 0x32, 0x8e, 0xdd, 0x28, 0xe8, 0x61, 0x4a, 0x73, 0x24, 0x62, 0xfe, 0xa9,
|
0xcd, 0x4c, 0x0b, 0x56, 0x65, 0x1c, 0x07, 0xa1, 0xdf, 0xc5, 0x94, 0x66, 0x48, 0xc4, 0xfc, 0x43,
|
||||||
0x01, 0x7a, 0x7e, 0x86, 0x7b, 0xc5, 0xe0, 0x13, 0x74, 0xeb, 0x59, 0x74, 0xcf, 0x5f, 0x4f, 0x77,
|
0x03, 0xf4, 0xfc, 0x02, 0x77, 0xf3, 0xc1, 0x27, 0xe8, 0xd6, 0xd3, 0xe8, 0x5e, 0xbc, 0x99, 0xee,
|
||||||
0x29, 0x83, 0xee, 0xf2, 0x04, 0xdd, 0x6b, 0x50, 0xa2, 0x21, 0xee, 0x09, 0xcd, 0x64, 0xd1, 0x23,
|
0x42, 0x0a, 0xdd, 0xc5, 0x09, 0xba, 0x37, 0xa0, 0x40, 0x03, 0xdc, 0x15, 0x9a, 0x49, 0xa3, 0x47,
|
||||||
0x10, 0xe6, 0x5d, 0xf8, 0x78, 0x22, 0x72, 0x99, 0x77, 0xf3, 0x35, 0x2c, 0x3a, 0x98, 0x92, 0x5f,
|
0x20, 0xcc, 0xbb, 0xf0, 0xff, 0x89, 0xc8, 0x65, 0xde, 0xcd, 0xd7, 0xb0, 0x6c, 0x63, 0x4a, 0x7e,
|
||||||
0xf1, 0x2e, 0x3b, 0xcf, 0x3b, 0xce, 0x32, 0x94, 0x7f, 0x21, 0x1e, 0x1b, 0x28, 0x2e, 0xa4, 0xc1,
|
0xc1, 0x07, 0xec, 0x32, 0xeb, 0x38, 0xab, 0x50, 0xfc, 0x99, 0xb8, 0xac, 0xaf, 0xb8, 0x90, 0x06,
|
||||||
0x43, 0x1b, 0x60, 0xd2, 0x1f, 0x48, 0x0e, 0x9a, 0x8e, 0xb2, 0xcc, 0x07, 0x70, 0x87, 0x13, 0x85,
|
0x0f, 0xad, 0x8f, 0x49, 0xaf, 0x2f, 0x39, 0xa8, 0xdb, 0xca, 0x32, 0x1f, 0xc0, 0x1d, 0x4e, 0x14,
|
||||||
0xf3, 0x72, 0xfa, 0x56, 0x87, 0xa6, 0x02, 0x2a, 0x2d, 0xdc, 0xf4, 0x82, 0x2a, 0xed, 0xcc, 0x27,
|
0xce, 0xca, 0xe9, 0x5b, 0x1d, 0xea, 0x0a, 0xa8, 0xb4, 0x30, 0xef, 0x05, 0x55, 0xda, 0x59, 0x8c,
|
||||||
0xda, 0xd9, 0xe0, 0xe9, 0x12, 0xb2, 0xe1, 0x69, 0x5c, 0xe8, 0xde, 0x4f, 0x5f, 0xcc, 0xd3, 0x75,
|
0xb5, 0xb3, 0xc5, 0xd3, 0x25, 0x64, 0xc3, 0xd3, 0xb8, 0xd4, 0xb9, 0x9f, 0xbc, 0x98, 0xe7, 0x9b,
|
||||||
0x75, 0x37, 0xa5, 0x8e, 0x1c, 0x05, 0x4d, 0x18, 0x29, 0x5f, 0xcf, 0x48, 0x25, 0x83, 0x91, 0xea,
|
0xea, 0x6e, 0x4a, 0x1d, 0xd9, 0x0a, 0x1a, 0x33, 0x52, 0xbc, 0x99, 0x91, 0x52, 0x0a, 0x23, 0xe5,
|
||||||
0x04, 0x23, 0x69, 0xce, 0x6b, 0x53, 0x9c, 0x4f, 0x49, 0xba, 0xfe, 0x61, 0x49, 0xc3, 0xad, 0x24,
|
0x09, 0x46, 0x92, 0x9c, 0x57, 0xa6, 0x38, 0x9f, 0x92, 0x74, 0xf5, 0xc3, 0x92, 0x86, 0x5b, 0x49,
|
||||||
0xfd, 0x12, 0x1a, 0xdf, 0x91, 0xe1, 0xb0, 0x40, 0xb1, 0xa3, 0xa4, 0x3f, 0x16, 0x66, 0xd3, 0x51,
|
0x7a, 0x1f, 0x6a, 0xdf, 0x92, 0xc1, 0x20, 0x47, 0xb1, 0xa3, 0xa4, 0x37, 0x16, 0x66, 0xdd, 0x56,
|
||||||
0x16, 0xcf, 0xa5, 0x3b, 0x1c, 0x8a, 0x5c, 0xd6, 0x1c, 0xfe, 0x69, 0x3e, 0x85, 0x85, 0xed, 0x61,
|
0x16, 0xcf, 0xa5, 0x33, 0x18, 0x88, 0x5c, 0x56, 0x6c, 0xfe, 0x69, 0x3e, 0x85, 0xa5, 0xdd, 0x81,
|
||||||
0x40, 0xf1, 0xce, 0xcb, 0x02, 0xfa, 0x90, 0x09, 0x94, 0x5a, 0x97, 0x86, 0xf9, 0x19, 0x7c, 0xf4,
|
0x4f, 0xf1, 0xde, 0x7e, 0x0e, 0x7d, 0xc8, 0x04, 0x4a, 0xad, 0x4b, 0xc3, 0xfc, 0x04, 0xfe, 0xf7,
|
||||||
0x3d, 0xa1, 0x6c, 0x97, 0x78, 0xb9, 0xd7, 0xcb, 0x81, 0xc5, 0x04, 0xaa, 0xc4, 0xf0, 0x14, 0xea,
|
0x1d, 0xa1, 0xec, 0x80, 0xb8, 0x99, 0xd7, 0xcb, 0x86, 0xe5, 0x18, 0xaa, 0xc4, 0xf0, 0x14, 0xaa,
|
||||||
0xa1, 0xd4, 0x2c, 0xa6, 0x86, 0x26, 0xca, 0x6c, 0xe7, 0x5a, 0x36, 0x95, 0xb2, 0x77, 0xfc, 0xe3,
|
0x81, 0xd4, 0x2c, 0xa6, 0x86, 0x26, 0xca, 0x6c, 0xeb, 0x46, 0x36, 0x95, 0xb2, 0xf7, 0xbc, 0x53,
|
||||||
0xc0, 0x49, 0x5c, 0xcc, 0x9f, 0xe0, 0x6e, 0x52, 0xd1, 0xd2, 0x6d, 0x00, 0x41, 0x29, 0x74, 0xd9,
|
0xdf, 0x8e, 0x5d, 0xcc, 0x1f, 0xe1, 0x6e, 0x5c, 0xd1, 0x92, 0x6d, 0x00, 0x41, 0x21, 0x70, 0x58,
|
||||||
0x40, 0x86, 0xe1, 0x88, 0xef, 0x74, 0xc1, 0xd3, 0x8b, 0x14, 0xbc, 0x87, 0xb0, 0xb8, 0x37, 0x20,
|
0x5f, 0x86, 0x61, 0x8b, 0xef, 0x64, 0xc1, 0xd3, 0xf3, 0x14, 0xbc, 0x87, 0xb0, 0x7c, 0xd8, 0x27,
|
||||||
0x23, 0xb1, 0xe7, 0x38, 0xe0, 0x7b, 0x50, 0xe3, 0x2d, 0xf6, 0x30, 0x29, 0x67, 0x55, 0x6e, 0xef,
|
0x43, 0xb1, 0xe7, 0x38, 0xe0, 0x7b, 0x50, 0xe1, 0x2d, 0xf6, 0x38, 0x2e, 0x67, 0x65, 0x6e, 0x1f,
|
||||||
0x12, 0xcf, 0xfc, 0x16, 0x96, 0x0e, 0x42, 0x6f, 0xaa, 0x1d, 0x75, 0xa1, 0x1e, 0x61, 0x1a, 0xc4,
|
0x10, 0xd7, 0xfc, 0x06, 0x56, 0x5e, 0x06, 0xee, 0x54, 0x3b, 0xea, 0x40, 0x35, 0xc4, 0xd4, 0x8f,
|
||||||
0x51, 0x4f, 0x1c, 0x30, 0x7b, 0xd7, 0x04, 0xa6, 0xee, 0x56, 0xc4, 0xf2, 0x12, 0xfa, 0xb5, 0xb8,
|
0xc2, 0xae, 0x38, 0x60, 0xfa, 0xae, 0x31, 0x4c, 0xdd, 0xad, 0x90, 0x65, 0x25, 0xf4, 0x2b, 0x71,
|
||||||
0x5a, 0x1c, 0x97, 0x73, 0xb5, 0xd4, 0x15, 0xd2, 0x93, 0x1a, 0xfd, 0x29, 0x34, 0x5e, 0xb9, 0x24,
|
0xb5, 0x38, 0x2e, 0xe3, 0x6a, 0xa9, 0x2b, 0xa4, 0xc7, 0x35, 0xfa, 0x63, 0xa8, 0xbd, 0x72, 0x48,
|
||||||
0x77, 0x87, 0x08, 0xee, 0x48, 0x98, 0xda, 0x60, 0x4a, 0xe2, 0xda, 0x87, 0x25, 0xae, 0xdf, 0x46,
|
0xe6, 0x0e, 0x21, 0xdc, 0x91, 0x30, 0xb5, 0xc1, 0x94, 0xc4, 0xb5, 0x0f, 0x4b, 0x5c, 0xbf, 0x8d,
|
||||||
0xe2, 0xdd, 0xb7, 0x0d, 0x28, 0xf1, 0xb4, 0xa3, 0x01, 0x94, 0x45, 0xe5, 0x40, 0x96, 0x95, 0xf7,
|
0xc4, 0x3b, 0x6f, 0x6b, 0x50, 0xe0, 0x69, 0x47, 0x7d, 0x28, 0x8a, 0xca, 0x81, 0x2c, 0x2b, 0xeb,
|
||||||
0xdc, 0xb1, 0xd2, 0xb5, 0xa8, 0x65, 0x17, 0xc6, 0xab, 0x63, 0x51, 0xa8, 0xc8, 0xce, 0x86, 0x36,
|
0xb9, 0x63, 0x25, 0x6b, 0x51, 0xa3, 0x9d, 0x1b, 0xaf, 0x8e, 0x45, 0xa1, 0x24, 0x3b, 0x1b, 0xda,
|
||||||
0xf2, 0x5d, 0x67, 0x9e, 0x1c, 0xad, 0x2f, 0x6f, 0xe6, 0xa4, 0x36, 0x95, 0xc7, 0x8b, 0x58, 0xc1,
|
0xca, 0x76, 0x9d, 0x79, 0x72, 0x34, 0x3e, 0x9f, 0xcf, 0x49, 0x6d, 0x2a, 0x8f, 0x17, 0xb2, 0x9c,
|
||||||
0xe3, 0x5d, 0xc9, 0xa1, 0xe0, 0xf1, 0x52, 0xb2, 0x70, 0xa0, 0x22, 0xfb, 0x20, 0x5a, 0x99, 0xe1,
|
0xc7, 0xbb, 0x96, 0x43, 0xce, 0xe3, 0x25, 0x64, 0x61, 0x43, 0x49, 0xf6, 0x41, 0xb4, 0x36, 0xc3,
|
||||||
0xe2, 0x39, 0x7f, 0xfb, 0xb5, 0xbe, 0xc8, 0x5f, 0x72, 0xaa, 0xa3, 0x9f, 0x43, 0x73, 0xa2, 0xb7,
|
0xc5, 0x73, 0xfe, 0xf6, 0x6b, 0x7c, 0x96, 0xbd, 0xe4, 0x54, 0x47, 0xbf, 0x84, 0xfa, 0x44, 0x6f,
|
||||||
0xa2, 0x47, 0x45, 0x97, 0x98, 0xec, 0xae, 0xb7, 0xd8, 0xfa, 0x0d, 0xd4, 0xc6, 0x75, 0x04, 0xad,
|
0x45, 0x8f, 0xf2, 0x2e, 0x31, 0xd9, 0x5d, 0x6f, 0xb1, 0xf5, 0x1b, 0xa8, 0x8c, 0xeb, 0x08, 0xda,
|
||||||
0xe7, 0x7b, 0x4f, 0x95, 0xa7, 0x56, 0xf7, 0x26, 0x2e, 0x6a, 0xcb, 0xc7, 0x50, 0xde, 0x75, 0x63,
|
0xcc, 0xf6, 0x9e, 0x2a, 0x4f, 0x8d, 0xce, 0x3c, 0x2e, 0x6a, 0xcb, 0xc7, 0x50, 0x3c, 0x70, 0x22,
|
||||||
0x9a, 0x9d, 0xc0, 0x8c, 0x71, 0xf4, 0x15, 0x54, 0x1c, 0x4c, 0xe3, 0xd1, 0xcd, 0x3d, 0x7f, 0x06,
|
0x9a, 0x9e, 0xc0, 0x94, 0x71, 0xf4, 0x25, 0x94, 0x6c, 0x4c, 0xa3, 0xe1, 0xfc, 0x9e, 0x3f, 0x01,
|
||||||
0x48, 0xbd, 0xd5, 0x1e, 0x17, 0x90, 0xd8, 0x75, 0x75, 0x30, 0x73, 0xf9, 0x17, 0x50, 0xe2, 0x8d,
|
0x24, 0xde, 0x6a, 0x8f, 0x73, 0x48, 0xec, 0xa6, 0x3a, 0x98, 0xba, 0xfc, 0x0b, 0x28, 0xf0, 0x46,
|
||||||
0x04, 0x3d, 0xcc, 0x5f, 0x38, 0xd5, 0x70, 0x32, 0x97, 0xdb, 0x87, 0x12, 0x7f, 0x7f, 0xa0, 0x02,
|
0x82, 0x1e, 0x66, 0x2f, 0x9c, 0x68, 0x38, 0xa9, 0xcb, 0x1d, 0x41, 0x81, 0xbf, 0x3f, 0x50, 0x8e,
|
||||||
0x57, 0x61, 0xf6, 0x85, 0x95, 0xb9, 0xea, 0x2b, 0xa8, 0x5f, 0x3d, 0x5f, 0x50, 0x01, 0xde, 0xa6,
|
0xab, 0x30, 0xfb, 0xc2, 0x4a, 0x5d, 0xf5, 0x15, 0x54, 0xaf, 0x9f, 0x2f, 0x28, 0x07, 0x6f, 0xd3,
|
||||||
0xdf, 0x3a, 0x99, 0x0b, 0xef, 0x41, 0x55, 0x75, 0x3d, 0x54, 0x40, 0x7f, 0x93, 0x0d, 0x32, 0x73,
|
0x6f, 0x9d, 0xd4, 0x85, 0x0f, 0xa1, 0xac, 0xba, 0x1e, 0xca, 0xa1, 0xbf, 0xc9, 0x06, 0x99, 0xba,
|
||||||
0xd1, 0x1f, 0xa0, 0x36, 0x6e, 0x17, 0x99, 0x6c, 0x17, 0x38, 0xc4, 0x4c, 0xcb, 0x39, 0x80, 0x8a,
|
0xe8, 0xf7, 0x50, 0x19, 0xb7, 0x8b, 0x54, 0xb6, 0x73, 0x1c, 0x62, 0xa6, 0xe5, 0xbc, 0x84, 0x92,
|
||||||
0xec, 0x2b, 0x45, 0xaa, 0xd3, 0x4c, 0x07, 0xca, 0x0c, 0x17, 0x43, 0x89, 0xd7, 0xf6, 0x22, 0x0a,
|
0xec, 0x2b, 0x79, 0xaa, 0xd3, 0x4c, 0x07, 0x4a, 0x0d, 0x17, 0x43, 0x81, 0xd7, 0xf6, 0x3c, 0x0a,
|
||||||
0x48, 0xb5, 0x8a, 0x96, 0x55, 0x14, 0x2e, 0xa3, 0xdf, 0x3a, 0xb8, 0x78, 0xdf, 0x9e, 0xfb, 0xfb,
|
0x48, 0xb4, 0x8a, 0x86, 0x95, 0x17, 0x2e, 0xa3, 0xdf, 0xd9, 0xbf, 0x7a, 0xdf, 0x5c, 0xf8, 0xeb,
|
||||||
0x7d, 0x7b, 0xee, 0xb7, 0xcb, 0xb6, 0x76, 0x71, 0xd9, 0xd6, 0xfe, 0xba, 0x6c, 0x6b, 0xff, 0x5e,
|
0x7d, 0x73, 0xe1, 0xd7, 0x51, 0x53, 0xbb, 0x1a, 0x35, 0xb5, 0x3f, 0x47, 0x4d, 0xed, 0x9f, 0x51,
|
||||||
0xb6, 0xb5, 0x1f, 0x9f, 0xdc, 0xee, 0xff, 0xe0, 0x27, 0xfc, 0xf7, 0xb5, 0x7e, 0x54, 0x11, 0xe7,
|
0x53, 0xfb, 0xe1, 0x8b, 0x79, 0xff, 0x03, 0x7e, 0xc2, 0x7f, 0x5f, 0xeb, 0x27, 0x25, 0x71, 0x92,
|
||||||
0xd9, 0xf8, 0x3f, 0x00, 0x00, 0xff, 0xff, 0xfb, 0xc9, 0x30, 0x0d, 0x4f, 0x0f, 0x00, 0x00,
|
0xad, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x5b, 0x88, 0x3a, 0x56, 0x43, 0x0f, 0x00, 0x00,
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ import "google/protobuf/timestamp.proto";
|
|||||||
import "github.com/containerd/containerd/api/types/mount.proto";
|
import "github.com/containerd/containerd/api/types/mount.proto";
|
||||||
import "github.com/containerd/containerd/api/types/task/task.proto";
|
import "github.com/containerd/containerd/api/types/task/task.proto";
|
||||||
|
|
||||||
option go_package = "github.com/containerd/containerd/runtime/linux/shim/v1;shim";
|
option go_package = "github.com/containerd/containerd/runtime/shim/v1;shim";
|
||||||
|
|
||||||
// Shim service is launched for each container and is responsible for owning the IO
|
// Shim service is launched for each container and is responsible for owning the IO
|
||||||
// for the container and its additional processes. The shim is also the parent of
|
// for the container and its additional processes. The shim is also the parent of
|
37
vendor/github.com/containerd/containerd/vendor.conf
generated
vendored
37
vendor/github.com/containerd/containerd/vendor.conf
generated
vendored
@ -1,7 +1,7 @@
|
|||||||
github.com/containerd/go-runc f271fa2021de855d4d918dbef83c5fe19db1bdd5
|
github.com/containerd/go-runc f271fa2021de855d4d918dbef83c5fe19db1bdd5
|
||||||
github.com/containerd/console cb7008ab3d8359b78c5f464cb7cf160107ad5925
|
github.com/containerd/console 5d1b48d6114b8c9666f0c8b916f871af97b0a761
|
||||||
github.com/containerd/cgroups fe281dd265766145e943a034aa41086474ea6130
|
github.com/containerd/cgroups fe281dd265766145e943a034aa41086474ea6130
|
||||||
github.com/containerd/typeurl f6943554a7e7e88b3c14aad190bf05932da84788
|
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
||||||
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
|
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
|
||||||
github.com/containerd/btrfs 2e1aa0ddf94f91fa282b6ed87c23bf0d64911244
|
github.com/containerd/btrfs 2e1aa0ddf94f91fa282b6ed87c23bf0d64911244
|
||||||
github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b
|
github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b
|
||||||
@ -22,7 +22,6 @@ github.com/golang/protobuf v1.1.0
|
|||||||
github.com/opencontainers/runtime-spec v1.0.1
|
github.com/opencontainers/runtime-spec v1.0.1
|
||||||
github.com/opencontainers/runc 69663f0bd4b60df09991c08812a60108003fa340
|
github.com/opencontainers/runc 69663f0bd4b60df09991c08812a60108003fa340
|
||||||
github.com/sirupsen/logrus v1.0.0
|
github.com/sirupsen/logrus v1.0.0
|
||||||
github.com/pmezard/go-difflib v1.0.0
|
|
||||||
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
|
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
|
||||||
golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
|
golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
|
||||||
google.golang.org/grpc v1.12.0
|
google.golang.org/grpc v1.12.0
|
||||||
@ -38,14 +37,14 @@ github.com/Microsoft/hcsshim v0.6.11
|
|||||||
github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd
|
github.com/boltdb/bolt e9cf4fae01b5a8ff89d0ec6b32f0d9c9f79aefdd
|
||||||
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
||||||
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
||||||
github.com/stevvooe/ttrpc d4528379866b0ce7e9d71f3eb96f0582fc374577
|
github.com/containerd/ttrpc 94dde388801693c54f88a6596f713b51a8b30b2d
|
||||||
github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
|
github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16
|
||||||
github.com/gotestyourself/gotestyourself 44dbf532bbf5767611f6f2a61bded572e337010a
|
gotest.tools v2.1.0
|
||||||
github.com/google/go-cmp v0.1.0
|
github.com/google/go-cmp v0.1.0
|
||||||
|
|
||||||
# #2135: cri is temporarily forked because of circular dependency. will be fixed immediately in a follow-up PR.
|
# cri dependencies
|
||||||
github.com/containerd/cri 6e975823be192ad19f2ce7afcf6c57b88a991c30 https://github.com/AkihiroSuda/cri-containerd.git
|
github.com/containerd/cri v1.11.0
|
||||||
github.com/containerd/go-cni f2d7272f12d045b16ed924f50e91f9f9cecc55a7
|
github.com/containerd/go-cni 5882530828ecf62032409b298a3e8b19e08b6534
|
||||||
github.com/blang/semver v3.1.0
|
github.com/blang/semver v3.1.0
|
||||||
github.com/containernetworking/cni v0.6.0
|
github.com/containernetworking/cni v0.6.0
|
||||||
github.com/containernetworking/plugins v0.7.0
|
github.com/containernetworking/plugins v0.7.0
|
||||||
@ -59,22 +58,26 @@ github.com/golang/glog 44145f04b68cf362d9c4df2182967c2275eaefed
|
|||||||
github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c
|
github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c
|
||||||
github.com/hashicorp/errwrap 7554cd9344cec97297fa6649b055a8c98c2a1e55
|
github.com/hashicorp/errwrap 7554cd9344cec97297fa6649b055a8c98c2a1e55
|
||||||
github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f
|
github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f
|
||||||
github.com/json-iterator/go 1.0.4
|
github.com/json-iterator/go f2b4162afba35581b6d4a50d3b8f34e33c144682
|
||||||
github.com/opencontainers/runtime-tools 6073aff4ac61897f75895123f7e24135204a404d
|
github.com/modern-go/reflect2 05fbef0ca5da472bbf96c9322b84a53edc03c9fd
|
||||||
|
github.com/modern-go/concurrent 1.0.3
|
||||||
|
github.com/opencontainers/runtime-tools v0.6.0
|
||||||
github.com/opencontainers/selinux 4a2974bf1ee960774ffd517717f1f45325af0206
|
github.com/opencontainers/selinux 4a2974bf1ee960774ffd517717f1f45325af0206
|
||||||
github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
|
github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
|
||||||
github.com/spf13/pflag v1.0.0
|
|
||||||
github.com/tchap/go-patricia 5ad6cdb7538b0097d5598c7e57f0a24072adf7dc
|
github.com/tchap/go-patricia 5ad6cdb7538b0097d5598c7e57f0a24072adf7dc
|
||||||
|
github.com/xeipuuv/gojsonpointer 4e3ac2762d5f479393488629ee9370b50873b3a6
|
||||||
|
github.com/xeipuuv/gojsonreference bd5ef7bd5415a7ac448318e64f11a24cd21e594b
|
||||||
|
github.com/xeipuuv/gojsonschema 1d523034197ff1f222f6429836dd36a2457a1874
|
||||||
golang.org/x/crypto 49796115aa4b964c318aad4f3084fdb41e9aa067
|
golang.org/x/crypto 49796115aa4b964c318aad4f3084fdb41e9aa067
|
||||||
golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631
|
golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631
|
||||||
gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
|
gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
|
||||||
gopkg.in/yaml.v2 53feefa2559fb8dfa8d81baad31be332c97d6c77
|
gopkg.in/yaml.v2 53feefa2559fb8dfa8d81baad31be332c97d6c77
|
||||||
k8s.io/api 7e796de92438aede7cb5d6bcf6c10f4fa65db560
|
k8s.io/api 9e5ffd1f1320950b238cfce291b926411f0af722
|
||||||
k8s.io/apimachinery fcb9a12f7875d01f8390b28faedc37dcf2e713b9
|
k8s.io/apimachinery ed135c5b96450fd24e5e981c708114fbbd950697
|
||||||
k8s.io/apiserver 4a8377c547bbff4576a35b5b5bf4026d9b5aa763
|
k8s.io/apiserver a90e3a95c2e91b944bfca8225c4e0d12e42a9eb5
|
||||||
k8s.io/client-go b9a0cf870f239c4a4ecfd3feb075a50e7cbe1473
|
k8s.io/client-go 03bfb9bdcfe5482795b999f39ca3ed9ad42ce5bb
|
||||||
k8s.io/kubernetes v1.10.0
|
k8s.io/kubernetes v1.11.0
|
||||||
k8s.io/utils 258e2a2fa64568210fbd6267cf1d8fd87c3cb86e
|
k8s.io/utils 733eca437aa39379e4bcc25e726439dfca40fcff
|
||||||
|
|
||||||
# zfs dependencies
|
# zfs dependencies
|
||||||
github.com/containerd/zfs 9a0b8b8b5982014b729cd34eb7cd7a11062aa6ec
|
github.com/containerd/zfs 9a0b8b8b5982014b729cd34eb7cd7a11062aa6ec
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# ttrpc
|
# ttrpc
|
||||||
|
|
||||||
[](https://travis-ci.org/stevvooe/ttrpc)
|
[](https://travis-ci.org/containerd/ttrpc)
|
||||||
|
|
||||||
GRPC for low-memory environments.
|
GRPC for low-memory environments.
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ Create a gogo vanity binary (see
|
|||||||
[`cmd/protoc-gen-gogottrpc/main.go`](cmd/protoc-gen-gogottrpc/main.go) for an
|
[`cmd/protoc-gen-gogottrpc/main.go`](cmd/protoc-gen-gogottrpc/main.go) for an
|
||||||
example with the ttrpc plugin enabled.
|
example with the ttrpc plugin enabled.
|
||||||
|
|
||||||
It's recommended to use [`protobuild`](https://github.com/stevvooe/protobuild)
|
It's recommended to use [`protobuild`](https://github.com//stevvooe/protobuild)
|
||||||
to build the protobufs for this project, but this will work with protoc
|
to build the protobufs for this project, but this will work with protoc
|
||||||
directly, if required.
|
directly, if required.
|
||||||
|
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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 ttrpc
|
package ttrpc
|
||||||
|
|
||||||
import (
|
import (
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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 ttrpc
|
package ttrpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -9,9 +25,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -180,7 +196,7 @@ func (c *Client) run() {
|
|||||||
case msg := <-incoming:
|
case msg := <-incoming:
|
||||||
call, ok := waiters[msg.StreamID]
|
call, ok := waiters[msg.StreamID]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.L.Errorf("ttrpc: received message for unknown channel %v", msg.StreamID)
|
logrus.Errorf("ttrpc: received message for unknown channel %v", msg.StreamID)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
42
vendor/github.com/containerd/ttrpc/codec.go
generated
vendored
Normal file
42
vendor/github.com/containerd/ttrpc/codec.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
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 ttrpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type codec struct{}
|
||||||
|
|
||||||
|
func (c codec) Marshal(msg interface{}) ([]byte, error) {
|
||||||
|
switch v := msg.(type) {
|
||||||
|
case proto.Message:
|
||||||
|
return proto.Marshal(v)
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("ttrpc: cannot marshal unknown type: %T", msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c codec) Unmarshal(p []byte, msg interface{}) error {
|
||||||
|
switch v := msg.(type) {
|
||||||
|
case proto.Message:
|
||||||
|
return proto.Unmarshal(p, v)
|
||||||
|
default:
|
||||||
|
return errors.Errorf("ttrpc: cannot unmarshal into unknown type: %T", msg)
|
||||||
|
}
|
||||||
|
}
|
39
vendor/github.com/containerd/ttrpc/config.go
generated
vendored
Normal file
39
vendor/github.com/containerd/ttrpc/config.go
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
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 ttrpc
|
||||||
|
|
||||||
|
import "github.com/pkg/errors"
|
||||||
|
|
||||||
|
type serverConfig struct {
|
||||||
|
handshaker Handshaker
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerOpt func(*serverConfig) error
|
||||||
|
|
||||||
|
// WithServerHandshaker can be passed to NewServer to ensure that the
|
||||||
|
// handshaker is called before every connection attempt.
|
||||||
|
//
|
||||||
|
// Only one handshaker is allowed per server.
|
||||||
|
func WithServerHandshaker(handshaker Handshaker) ServerOpt {
|
||||||
|
return func(c *serverConfig) error {
|
||||||
|
if c.handshaker != nil {
|
||||||
|
return errors.New("only one handshaker allowed per server")
|
||||||
|
}
|
||||||
|
c.handshaker = handshaker
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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 ttrpc
|
package ttrpc
|
||||||
|
|
||||||
import (
|
import (
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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 ttrpc
|
package ttrpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -9,8 +25,8 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
@ -51,12 +67,11 @@ func (s *Server) Register(name string, methods map[string]Method) {
|
|||||||
s.services.register(name, methods)
|
s.services.register(name, methods)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Serve(l net.Listener) error {
|
func (s *Server) Serve(ctx context.Context, l net.Listener) error {
|
||||||
s.addListener(l)
|
s.addListener(l)
|
||||||
defer s.closeListener(l)
|
defer s.closeListener(l)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ctx = context.Background()
|
|
||||||
backoff time.Duration
|
backoff time.Duration
|
||||||
handshaker = s.config.handshaker
|
handshaker = s.config.handshaker
|
||||||
)
|
)
|
||||||
@ -88,7 +103,7 @@ func (s *Server) Serve(l net.Listener) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sleep := time.Duration(rand.Int63n(int64(backoff)))
|
sleep := time.Duration(rand.Int63n(int64(backoff)))
|
||||||
log.L.WithError(err).Errorf("ttrpc: failed accept; backoff %v", sleep)
|
logrus.WithError(err).Errorf("ttrpc: failed accept; backoff %v", sleep)
|
||||||
time.Sleep(sleep)
|
time.Sleep(sleep)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -100,7 +115,7 @@ func (s *Server) Serve(l net.Listener) error {
|
|||||||
|
|
||||||
approved, handshake, err := handshaker.Handshake(ctx, conn)
|
approved, handshake, err := handshaker.Handshake(ctx, conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.L.WithError(err).Errorf("ttrpc: refusing connection after handshake")
|
logrus.WithError(err).Errorf("ttrpc: refusing connection after handshake")
|
||||||
conn.Close()
|
conn.Close()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -416,12 +431,12 @@ func (c *serverConn) run(sctx context.Context) {
|
|||||||
case response := <-responses:
|
case response := <-responses:
|
||||||
p, err := c.server.codec.Marshal(response.resp)
|
p, err := c.server.codec.Marshal(response.resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.L.WithError(err).Error("failed marshaling response")
|
logrus.WithError(err).Error("failed marshaling response")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ch.send(ctx, response.id, messageTypeResponse, p); err != nil {
|
if err := ch.send(ctx, response.id, messageTypeResponse, p); err != nil {
|
||||||
log.L.WithError(err).Error("failed sending message on channel")
|
logrus.WithError(err).Error("failed sending message on channel")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,7 +447,7 @@ func (c *serverConn) run(sctx context.Context) {
|
|||||||
// requests due to a terminal error.
|
// requests due to a terminal error.
|
||||||
recvErr = nil // connection is now "closing"
|
recvErr = nil // connection is now "closing"
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
log.L.WithError(err).Error("error receiving message")
|
logrus.WithError(err).Error("error receiving message")
|
||||||
}
|
}
|
||||||
case <-shutdown:
|
case <-shutdown:
|
||||||
return
|
return
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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 ttrpc
|
package ttrpc
|
||||||
|
|
||||||
import (
|
import (
|
16
vendor/github.com/stevvooe/ttrpc/types.go → vendor/github.com/containerd/ttrpc/types.go
generated
vendored
16
vendor/github.com/stevvooe/ttrpc/types.go → vendor/github.com/containerd/ttrpc/types.go
generated
vendored
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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 ttrpc
|
package ttrpc
|
||||||
|
|
||||||
import (
|
import (
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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 ttrpc
|
package ttrpc
|
||||||
|
|
||||||
import (
|
import (
|
16
vendor/github.com/containerd/typeurl/types.go
generated
vendored
16
vendor/github.com/containerd/typeurl/types.go
generated
vendored
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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 typeurl
|
package typeurl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
4
vendor/github.com/docker/docker/contrib/README.md
generated
vendored
4
vendor/github.com/docker/docker/contrib/README.md
generated
vendored
@ -1,4 +0,0 @@
|
|||||||
The `contrib` directory contains scripts, images, and other helpful things
|
|
||||||
which are not part of the core docker distribution. Please note that they
|
|
||||||
could be out of date, since they do not receive the same attention as the
|
|
||||||
rest of the repository.
|
|
10
vendor/github.com/docker/docker/contrib/nnp-test/nnp-test.c
generated
vendored
10
vendor/github.com/docker/docker/contrib/nnp-test/nnp-test.c
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
printf("EUID=%d\n", geteuid());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
16
vendor/github.com/docker/docker/contrib/syscall-test/acct.c
generated
vendored
16
vendor/github.com/docker/docker/contrib/syscall-test/acct.c
generated
vendored
@ -1,16 +0,0 @@
|
|||||||
#define _GNU_SOURCE
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int err = acct("/tmp/t");
|
|
||||||
if (err == -1) {
|
|
||||||
fprintf(stderr, "acct failed: %s\n", strerror(errno));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
7
vendor/github.com/docker/docker/contrib/syscall-test/exit32.s
generated
vendored
7
vendor/github.com/docker/docker/contrib/syscall-test/exit32.s
generated
vendored
@ -1,7 +0,0 @@
|
|||||||
.globl _start
|
|
||||||
.text
|
|
||||||
_start:
|
|
||||||
xorl %eax, %eax
|
|
||||||
incl %eax
|
|
||||||
movb $0, %bl
|
|
||||||
int $0x80
|
|
63
vendor/github.com/docker/docker/contrib/syscall-test/ns.c
generated
vendored
63
vendor/github.com/docker/docker/contrib/syscall-test/ns.c
generated
vendored
@ -1,63 +0,0 @@
|
|||||||
#define _GNU_SOURCE
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sched.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#define STACK_SIZE (1024 * 1024) /* Stack size for cloned child */
|
|
||||||
|
|
||||||
struct clone_args {
|
|
||||||
char **argv;
|
|
||||||
};
|
|
||||||
|
|
||||||
// child_exec is the func that will be executed as the result of clone
|
|
||||||
static int child_exec(void *stuff)
|
|
||||||
{
|
|
||||||
struct clone_args *args = (struct clone_args *)stuff;
|
|
||||||
if (execvp(args->argv[0], args->argv) != 0) {
|
|
||||||
fprintf(stderr, "failed to execvp arguments %s\n",
|
|
||||||
strerror(errno));
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
// we should never reach here!
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
struct clone_args args;
|
|
||||||
args.argv = &argv[1];
|
|
||||||
|
|
||||||
int clone_flags = CLONE_NEWNS | CLONE_NEWPID | SIGCHLD;
|
|
||||||
|
|
||||||
// allocate stack for child
|
|
||||||
char *stack; /* Start of stack buffer */
|
|
||||||
char *child_stack; /* End of stack buffer */
|
|
||||||
stack =
|
|
||||||
mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
|
|
||||||
MAP_SHARED | MAP_ANON | MAP_STACK, -1, 0);
|
|
||||||
if (stack == MAP_FAILED) {
|
|
||||||
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
child_stack = stack + STACK_SIZE; /* Assume stack grows downward */
|
|
||||||
|
|
||||||
// the result of this call is that our child_exec will be run in another
|
|
||||||
// process returning its pid
|
|
||||||
pid_t pid = clone(child_exec, child_stack, clone_flags, &args);
|
|
||||||
if (pid < 0) {
|
|
||||||
fprintf(stderr, "clone failed: %s\n", strerror(errno));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
// lets wait on our child process here before we, the parent, exits
|
|
||||||
if (waitpid(pid, NULL, 0) == -1) {
|
|
||||||
fprintf(stderr, "failed to wait pid %d\n", pid);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
14
vendor/github.com/docker/docker/contrib/syscall-test/raw.c
generated
vendored
14
vendor/github.com/docker/docker/contrib/syscall-test/raw.c
generated
vendored
@ -1,14 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/ip.h>
|
|
||||||
#include <netinet/udp.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
if (socket(PF_INET, SOCK_RAW, IPPROTO_UDP) == -1) {
|
|
||||||
perror("socket");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
11
vendor/github.com/docker/docker/contrib/syscall-test/setgid.c
generated
vendored
11
vendor/github.com/docker/docker/contrib/syscall-test/setgid.c
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
if (setgid(1) == -1) {
|
|
||||||
perror("setgid");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
11
vendor/github.com/docker/docker/contrib/syscall-test/setuid.c
generated
vendored
11
vendor/github.com/docker/docker/contrib/syscall-test/setuid.c
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
if (setuid(1) == -1) {
|
|
||||||
perror("setuid");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
30
vendor/github.com/docker/docker/contrib/syscall-test/socket.c
generated
vendored
30
vendor/github.com/docker/docker/contrib/syscall-test/socket.c
generated
vendored
@ -1,30 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
int s;
|
|
||||||
struct sockaddr_in sin;
|
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
if (s == -1) {
|
|
||||||
perror("socket");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sin.sin_family = AF_INET;
|
|
||||||
sin.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
sin.sin_port = htons(80);
|
|
||||||
|
|
||||||
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
|
|
||||||
perror("bind");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(s);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
63
vendor/github.com/docker/docker/contrib/syscall-test/userns.c
generated
vendored
63
vendor/github.com/docker/docker/contrib/syscall-test/userns.c
generated
vendored
@ -1,63 +0,0 @@
|
|||||||
#define _GNU_SOURCE
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sched.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#define STACK_SIZE (1024 * 1024) /* Stack size for cloned child */
|
|
||||||
|
|
||||||
struct clone_args {
|
|
||||||
char **argv;
|
|
||||||
};
|
|
||||||
|
|
||||||
// child_exec is the func that will be executed as the result of clone
|
|
||||||
static int child_exec(void *stuff)
|
|
||||||
{
|
|
||||||
struct clone_args *args = (struct clone_args *)stuff;
|
|
||||||
if (execvp(args->argv[0], args->argv) != 0) {
|
|
||||||
fprintf(stderr, "failed to execvp arguments %s\n",
|
|
||||||
strerror(errno));
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
// we should never reach here!
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
struct clone_args args;
|
|
||||||
args.argv = &argv[1];
|
|
||||||
|
|
||||||
int clone_flags = CLONE_NEWUSER | SIGCHLD;
|
|
||||||
|
|
||||||
// allocate stack for child
|
|
||||||
char *stack; /* Start of stack buffer */
|
|
||||||
char *child_stack; /* End of stack buffer */
|
|
||||||
stack =
|
|
||||||
mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
|
|
||||||
MAP_SHARED | MAP_ANON | MAP_STACK, -1, 0);
|
|
||||||
if (stack == MAP_FAILED) {
|
|
||||||
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
child_stack = stack + STACK_SIZE; /* Assume stack grows downward */
|
|
||||||
|
|
||||||
// the result of this call is that our child_exec will be run in another
|
|
||||||
// process returning its pid
|
|
||||||
pid_t pid = clone(child_exec, child_stack, clone_flags, &args);
|
|
||||||
if (pid < 0) {
|
|
||||||
fprintf(stderr, "clone failed: %s\n", strerror(errno));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
// lets wait on our child process here before we, the parent, exits
|
|
||||||
if (waitpid(pid, NULL, 0) == -1) {
|
|
||||||
fprintf(stderr, "failed to wait pid %d\n", pid);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
26
vendor/github.com/stevvooe/ttrpc/codec.go
generated
vendored
26
vendor/github.com/stevvooe/ttrpc/codec.go
generated
vendored
@ -1,26 +0,0 @@
|
|||||||
package ttrpc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gogo/protobuf/proto"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
type codec struct{}
|
|
||||||
|
|
||||||
func (c codec) Marshal(msg interface{}) ([]byte, error) {
|
|
||||||
switch v := msg.(type) {
|
|
||||||
case proto.Message:
|
|
||||||
return proto.Marshal(v)
|
|
||||||
default:
|
|
||||||
return nil, errors.Errorf("ttrpc: cannot marshal unknown type: %T", msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c codec) Unmarshal(p []byte, msg interface{}) error {
|
|
||||||
switch v := msg.(type) {
|
|
||||||
case proto.Message:
|
|
||||||
return proto.Unmarshal(p, v)
|
|
||||||
default:
|
|
||||||
return errors.Errorf("ttrpc: cannot unmarshal into unknown type: %T", msg)
|
|
||||||
}
|
|
||||||
}
|
|
23
vendor/github.com/stevvooe/ttrpc/config.go
generated
vendored
23
vendor/github.com/stevvooe/ttrpc/config.go
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
package ttrpc
|
|
||||||
|
|
||||||
import "github.com/pkg/errors"
|
|
||||||
|
|
||||||
type serverConfig struct {
|
|
||||||
handshaker Handshaker
|
|
||||||
}
|
|
||||||
|
|
||||||
type ServerOpt func(*serverConfig) error
|
|
||||||
|
|
||||||
// WithServerHandshaker can be passed to NewServer to ensure that the
|
|
||||||
// handshaker is called before every connection attempt.
|
|
||||||
//
|
|
||||||
// Only one handshaker is allowed per server.
|
|
||||||
func WithServerHandshaker(handshaker Handshaker) ServerOpt {
|
|
||||||
return func(c *serverConfig) error {
|
|
||||||
if c.handshaker != nil {
|
|
||||||
return errors.New("only one handshaker allowed per server")
|
|
||||||
}
|
|
||||||
c.handshaker = handshaker
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
197
vendor/golang.org/x/crypto/otr/libotr_test_helper.c
generated
vendored
197
vendor/golang.org/x/crypto/otr/libotr_test_helper.c
generated
vendored
@ -1,197 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// This code can be compiled and used to test the otr package against libotr.
|
|
||||||
// See otr_test.go.
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <proto.h>
|
|
||||||
#include <message.h>
|
|
||||||
#include <privkey.h>
|
|
||||||
|
|
||||||
static int g_session_established = 0;
|
|
||||||
|
|
||||||
OtrlPolicy policy(void *opdata, ConnContext *context) {
|
|
||||||
return OTRL_POLICY_ALWAYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int is_logged_in(void *opdata, const char *accountname, const char *protocol,
|
|
||||||
const char *recipient) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void inject_message(void *opdata, const char *accountname, const char *protocol,
|
|
||||||
const char *recipient, const char *message) {
|
|
||||||
printf("%s\n", message);
|
|
||||||
fflush(stdout);
|
|
||||||
fprintf(stderr, "libotr helper sent: %s\n", message);
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_context_list(void *opdata) {}
|
|
||||||
|
|
||||||
void new_fingerprint(void *opdata, OtrlUserState us, const char *accountname,
|
|
||||||
const char *protocol, const char *username,
|
|
||||||
unsigned char fingerprint[20]) {
|
|
||||||
fprintf(stderr, "NEW FINGERPRINT\n");
|
|
||||||
g_session_established = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_fingerprints(void *opdata) {}
|
|
||||||
|
|
||||||
void gone_secure(void *opdata, ConnContext *context) {}
|
|
||||||
|
|
||||||
void gone_insecure(void *opdata, ConnContext *context) {}
|
|
||||||
|
|
||||||
void still_secure(void *opdata, ConnContext *context, int is_reply) {}
|
|
||||||
|
|
||||||
int max_message_size(void *opdata, ConnContext *context) { return 99999; }
|
|
||||||
|
|
||||||
const char *account_name(void *opdata, const char *account,
|
|
||||||
const char *protocol) {
|
|
||||||
return "ACCOUNT";
|
|
||||||
}
|
|
||||||
|
|
||||||
void account_name_free(void *opdata, const char *account_name) {}
|
|
||||||
|
|
||||||
const char *error_message(void *opdata, ConnContext *context,
|
|
||||||
OtrlErrorCode err_code) {
|
|
||||||
return "ERR";
|
|
||||||
}
|
|
||||||
|
|
||||||
void error_message_free(void *opdata, const char *msg) {}
|
|
||||||
|
|
||||||
void resent_msg_prefix_free(void *opdata, const char *prefix) {}
|
|
||||||
|
|
||||||
void handle_smp_event(void *opdata, OtrlSMPEvent smp_event,
|
|
||||||
ConnContext *context, unsigned short progress_event,
|
|
||||||
char *question) {}
|
|
||||||
|
|
||||||
void handle_msg_event(void *opdata, OtrlMessageEvent msg_event,
|
|
||||||
ConnContext *context, const char *message,
|
|
||||||
gcry_error_t err) {
|
|
||||||
fprintf(stderr, "msg event: %d %s\n", msg_event, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
OtrlMessageAppOps uiops = {
|
|
||||||
policy,
|
|
||||||
NULL,
|
|
||||||
is_logged_in,
|
|
||||||
inject_message,
|
|
||||||
update_context_list,
|
|
||||||
new_fingerprint,
|
|
||||||
write_fingerprints,
|
|
||||||
gone_secure,
|
|
||||||
gone_insecure,
|
|
||||||
still_secure,
|
|
||||||
max_message_size,
|
|
||||||
account_name,
|
|
||||||
account_name_free,
|
|
||||||
NULL, /* received_symkey */
|
|
||||||
error_message,
|
|
||||||
error_message_free,
|
|
||||||
NULL, /* resent_msg_prefix */
|
|
||||||
resent_msg_prefix_free,
|
|
||||||
handle_smp_event,
|
|
||||||
handle_msg_event,
|
|
||||||
NULL /* create_instag */,
|
|
||||||
NULL /* convert_msg */,
|
|
||||||
NULL /* convert_free */,
|
|
||||||
NULL /* timer_control */,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char kPrivateKeyData[] =
|
|
||||||
"(privkeys (account (name \"account\") (protocol proto) (private-key (dsa "
|
|
||||||
"(p "
|
|
||||||
"#00FC07ABCF0DC916AFF6E9AE47BEF60C7AB9B4D6B2469E436630E36F8A489BE812486A09F"
|
|
||||||
"30B71224508654940A835301ACC525A4FF133FC152CC53DCC59D65C30A54F1993FE13FE63E"
|
|
||||||
"5823D4C746DB21B90F9B9C00B49EC7404AB1D929BA7FBA12F2E45C6E0A651689750E8528AB"
|
|
||||||
"8C031D3561FECEE72EBB4A090D450A9B7A857#) (q "
|
|
||||||
"#00997BD266EF7B1F60A5C23F3A741F2AEFD07A2081#) (g "
|
|
||||||
"#535E360E8A95EBA46A4F7DE50AD6E9B2A6DB785A66B64EB9F20338D2A3E8FB0E94725848F"
|
|
||||||
"1AA6CC567CB83A1CC517EC806F2E92EAE71457E80B2210A189B91250779434B41FC8A8873F"
|
|
||||||
"6DB94BEA7D177F5D59E7E114EE10A49CFD9CEF88AE43387023B672927BA74B04EB6BBB5E57"
|
|
||||||
"597766A2F9CE3857D7ACE3E1E3BC1FC6F26#) (y "
|
|
||||||
"#0AC8670AD767D7A8D9D14CC1AC6744CD7D76F993B77FFD9E39DF01E5A6536EF65E775FCEF"
|
|
||||||
"2A983E2A19BD6415500F6979715D9FD1257E1FE2B6F5E1E74B333079E7C880D39868462A93"
|
|
||||||
"454B41877BE62E5EF0A041C2EE9C9E76BD1E12AE25D9628DECB097025DD625EF49C3258A1A"
|
|
||||||
"3C0FF501E3DC673B76D7BABF349009B6ECF#) (x "
|
|
||||||
"#14D0345A3562C480A039E3C72764F72D79043216#)))))\n";
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
OTRL_INIT;
|
|
||||||
|
|
||||||
// We have to write the private key information to a file because the libotr
|
|
||||||
// API demands a filename to read from.
|
|
||||||
const char *tmpdir = "/tmp";
|
|
||||||
if (getenv("TMP")) {
|
|
||||||
tmpdir = getenv("TMP");
|
|
||||||
}
|
|
||||||
|
|
||||||
char private_key_file[256];
|
|
||||||
snprintf(private_key_file, sizeof(private_key_file),
|
|
||||||
"%s/libotr_test_helper_privatekeys-XXXXXX", tmpdir);
|
|
||||||
int fd = mkstemp(private_key_file);
|
|
||||||
if (fd == -1) {
|
|
||||||
perror("creating temp file");
|
|
||||||
}
|
|
||||||
write(fd, kPrivateKeyData, sizeof(kPrivateKeyData) - 1);
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
OtrlUserState userstate = otrl_userstate_create();
|
|
||||||
otrl_privkey_read(userstate, private_key_file);
|
|
||||||
unlink(private_key_file);
|
|
||||||
|
|
||||||
fprintf(stderr, "libotr helper started\n");
|
|
||||||
|
|
||||||
char buf[4096];
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
char *message = fgets(buf, sizeof(buf), stdin);
|
|
||||||
if (strlen(message) == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
message[strlen(message) - 1] = 0;
|
|
||||||
fprintf(stderr, "libotr helper got: %s\n", message);
|
|
||||||
|
|
||||||
char *newmessage = NULL;
|
|
||||||
OtrlTLV *tlvs;
|
|
||||||
int ignore_message = otrl_message_receiving(
|
|
||||||
userstate, &uiops, NULL, "account", "proto", "peer", message,
|
|
||||||
&newmessage, &tlvs, NULL, NULL, NULL);
|
|
||||||
if (tlvs) {
|
|
||||||
otrl_tlv_free(tlvs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newmessage != NULL) {
|
|
||||||
fprintf(stderr, "libotr got: %s\n", newmessage);
|
|
||||||
otrl_message_free(newmessage);
|
|
||||||
|
|
||||||
gcry_error_t err;
|
|
||||||
char *newmessage = NULL;
|
|
||||||
|
|
||||||
err = otrl_message_sending(userstate, &uiops, NULL, "account", "proto",
|
|
||||||
"peer", 0, "test message", NULL, &newmessage,
|
|
||||||
OTRL_FRAGMENT_SEND_SKIP, NULL, NULL, NULL);
|
|
||||||
if (newmessage == NULL) {
|
|
||||||
fprintf(stderr, "libotr didn't encrypt message\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
write(1, newmessage, strlen(newmessage));
|
|
||||||
write(1, "\n", 1);
|
|
||||||
fprintf(stderr, "libotr sent: %s\n", newmessage);
|
|
||||||
otrl_message_free(newmessage);
|
|
||||||
|
|
||||||
g_session_established = 0;
|
|
||||||
write(1, "?OTRv2?\n", 8);
|
|
||||||
fprintf(stderr, "libotr sent: ?OTRv2\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
1415
vendor/golang.org/x/crypto/otr/otr.go
generated
vendored
1415
vendor/golang.org/x/crypto/otr/otr.go
generated
vendored
File diff suppressed because it is too large
Load Diff
572
vendor/golang.org/x/crypto/otr/smp.go
generated
vendored
572
vendor/golang.org/x/crypto/otr/smp.go
generated
vendored
@ -1,572 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// This file implements the Socialist Millionaires Protocol as described in
|
|
||||||
// http://www.cypherpunks.ca/otr/Protocol-v2-3.1.0.html. The protocol
|
|
||||||
// specification is required in order to understand this code and, where
|
|
||||||
// possible, the variable names in the code match up with the spec.
|
|
||||||
|
|
||||||
package otr
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/sha256"
|
|
||||||
"errors"
|
|
||||||
"hash"
|
|
||||||
"math/big"
|
|
||||||
)
|
|
||||||
|
|
||||||
type smpFailure string
|
|
||||||
|
|
||||||
func (s smpFailure) Error() string {
|
|
||||||
return string(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
var smpFailureError = smpFailure("otr: SMP protocol failed")
|
|
||||||
var smpSecretMissingError = smpFailure("otr: mutual secret needed")
|
|
||||||
|
|
||||||
const smpVersion = 1
|
|
||||||
|
|
||||||
const (
|
|
||||||
smpState1 = iota
|
|
||||||
smpState2
|
|
||||||
smpState3
|
|
||||||
smpState4
|
|
||||||
)
|
|
||||||
|
|
||||||
type smpState struct {
|
|
||||||
state int
|
|
||||||
a2, a3, b2, b3, pb, qb *big.Int
|
|
||||||
g2a, g3a *big.Int
|
|
||||||
g2, g3 *big.Int
|
|
||||||
g3b, papb, qaqb, ra *big.Int
|
|
||||||
saved *tlv
|
|
||||||
secret *big.Int
|
|
||||||
question string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conversation) startSMP(question string) (tlvs []tlv) {
|
|
||||||
if c.smp.state != smpState1 {
|
|
||||||
tlvs = append(tlvs, c.generateSMPAbort())
|
|
||||||
}
|
|
||||||
tlvs = append(tlvs, c.generateSMP1(question))
|
|
||||||
c.smp.question = ""
|
|
||||||
c.smp.state = smpState2
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conversation) resetSMP() {
|
|
||||||
c.smp.state = smpState1
|
|
||||||
c.smp.secret = nil
|
|
||||||
c.smp.question = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conversation) processSMP(in tlv) (out tlv, complete bool, err error) {
|
|
||||||
data := in.data
|
|
||||||
|
|
||||||
switch in.typ {
|
|
||||||
case tlvTypeSMPAbort:
|
|
||||||
if c.smp.state != smpState1 {
|
|
||||||
err = smpFailureError
|
|
||||||
}
|
|
||||||
c.resetSMP()
|
|
||||||
return
|
|
||||||
case tlvTypeSMP1WithQuestion:
|
|
||||||
// We preprocess this into a SMP1 message.
|
|
||||||
nulPos := bytes.IndexByte(data, 0)
|
|
||||||
if nulPos == -1 {
|
|
||||||
err = errors.New("otr: SMP message with question didn't contain a NUL byte")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.smp.question = string(data[:nulPos])
|
|
||||||
data = data[nulPos+1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
numMPIs, data, ok := getU32(data)
|
|
||||||
if !ok || numMPIs > 20 {
|
|
||||||
err = errors.New("otr: corrupt SMP message")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mpis := make([]*big.Int, numMPIs)
|
|
||||||
for i := range mpis {
|
|
||||||
var ok bool
|
|
||||||
mpis[i], data, ok = getMPI(data)
|
|
||||||
if !ok {
|
|
||||||
err = errors.New("otr: corrupt SMP message")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch in.typ {
|
|
||||||
case tlvTypeSMP1, tlvTypeSMP1WithQuestion:
|
|
||||||
if c.smp.state != smpState1 {
|
|
||||||
c.resetSMP()
|
|
||||||
out = c.generateSMPAbort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if c.smp.secret == nil {
|
|
||||||
err = smpSecretMissingError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = c.processSMP1(mpis); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.smp.state = smpState3
|
|
||||||
out = c.generateSMP2()
|
|
||||||
case tlvTypeSMP2:
|
|
||||||
if c.smp.state != smpState2 {
|
|
||||||
c.resetSMP()
|
|
||||||
out = c.generateSMPAbort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if out, err = c.processSMP2(mpis); err != nil {
|
|
||||||
out = c.generateSMPAbort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.smp.state = smpState4
|
|
||||||
case tlvTypeSMP3:
|
|
||||||
if c.smp.state != smpState3 {
|
|
||||||
c.resetSMP()
|
|
||||||
out = c.generateSMPAbort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if out, err = c.processSMP3(mpis); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.smp.state = smpState1
|
|
||||||
c.smp.secret = nil
|
|
||||||
complete = true
|
|
||||||
case tlvTypeSMP4:
|
|
||||||
if c.smp.state != smpState4 {
|
|
||||||
c.resetSMP()
|
|
||||||
out = c.generateSMPAbort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = c.processSMP4(mpis); err != nil {
|
|
||||||
out = c.generateSMPAbort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.smp.state = smpState1
|
|
||||||
c.smp.secret = nil
|
|
||||||
complete = true
|
|
||||||
default:
|
|
||||||
panic("unknown SMP message")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conversation) calcSMPSecret(mutualSecret []byte, weStarted bool) {
|
|
||||||
h := sha256.New()
|
|
||||||
h.Write([]byte{smpVersion})
|
|
||||||
if weStarted {
|
|
||||||
h.Write(c.PrivateKey.PublicKey.Fingerprint())
|
|
||||||
h.Write(c.TheirPublicKey.Fingerprint())
|
|
||||||
} else {
|
|
||||||
h.Write(c.TheirPublicKey.Fingerprint())
|
|
||||||
h.Write(c.PrivateKey.PublicKey.Fingerprint())
|
|
||||||
}
|
|
||||||
h.Write(c.SSID[:])
|
|
||||||
h.Write(mutualSecret)
|
|
||||||
c.smp.secret = new(big.Int).SetBytes(h.Sum(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conversation) generateSMP1(question string) tlv {
|
|
||||||
var randBuf [16]byte
|
|
||||||
c.smp.a2 = c.randMPI(randBuf[:])
|
|
||||||
c.smp.a3 = c.randMPI(randBuf[:])
|
|
||||||
g2a := new(big.Int).Exp(g, c.smp.a2, p)
|
|
||||||
g3a := new(big.Int).Exp(g, c.smp.a3, p)
|
|
||||||
h := sha256.New()
|
|
||||||
|
|
||||||
r2 := c.randMPI(randBuf[:])
|
|
||||||
r := new(big.Int).Exp(g, r2, p)
|
|
||||||
c2 := new(big.Int).SetBytes(hashMPIs(h, 1, r))
|
|
||||||
d2 := new(big.Int).Mul(c.smp.a2, c2)
|
|
||||||
d2.Sub(r2, d2)
|
|
||||||
d2.Mod(d2, q)
|
|
||||||
if d2.Sign() < 0 {
|
|
||||||
d2.Add(d2, q)
|
|
||||||
}
|
|
||||||
|
|
||||||
r3 := c.randMPI(randBuf[:])
|
|
||||||
r.Exp(g, r3, p)
|
|
||||||
c3 := new(big.Int).SetBytes(hashMPIs(h, 2, r))
|
|
||||||
d3 := new(big.Int).Mul(c.smp.a3, c3)
|
|
||||||
d3.Sub(r3, d3)
|
|
||||||
d3.Mod(d3, q)
|
|
||||||
if d3.Sign() < 0 {
|
|
||||||
d3.Add(d3, q)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ret tlv
|
|
||||||
if len(question) > 0 {
|
|
||||||
ret.typ = tlvTypeSMP1WithQuestion
|
|
||||||
ret.data = append(ret.data, question...)
|
|
||||||
ret.data = append(ret.data, 0)
|
|
||||||
} else {
|
|
||||||
ret.typ = tlvTypeSMP1
|
|
||||||
}
|
|
||||||
ret.data = appendU32(ret.data, 6)
|
|
||||||
ret.data = appendMPIs(ret.data, g2a, c2, d2, g3a, c3, d3)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conversation) processSMP1(mpis []*big.Int) error {
|
|
||||||
if len(mpis) != 6 {
|
|
||||||
return errors.New("otr: incorrect number of arguments in SMP1 message")
|
|
||||||
}
|
|
||||||
g2a := mpis[0]
|
|
||||||
c2 := mpis[1]
|
|
||||||
d2 := mpis[2]
|
|
||||||
g3a := mpis[3]
|
|
||||||
c3 := mpis[4]
|
|
||||||
d3 := mpis[5]
|
|
||||||
h := sha256.New()
|
|
||||||
|
|
||||||
r := new(big.Int).Exp(g, d2, p)
|
|
||||||
s := new(big.Int).Exp(g2a, c2, p)
|
|
||||||
r.Mul(r, s)
|
|
||||||
r.Mod(r, p)
|
|
||||||
t := new(big.Int).SetBytes(hashMPIs(h, 1, r))
|
|
||||||
if c2.Cmp(t) != 0 {
|
|
||||||
return errors.New("otr: ZKP c2 incorrect in SMP1 message")
|
|
||||||
}
|
|
||||||
r.Exp(g, d3, p)
|
|
||||||
s.Exp(g3a, c3, p)
|
|
||||||
r.Mul(r, s)
|
|
||||||
r.Mod(r, p)
|
|
||||||
t.SetBytes(hashMPIs(h, 2, r))
|
|
||||||
if c3.Cmp(t) != 0 {
|
|
||||||
return errors.New("otr: ZKP c3 incorrect in SMP1 message")
|
|
||||||
}
|
|
||||||
|
|
||||||
c.smp.g2a = g2a
|
|
||||||
c.smp.g3a = g3a
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conversation) generateSMP2() tlv {
|
|
||||||
var randBuf [16]byte
|
|
||||||
b2 := c.randMPI(randBuf[:])
|
|
||||||
c.smp.b3 = c.randMPI(randBuf[:])
|
|
||||||
r2 := c.randMPI(randBuf[:])
|
|
||||||
r3 := c.randMPI(randBuf[:])
|
|
||||||
r4 := c.randMPI(randBuf[:])
|
|
||||||
r5 := c.randMPI(randBuf[:])
|
|
||||||
r6 := c.randMPI(randBuf[:])
|
|
||||||
|
|
||||||
g2b := new(big.Int).Exp(g, b2, p)
|
|
||||||
g3b := new(big.Int).Exp(g, c.smp.b3, p)
|
|
||||||
|
|
||||||
r := new(big.Int).Exp(g, r2, p)
|
|
||||||
h := sha256.New()
|
|
||||||
c2 := new(big.Int).SetBytes(hashMPIs(h, 3, r))
|
|
||||||
d2 := new(big.Int).Mul(b2, c2)
|
|
||||||
d2.Sub(r2, d2)
|
|
||||||
d2.Mod(d2, q)
|
|
||||||
if d2.Sign() < 0 {
|
|
||||||
d2.Add(d2, q)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Exp(g, r3, p)
|
|
||||||
c3 := new(big.Int).SetBytes(hashMPIs(h, 4, r))
|
|
||||||
d3 := new(big.Int).Mul(c.smp.b3, c3)
|
|
||||||
d3.Sub(r3, d3)
|
|
||||||
d3.Mod(d3, q)
|
|
||||||
if d3.Sign() < 0 {
|
|
||||||
d3.Add(d3, q)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.smp.g2 = new(big.Int).Exp(c.smp.g2a, b2, p)
|
|
||||||
c.smp.g3 = new(big.Int).Exp(c.smp.g3a, c.smp.b3, p)
|
|
||||||
c.smp.pb = new(big.Int).Exp(c.smp.g3, r4, p)
|
|
||||||
c.smp.qb = new(big.Int).Exp(g, r4, p)
|
|
||||||
r.Exp(c.smp.g2, c.smp.secret, p)
|
|
||||||
c.smp.qb.Mul(c.smp.qb, r)
|
|
||||||
c.smp.qb.Mod(c.smp.qb, p)
|
|
||||||
|
|
||||||
s := new(big.Int)
|
|
||||||
s.Exp(c.smp.g2, r6, p)
|
|
||||||
r.Exp(g, r5, p)
|
|
||||||
s.Mul(r, s)
|
|
||||||
s.Mod(s, p)
|
|
||||||
r.Exp(c.smp.g3, r5, p)
|
|
||||||
cp := new(big.Int).SetBytes(hashMPIs(h, 5, r, s))
|
|
||||||
|
|
||||||
// D5 = r5 - r4 cP mod q and D6 = r6 - y cP mod q
|
|
||||||
|
|
||||||
s.Mul(r4, cp)
|
|
||||||
r.Sub(r5, s)
|
|
||||||
d5 := new(big.Int).Mod(r, q)
|
|
||||||
if d5.Sign() < 0 {
|
|
||||||
d5.Add(d5, q)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Mul(c.smp.secret, cp)
|
|
||||||
r.Sub(r6, s)
|
|
||||||
d6 := new(big.Int).Mod(r, q)
|
|
||||||
if d6.Sign() < 0 {
|
|
||||||
d6.Add(d6, q)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ret tlv
|
|
||||||
ret.typ = tlvTypeSMP2
|
|
||||||
ret.data = appendU32(ret.data, 11)
|
|
||||||
ret.data = appendMPIs(ret.data, g2b, c2, d2, g3b, c3, d3, c.smp.pb, c.smp.qb, cp, d5, d6)
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conversation) processSMP2(mpis []*big.Int) (out tlv, err error) {
|
|
||||||
if len(mpis) != 11 {
|
|
||||||
err = errors.New("otr: incorrect number of arguments in SMP2 message")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
g2b := mpis[0]
|
|
||||||
c2 := mpis[1]
|
|
||||||
d2 := mpis[2]
|
|
||||||
g3b := mpis[3]
|
|
||||||
c3 := mpis[4]
|
|
||||||
d3 := mpis[5]
|
|
||||||
pb := mpis[6]
|
|
||||||
qb := mpis[7]
|
|
||||||
cp := mpis[8]
|
|
||||||
d5 := mpis[9]
|
|
||||||
d6 := mpis[10]
|
|
||||||
h := sha256.New()
|
|
||||||
|
|
||||||
r := new(big.Int).Exp(g, d2, p)
|
|
||||||
s := new(big.Int).Exp(g2b, c2, p)
|
|
||||||
r.Mul(r, s)
|
|
||||||
r.Mod(r, p)
|
|
||||||
s.SetBytes(hashMPIs(h, 3, r))
|
|
||||||
if c2.Cmp(s) != 0 {
|
|
||||||
err = errors.New("otr: ZKP c2 failed in SMP2 message")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Exp(g, d3, p)
|
|
||||||
s.Exp(g3b, c3, p)
|
|
||||||
r.Mul(r, s)
|
|
||||||
r.Mod(r, p)
|
|
||||||
s.SetBytes(hashMPIs(h, 4, r))
|
|
||||||
if c3.Cmp(s) != 0 {
|
|
||||||
err = errors.New("otr: ZKP c3 failed in SMP2 message")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.smp.g2 = new(big.Int).Exp(g2b, c.smp.a2, p)
|
|
||||||
c.smp.g3 = new(big.Int).Exp(g3b, c.smp.a3, p)
|
|
||||||
|
|
||||||
r.Exp(g, d5, p)
|
|
||||||
s.Exp(c.smp.g2, d6, p)
|
|
||||||
r.Mul(r, s)
|
|
||||||
s.Exp(qb, cp, p)
|
|
||||||
r.Mul(r, s)
|
|
||||||
r.Mod(r, p)
|
|
||||||
|
|
||||||
s.Exp(c.smp.g3, d5, p)
|
|
||||||
t := new(big.Int).Exp(pb, cp, p)
|
|
||||||
s.Mul(s, t)
|
|
||||||
s.Mod(s, p)
|
|
||||||
t.SetBytes(hashMPIs(h, 5, s, r))
|
|
||||||
if cp.Cmp(t) != 0 {
|
|
||||||
err = errors.New("otr: ZKP cP failed in SMP2 message")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var randBuf [16]byte
|
|
||||||
r4 := c.randMPI(randBuf[:])
|
|
||||||
r5 := c.randMPI(randBuf[:])
|
|
||||||
r6 := c.randMPI(randBuf[:])
|
|
||||||
r7 := c.randMPI(randBuf[:])
|
|
||||||
|
|
||||||
pa := new(big.Int).Exp(c.smp.g3, r4, p)
|
|
||||||
r.Exp(c.smp.g2, c.smp.secret, p)
|
|
||||||
qa := new(big.Int).Exp(g, r4, p)
|
|
||||||
qa.Mul(qa, r)
|
|
||||||
qa.Mod(qa, p)
|
|
||||||
|
|
||||||
r.Exp(g, r5, p)
|
|
||||||
s.Exp(c.smp.g2, r6, p)
|
|
||||||
r.Mul(r, s)
|
|
||||||
r.Mod(r, p)
|
|
||||||
|
|
||||||
s.Exp(c.smp.g3, r5, p)
|
|
||||||
cp.SetBytes(hashMPIs(h, 6, s, r))
|
|
||||||
|
|
||||||
r.Mul(r4, cp)
|
|
||||||
d5 = new(big.Int).Sub(r5, r)
|
|
||||||
d5.Mod(d5, q)
|
|
||||||
if d5.Sign() < 0 {
|
|
||||||
d5.Add(d5, q)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Mul(c.smp.secret, cp)
|
|
||||||
d6 = new(big.Int).Sub(r6, r)
|
|
||||||
d6.Mod(d6, q)
|
|
||||||
if d6.Sign() < 0 {
|
|
||||||
d6.Add(d6, q)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.ModInverse(qb, p)
|
|
||||||
qaqb := new(big.Int).Mul(qa, r)
|
|
||||||
qaqb.Mod(qaqb, p)
|
|
||||||
|
|
||||||
ra := new(big.Int).Exp(qaqb, c.smp.a3, p)
|
|
||||||
r.Exp(qaqb, r7, p)
|
|
||||||
s.Exp(g, r7, p)
|
|
||||||
cr := new(big.Int).SetBytes(hashMPIs(h, 7, s, r))
|
|
||||||
|
|
||||||
r.Mul(c.smp.a3, cr)
|
|
||||||
d7 := new(big.Int).Sub(r7, r)
|
|
||||||
d7.Mod(d7, q)
|
|
||||||
if d7.Sign() < 0 {
|
|
||||||
d7.Add(d7, q)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.smp.g3b = g3b
|
|
||||||
c.smp.qaqb = qaqb
|
|
||||||
|
|
||||||
r.ModInverse(pb, p)
|
|
||||||
c.smp.papb = new(big.Int).Mul(pa, r)
|
|
||||||
c.smp.papb.Mod(c.smp.papb, p)
|
|
||||||
c.smp.ra = ra
|
|
||||||
|
|
||||||
out.typ = tlvTypeSMP3
|
|
||||||
out.data = appendU32(out.data, 8)
|
|
||||||
out.data = appendMPIs(out.data, pa, qa, cp, d5, d6, ra, cr, d7)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conversation) processSMP3(mpis []*big.Int) (out tlv, err error) {
|
|
||||||
if len(mpis) != 8 {
|
|
||||||
err = errors.New("otr: incorrect number of arguments in SMP3 message")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pa := mpis[0]
|
|
||||||
qa := mpis[1]
|
|
||||||
cp := mpis[2]
|
|
||||||
d5 := mpis[3]
|
|
||||||
d6 := mpis[4]
|
|
||||||
ra := mpis[5]
|
|
||||||
cr := mpis[6]
|
|
||||||
d7 := mpis[7]
|
|
||||||
h := sha256.New()
|
|
||||||
|
|
||||||
r := new(big.Int).Exp(g, d5, p)
|
|
||||||
s := new(big.Int).Exp(c.smp.g2, d6, p)
|
|
||||||
r.Mul(r, s)
|
|
||||||
s.Exp(qa, cp, p)
|
|
||||||
r.Mul(r, s)
|
|
||||||
r.Mod(r, p)
|
|
||||||
|
|
||||||
s.Exp(c.smp.g3, d5, p)
|
|
||||||
t := new(big.Int).Exp(pa, cp, p)
|
|
||||||
s.Mul(s, t)
|
|
||||||
s.Mod(s, p)
|
|
||||||
t.SetBytes(hashMPIs(h, 6, s, r))
|
|
||||||
if t.Cmp(cp) != 0 {
|
|
||||||
err = errors.New("otr: ZKP cP failed in SMP3 message")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r.ModInverse(c.smp.qb, p)
|
|
||||||
qaqb := new(big.Int).Mul(qa, r)
|
|
||||||
qaqb.Mod(qaqb, p)
|
|
||||||
|
|
||||||
r.Exp(qaqb, d7, p)
|
|
||||||
s.Exp(ra, cr, p)
|
|
||||||
r.Mul(r, s)
|
|
||||||
r.Mod(r, p)
|
|
||||||
|
|
||||||
s.Exp(g, d7, p)
|
|
||||||
t.Exp(c.smp.g3a, cr, p)
|
|
||||||
s.Mul(s, t)
|
|
||||||
s.Mod(s, p)
|
|
||||||
t.SetBytes(hashMPIs(h, 7, s, r))
|
|
||||||
if t.Cmp(cr) != 0 {
|
|
||||||
err = errors.New("otr: ZKP cR failed in SMP3 message")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var randBuf [16]byte
|
|
||||||
r7 := c.randMPI(randBuf[:])
|
|
||||||
rb := new(big.Int).Exp(qaqb, c.smp.b3, p)
|
|
||||||
|
|
||||||
r.Exp(qaqb, r7, p)
|
|
||||||
s.Exp(g, r7, p)
|
|
||||||
cr = new(big.Int).SetBytes(hashMPIs(h, 8, s, r))
|
|
||||||
|
|
||||||
r.Mul(c.smp.b3, cr)
|
|
||||||
d7 = new(big.Int).Sub(r7, r)
|
|
||||||
d7.Mod(d7, q)
|
|
||||||
if d7.Sign() < 0 {
|
|
||||||
d7.Add(d7, q)
|
|
||||||
}
|
|
||||||
|
|
||||||
out.typ = tlvTypeSMP4
|
|
||||||
out.data = appendU32(out.data, 3)
|
|
||||||
out.data = appendMPIs(out.data, rb, cr, d7)
|
|
||||||
|
|
||||||
r.ModInverse(c.smp.pb, p)
|
|
||||||
r.Mul(pa, r)
|
|
||||||
r.Mod(r, p)
|
|
||||||
s.Exp(ra, c.smp.b3, p)
|
|
||||||
if r.Cmp(s) != 0 {
|
|
||||||
err = smpFailureError
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conversation) processSMP4(mpis []*big.Int) error {
|
|
||||||
if len(mpis) != 3 {
|
|
||||||
return errors.New("otr: incorrect number of arguments in SMP4 message")
|
|
||||||
}
|
|
||||||
rb := mpis[0]
|
|
||||||
cr := mpis[1]
|
|
||||||
d7 := mpis[2]
|
|
||||||
h := sha256.New()
|
|
||||||
|
|
||||||
r := new(big.Int).Exp(c.smp.qaqb, d7, p)
|
|
||||||
s := new(big.Int).Exp(rb, cr, p)
|
|
||||||
r.Mul(r, s)
|
|
||||||
r.Mod(r, p)
|
|
||||||
|
|
||||||
s.Exp(g, d7, p)
|
|
||||||
t := new(big.Int).Exp(c.smp.g3b, cr, p)
|
|
||||||
s.Mul(s, t)
|
|
||||||
s.Mod(s, p)
|
|
||||||
t.SetBytes(hashMPIs(h, 8, s, r))
|
|
||||||
if t.Cmp(cr) != 0 {
|
|
||||||
return errors.New("otr: ZKP cR failed in SMP4 message")
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Exp(rb, c.smp.a3, p)
|
|
||||||
if r.Cmp(c.smp.papb) != 0 {
|
|
||||||
return smpFailureError
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conversation) generateSMPAbort() tlv {
|
|
||||||
return tlv{typ: tlvTypeSMPAbort}
|
|
||||||
}
|
|
||||||
|
|
||||||
func hashMPIs(h hash.Hash, magic byte, mpis ...*big.Int) []byte {
|
|
||||||
if h != nil {
|
|
||||||
h.Reset()
|
|
||||||
} else {
|
|
||||||
h = sha256.New()
|
|
||||||
}
|
|
||||||
|
|
||||||
h.Write([]byte{magic})
|
|
||||||
for _, mpi := range mpis {
|
|
||||||
h.Write(appendMPI(nil, mpi))
|
|
||||||
}
|
|
||||||
return h.Sum(nil)
|
|
||||||
}
|
|
7
vendor/golang.org/x/crypto/ssh/test/doc.go
generated
vendored
7
vendor/golang.org/x/crypto/ssh/test/doc.go
generated
vendored
@ -1,7 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package test contains integration tests for the
|
|
||||||
// golang.org/x/crypto/ssh package.
|
|
||||||
package test // import "golang.org/x/crypto/ssh/test"
|
|
173
vendor/golang.org/x/crypto/ssh/test/sshd_test_pw.c
generated
vendored
173
vendor/golang.org/x/crypto/ssh/test/sshd_test_pw.c
generated
vendored
@ -1,173 +0,0 @@
|
|||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// sshd_test_pw.c
|
|
||||||
// Wrapper to inject test password data for sshd PAM authentication
|
|
||||||
//
|
|
||||||
// This wrapper implements custom versions of getpwnam, getpwnam_r,
|
|
||||||
// getspnam and getspnam_r. These functions first call their real
|
|
||||||
// libc versions, then check if the requested user matches test user
|
|
||||||
// specified in env variable TEST_USER and if so replace the password
|
|
||||||
// with crypted() value of TEST_PASSWD env variable.
|
|
||||||
//
|
|
||||||
// Compile:
|
|
||||||
// gcc -Wall -shared -o sshd_test_pw.so -fPIC sshd_test_pw.c
|
|
||||||
//
|
|
||||||
// Compile with debug:
|
|
||||||
// gcc -DVERBOSE -Wall -shared -o sshd_test_pw.so -fPIC sshd_test_pw.c
|
|
||||||
//
|
|
||||||
// Run sshd:
|
|
||||||
// LD_PRELOAD="sshd_test_pw.so" TEST_USER="..." TEST_PASSWD="..." sshd ...
|
|
||||||
|
|
||||||
// +build ignore
|
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <string.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <shadow.h>
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#ifdef VERBOSE
|
|
||||||
#define DEBUG(X...) fprintf(stderr, X)
|
|
||||||
#else
|
|
||||||
#define DEBUG(X...) while (0) { }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* crypt() password */
|
|
||||||
static char *
|
|
||||||
pwhash(char *passwd) {
|
|
||||||
return strdup(crypt(passwd, "$6$"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pointers to real functions in libc */
|
|
||||||
static struct passwd * (*real_getpwnam)(const char *) = NULL;
|
|
||||||
static int (*real_getpwnam_r)(const char *, struct passwd *, char *, size_t, struct passwd **) = NULL;
|
|
||||||
static struct spwd * (*real_getspnam)(const char *) = NULL;
|
|
||||||
static int (*real_getspnam_r)(const char *, struct spwd *, char *, size_t, struct spwd **) = NULL;
|
|
||||||
|
|
||||||
/* Cached test user and test password */
|
|
||||||
static char *test_user = NULL;
|
|
||||||
static char *test_passwd_hash = NULL;
|
|
||||||
|
|
||||||
static void
|
|
||||||
init(void) {
|
|
||||||
/* Fetch real libc function pointers */
|
|
||||||
real_getpwnam = dlsym(RTLD_NEXT, "getpwnam");
|
|
||||||
real_getpwnam_r = dlsym(RTLD_NEXT, "getpwnam_r");
|
|
||||||
real_getspnam = dlsym(RTLD_NEXT, "getspnam");
|
|
||||||
real_getspnam_r = dlsym(RTLD_NEXT, "getspnam_r");
|
|
||||||
|
|
||||||
/* abort if env variables are not defined */
|
|
||||||
if (getenv("TEST_USER") == NULL || getenv("TEST_PASSWD") == NULL) {
|
|
||||||
fprintf(stderr, "env variables TEST_USER and TEST_PASSWD are missing\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fetch test user and test password from env */
|
|
||||||
test_user = strdup(getenv("TEST_USER"));
|
|
||||||
test_passwd_hash = pwhash(getenv("TEST_PASSWD"));
|
|
||||||
|
|
||||||
DEBUG("sshd_test_pw init():\n");
|
|
||||||
DEBUG("\treal_getpwnam: %p\n", real_getpwnam);
|
|
||||||
DEBUG("\treal_getpwnam_r: %p\n", real_getpwnam_r);
|
|
||||||
DEBUG("\treal_getspnam: %p\n", real_getspnam);
|
|
||||||
DEBUG("\treal_getspnam_r: %p\n", real_getspnam_r);
|
|
||||||
DEBUG("\tTEST_USER: '%s'\n", test_user);
|
|
||||||
DEBUG("\tTEST_PASSWD: '%s'\n", getenv("TEST_PASSWD"));
|
|
||||||
DEBUG("\tTEST_PASSWD_HASH: '%s'\n", test_passwd_hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
is_test_user(const char *name) {
|
|
||||||
if (test_user != NULL && strcmp(test_user, name) == 0)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* getpwnam */
|
|
||||||
|
|
||||||
struct passwd *
|
|
||||||
getpwnam(const char *name) {
|
|
||||||
struct passwd *pw;
|
|
||||||
|
|
||||||
DEBUG("sshd_test_pw getpwnam(%s)\n", name);
|
|
||||||
|
|
||||||
if (real_getpwnam == NULL)
|
|
||||||
init();
|
|
||||||
if ((pw = real_getpwnam(name)) == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (is_test_user(name))
|
|
||||||
pw->pw_passwd = strdup(test_passwd_hash);
|
|
||||||
|
|
||||||
return pw;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* getpwnam_r */
|
|
||||||
|
|
||||||
int
|
|
||||||
getpwnam_r(const char *name,
|
|
||||||
struct passwd *pwd,
|
|
||||||
char *buf,
|
|
||||||
size_t buflen,
|
|
||||||
struct passwd **result) {
|
|
||||||
int r;
|
|
||||||
|
|
||||||
DEBUG("sshd_test_pw getpwnam_r(%s)\n", name);
|
|
||||||
|
|
||||||
if (real_getpwnam_r == NULL)
|
|
||||||
init();
|
|
||||||
if ((r = real_getpwnam_r(name, pwd, buf, buflen, result)) != 0 || *result == NULL)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (is_test_user(name))
|
|
||||||
pwd->pw_passwd = strdup(test_passwd_hash);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* getspnam */
|
|
||||||
|
|
||||||
struct spwd *
|
|
||||||
getspnam(const char *name) {
|
|
||||||
struct spwd *sp;
|
|
||||||
|
|
||||||
DEBUG("sshd_test_pw getspnam(%s)\n", name);
|
|
||||||
|
|
||||||
if (real_getspnam == NULL)
|
|
||||||
init();
|
|
||||||
if ((sp = real_getspnam(name)) == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (is_test_user(name))
|
|
||||||
sp->sp_pwdp = strdup(test_passwd_hash);
|
|
||||||
|
|
||||||
return sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* getspnam_r */
|
|
||||||
|
|
||||||
int
|
|
||||||
getspnam_r(const char *name,
|
|
||||||
struct spwd *spbuf,
|
|
||||||
char *buf,
|
|
||||||
size_t buflen,
|
|
||||||
struct spwd **spbufp) {
|
|
||||||
int r;
|
|
||||||
|
|
||||||
DEBUG("sshd_test_pw getspnam_r(%s)\n", name);
|
|
||||||
|
|
||||||
if (real_getspnam_r == NULL)
|
|
||||||
init();
|
|
||||||
if ((r = real_getspnam_r(name, spbuf, buf, buflen, spbufp)) != 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (is_test_user(name))
|
|
||||||
spbuf->sp_pwdp = strdup(test_passwd_hash);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
48
vendor/golang.org/x/sys/windows/svc/event.go
generated
vendored
48
vendor/golang.org/x/sys/windows/svc/event.go
generated
vendored
@ -1,48 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package svc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
// event represents auto-reset, initially non-signaled Windows event.
|
|
||||||
// It is used to communicate between go and asm parts of this package.
|
|
||||||
type event struct {
|
|
||||||
h windows.Handle
|
|
||||||
}
|
|
||||||
|
|
||||||
func newEvent() (*event, error) {
|
|
||||||
h, err := windows.CreateEvent(nil, 0, 0, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &event{h: h}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *event) Close() error {
|
|
||||||
return windows.CloseHandle(e.h)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *event) Set() error {
|
|
||||||
return windows.SetEvent(e.h)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *event) Wait() error {
|
|
||||||
s, err := windows.WaitForSingleObject(e.h, windows.INFINITE)
|
|
||||||
switch s {
|
|
||||||
case windows.WAIT_OBJECT_0:
|
|
||||||
break
|
|
||||||
case windows.WAIT_FAILED:
|
|
||||||
return err
|
|
||||||
default:
|
|
||||||
return errors.New("unexpected result from WaitForSingleObject")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
24
vendor/golang.org/x/sys/windows/svc/go12.c
generated
vendored
24
vendor/golang.org/x/sys/windows/svc/go12.c
generated
vendored
@ -1,24 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
// +build !go1.3
|
|
||||||
|
|
||||||
// copied from pkg/runtime
|
|
||||||
typedef unsigned int uint32;
|
|
||||||
typedef unsigned long long int uint64;
|
|
||||||
#ifdef _64BIT
|
|
||||||
typedef uint64 uintptr;
|
|
||||||
#else
|
|
||||||
typedef uint32 uintptr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// from sys_386.s or sys_amd64.s
|
|
||||||
void ·servicemain(void);
|
|
||||||
|
|
||||||
void
|
|
||||||
·getServiceMain(uintptr *r)
|
|
||||||
{
|
|
||||||
*r = (uintptr)·servicemain;
|
|
||||||
}
|
|
11
vendor/golang.org/x/sys/windows/svc/go12.go
generated
vendored
11
vendor/golang.org/x/sys/windows/svc/go12.go
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
// +build !go1.3
|
|
||||||
|
|
||||||
package svc
|
|
||||||
|
|
||||||
// from go12.c
|
|
||||||
func getServiceMain(r *uintptr)
|
|
31
vendor/golang.org/x/sys/windows/svc/go13.go
generated
vendored
31
vendor/golang.org/x/sys/windows/svc/go13.go
generated
vendored
@ -1,31 +0,0 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
// +build go1.3
|
|
||||||
|
|
||||||
package svc
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
const ptrSize = 4 << (^uintptr(0) >> 63) // unsafe.Sizeof(uintptr(0)) but an ideal const
|
|
||||||
|
|
||||||
// Should be a built-in for unsafe.Pointer?
|
|
||||||
func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
|
|
||||||
return unsafe.Pointer(uintptr(p) + x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// funcPC returns the entry PC of the function f.
|
|
||||||
// It assumes that f is a func value. Otherwise the behavior is undefined.
|
|
||||||
func funcPC(f interface{}) uintptr {
|
|
||||||
return **(**uintptr)(add(unsafe.Pointer(&f), ptrSize))
|
|
||||||
}
|
|
||||||
|
|
||||||
// from sys_386.s and sys_amd64.s
|
|
||||||
func servicectlhandler(ctl uint32) uintptr
|
|
||||||
func servicemain(argc uint32, argv **uint16)
|
|
||||||
|
|
||||||
func getServiceMain(r *uintptr) {
|
|
||||||
*r = funcPC(servicemain)
|
|
||||||
}
|
|
62
vendor/golang.org/x/sys/windows/svc/security.go
generated
vendored
62
vendor/golang.org/x/sys/windows/svc/security.go
generated
vendored
@ -1,62 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package svc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
func allocSid(subAuth0 uint32) (*windows.SID, error) {
|
|
||||||
var sid *windows.SID
|
|
||||||
err := windows.AllocateAndInitializeSid(&windows.SECURITY_NT_AUTHORITY,
|
|
||||||
1, subAuth0, 0, 0, 0, 0, 0, 0, 0, &sid)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return sid, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsAnInteractiveSession determines if calling process is running interactively.
|
|
||||||
// It queries the process token for membership in the Interactive group.
|
|
||||||
// http://stackoverflow.com/questions/2668851/how-do-i-detect-that-my-application-is-running-as-service-or-in-an-interactive-s
|
|
||||||
func IsAnInteractiveSession() (bool, error) {
|
|
||||||
interSid, err := allocSid(windows.SECURITY_INTERACTIVE_RID)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
defer windows.FreeSid(interSid)
|
|
||||||
|
|
||||||
serviceSid, err := allocSid(windows.SECURITY_SERVICE_RID)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
defer windows.FreeSid(serviceSid)
|
|
||||||
|
|
||||||
t, err := windows.OpenCurrentProcessToken()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
defer t.Close()
|
|
||||||
|
|
||||||
gs, err := t.GetTokenGroups()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
p := unsafe.Pointer(&gs.Groups[0])
|
|
||||||
groups := (*[2 << 20]windows.SIDAndAttributes)(p)[:gs.GroupCount]
|
|
||||||
for _, g := range groups {
|
|
||||||
if windows.EqualSid(g.Sid, interSid) {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
if windows.EqualSid(g.Sid, serviceSid) {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
363
vendor/golang.org/x/sys/windows/svc/service.go
generated
vendored
363
vendor/golang.org/x/sys/windows/svc/service.go
generated
vendored
@ -1,363 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
// Package svc provides everything required to build Windows service.
|
|
||||||
//
|
|
||||||
package svc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"runtime"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
|
||||||
|
|
||||||
// State describes service execution state (Stopped, Running and so on).
|
|
||||||
type State uint32
|
|
||||||
|
|
||||||
const (
|
|
||||||
Stopped = State(windows.SERVICE_STOPPED)
|
|
||||||
StartPending = State(windows.SERVICE_START_PENDING)
|
|
||||||
StopPending = State(windows.SERVICE_STOP_PENDING)
|
|
||||||
Running = State(windows.SERVICE_RUNNING)
|
|
||||||
ContinuePending = State(windows.SERVICE_CONTINUE_PENDING)
|
|
||||||
PausePending = State(windows.SERVICE_PAUSE_PENDING)
|
|
||||||
Paused = State(windows.SERVICE_PAUSED)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Cmd represents service state change request. It is sent to a service
|
|
||||||
// by the service manager, and should be actioned upon by the service.
|
|
||||||
type Cmd uint32
|
|
||||||
|
|
||||||
const (
|
|
||||||
Stop = Cmd(windows.SERVICE_CONTROL_STOP)
|
|
||||||
Pause = Cmd(windows.SERVICE_CONTROL_PAUSE)
|
|
||||||
Continue = Cmd(windows.SERVICE_CONTROL_CONTINUE)
|
|
||||||
Interrogate = Cmd(windows.SERVICE_CONTROL_INTERROGATE)
|
|
||||||
Shutdown = Cmd(windows.SERVICE_CONTROL_SHUTDOWN)
|
|
||||||
ParamChange = Cmd(windows.SERVICE_CONTROL_PARAMCHANGE)
|
|
||||||
NetBindAdd = Cmd(windows.SERVICE_CONTROL_NETBINDADD)
|
|
||||||
NetBindRemove = Cmd(windows.SERVICE_CONTROL_NETBINDREMOVE)
|
|
||||||
NetBindEnable = Cmd(windows.SERVICE_CONTROL_NETBINDENABLE)
|
|
||||||
NetBindDisable = Cmd(windows.SERVICE_CONTROL_NETBINDDISABLE)
|
|
||||||
DeviceEvent = Cmd(windows.SERVICE_CONTROL_DEVICEEVENT)
|
|
||||||
HardwareProfileChange = Cmd(windows.SERVICE_CONTROL_HARDWAREPROFILECHANGE)
|
|
||||||
PowerEvent = Cmd(windows.SERVICE_CONTROL_POWEREVENT)
|
|
||||||
SessionChange = Cmd(windows.SERVICE_CONTROL_SESSIONCHANGE)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Accepted is used to describe commands accepted by the service.
|
|
||||||
// Note that Interrogate is always accepted.
|
|
||||||
type Accepted uint32
|
|
||||||
|
|
||||||
const (
|
|
||||||
AcceptStop = Accepted(windows.SERVICE_ACCEPT_STOP)
|
|
||||||
AcceptShutdown = Accepted(windows.SERVICE_ACCEPT_SHUTDOWN)
|
|
||||||
AcceptPauseAndContinue = Accepted(windows.SERVICE_ACCEPT_PAUSE_CONTINUE)
|
|
||||||
AcceptParamChange = Accepted(windows.SERVICE_ACCEPT_PARAMCHANGE)
|
|
||||||
AcceptNetBindChange = Accepted(windows.SERVICE_ACCEPT_NETBINDCHANGE)
|
|
||||||
AcceptHardwareProfileChange = Accepted(windows.SERVICE_ACCEPT_HARDWAREPROFILECHANGE)
|
|
||||||
AcceptPowerEvent = Accepted(windows.SERVICE_ACCEPT_POWEREVENT)
|
|
||||||
AcceptSessionChange = Accepted(windows.SERVICE_ACCEPT_SESSIONCHANGE)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Status combines State and Accepted commands to fully describe running service.
|
|
||||||
type Status struct {
|
|
||||||
State State
|
|
||||||
Accepts Accepted
|
|
||||||
CheckPoint uint32 // used to report progress during a lengthy operation
|
|
||||||
WaitHint uint32 // estimated time required for a pending operation, in milliseconds
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChangeRequest is sent to the service Handler to request service status change.
|
|
||||||
type ChangeRequest struct {
|
|
||||||
Cmd Cmd
|
|
||||||
EventType uint32
|
|
||||||
EventData uintptr
|
|
||||||
CurrentStatus Status
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handler is the interface that must be implemented to build Windows service.
|
|
||||||
type Handler interface {
|
|
||||||
|
|
||||||
// Execute will be called by the package code at the start of
|
|
||||||
// the service, and the service will exit once Execute completes.
|
|
||||||
// Inside Execute you must read service change requests from r and
|
|
||||||
// act accordingly. You must keep service control manager up to date
|
|
||||||
// about state of your service by writing into s as required.
|
|
||||||
// args contains service name followed by argument strings passed
|
|
||||||
// to the service.
|
|
||||||
// You can provide service exit code in exitCode return parameter,
|
|
||||||
// with 0 being "no error". You can also indicate if exit code,
|
|
||||||
// if any, is service specific or not by using svcSpecificEC
|
|
||||||
// parameter.
|
|
||||||
Execute(args []string, r <-chan ChangeRequest, s chan<- Status) (svcSpecificEC bool, exitCode uint32)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
// These are used by asm code.
|
|
||||||
goWaitsH uintptr
|
|
||||||
cWaitsH uintptr
|
|
||||||
ssHandle uintptr
|
|
||||||
sName *uint16
|
|
||||||
sArgc uintptr
|
|
||||||
sArgv **uint16
|
|
||||||
ctlHandlerExProc uintptr
|
|
||||||
cSetEvent uintptr
|
|
||||||
cWaitForSingleObject uintptr
|
|
||||||
cRegisterServiceCtrlHandlerExW uintptr
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
k := syscall.MustLoadDLL("kernel32.dll")
|
|
||||||
cSetEvent = k.MustFindProc("SetEvent").Addr()
|
|
||||||
cWaitForSingleObject = k.MustFindProc("WaitForSingleObject").Addr()
|
|
||||||
a := syscall.MustLoadDLL("advapi32.dll")
|
|
||||||
cRegisterServiceCtrlHandlerExW = a.MustFindProc("RegisterServiceCtrlHandlerExW").Addr()
|
|
||||||
}
|
|
||||||
|
|
||||||
// The HandlerEx prototype also has a context pointer but since we don't use
|
|
||||||
// it at start-up time we don't have to pass it over either.
|
|
||||||
type ctlEvent struct {
|
|
||||||
cmd Cmd
|
|
||||||
eventType uint32
|
|
||||||
eventData uintptr
|
|
||||||
errno uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
// service provides access to windows service api.
|
|
||||||
type service struct {
|
|
||||||
name string
|
|
||||||
h windows.Handle
|
|
||||||
cWaits *event
|
|
||||||
goWaits *event
|
|
||||||
c chan ctlEvent
|
|
||||||
handler Handler
|
|
||||||
}
|
|
||||||
|
|
||||||
func newService(name string, handler Handler) (*service, error) {
|
|
||||||
var s service
|
|
||||||
var err error
|
|
||||||
s.name = name
|
|
||||||
s.c = make(chan ctlEvent)
|
|
||||||
s.handler = handler
|
|
||||||
s.cWaits, err = newEvent()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
s.goWaits, err = newEvent()
|
|
||||||
if err != nil {
|
|
||||||
s.cWaits.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *service) close() error {
|
|
||||||
s.cWaits.Close()
|
|
||||||
s.goWaits.Close()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type exitCode struct {
|
|
||||||
isSvcSpecific bool
|
|
||||||
errno uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *service) updateStatus(status *Status, ec *exitCode) error {
|
|
||||||
if s.h == 0 {
|
|
||||||
return errors.New("updateStatus with no service status handle")
|
|
||||||
}
|
|
||||||
var t windows.SERVICE_STATUS
|
|
||||||
t.ServiceType = windows.SERVICE_WIN32_OWN_PROCESS
|
|
||||||
t.CurrentState = uint32(status.State)
|
|
||||||
if status.Accepts&AcceptStop != 0 {
|
|
||||||
t.ControlsAccepted |= windows.SERVICE_ACCEPT_STOP
|
|
||||||
}
|
|
||||||
if status.Accepts&AcceptShutdown != 0 {
|
|
||||||
t.ControlsAccepted |= windows.SERVICE_ACCEPT_SHUTDOWN
|
|
||||||
}
|
|
||||||
if status.Accepts&AcceptPauseAndContinue != 0 {
|
|
||||||
t.ControlsAccepted |= windows.SERVICE_ACCEPT_PAUSE_CONTINUE
|
|
||||||
}
|
|
||||||
if status.Accepts&AcceptParamChange != 0 {
|
|
||||||
t.ControlsAccepted |= windows.SERVICE_ACCEPT_PARAMCHANGE
|
|
||||||
}
|
|
||||||
if status.Accepts&AcceptNetBindChange != 0 {
|
|
||||||
t.ControlsAccepted |= windows.SERVICE_ACCEPT_NETBINDCHANGE
|
|
||||||
}
|
|
||||||
if status.Accepts&AcceptHardwareProfileChange != 0 {
|
|
||||||
t.ControlsAccepted |= windows.SERVICE_ACCEPT_HARDWAREPROFILECHANGE
|
|
||||||
}
|
|
||||||
if status.Accepts&AcceptPowerEvent != 0 {
|
|
||||||
t.ControlsAccepted |= windows.SERVICE_ACCEPT_POWEREVENT
|
|
||||||
}
|
|
||||||
if status.Accepts&AcceptSessionChange != 0 {
|
|
||||||
t.ControlsAccepted |= windows.SERVICE_ACCEPT_SESSIONCHANGE
|
|
||||||
}
|
|
||||||
if ec.errno == 0 {
|
|
||||||
t.Win32ExitCode = windows.NO_ERROR
|
|
||||||
t.ServiceSpecificExitCode = windows.NO_ERROR
|
|
||||||
} else if ec.isSvcSpecific {
|
|
||||||
t.Win32ExitCode = uint32(windows.ERROR_SERVICE_SPECIFIC_ERROR)
|
|
||||||
t.ServiceSpecificExitCode = ec.errno
|
|
||||||
} else {
|
|
||||||
t.Win32ExitCode = ec.errno
|
|
||||||
t.ServiceSpecificExitCode = windows.NO_ERROR
|
|
||||||
}
|
|
||||||
t.CheckPoint = status.CheckPoint
|
|
||||||
t.WaitHint = status.WaitHint
|
|
||||||
return windows.SetServiceStatus(s.h, &t)
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
sysErrSetServiceStatusFailed = uint32(syscall.APPLICATION_ERROR) + iota
|
|
||||||
sysErrNewThreadInCallback
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *service) run() {
|
|
||||||
s.goWaits.Wait()
|
|
||||||
s.h = windows.Handle(ssHandle)
|
|
||||||
argv := (*[100]*int16)(unsafe.Pointer(sArgv))[:sArgc]
|
|
||||||
args := make([]string, len(argv))
|
|
||||||
for i, a := range argv {
|
|
||||||
args[i] = syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(a))[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdsToHandler := make(chan ChangeRequest)
|
|
||||||
changesFromHandler := make(chan Status)
|
|
||||||
exitFromHandler := make(chan exitCode)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
ss, errno := s.handler.Execute(args, cmdsToHandler, changesFromHandler)
|
|
||||||
exitFromHandler <- exitCode{ss, errno}
|
|
||||||
}()
|
|
||||||
|
|
||||||
status := Status{State: Stopped}
|
|
||||||
ec := exitCode{isSvcSpecific: true, errno: 0}
|
|
||||||
var outch chan ChangeRequest
|
|
||||||
inch := s.c
|
|
||||||
var cmd Cmd
|
|
||||||
var evtype uint32
|
|
||||||
var evdata uintptr
|
|
||||||
loop:
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case r := <-inch:
|
|
||||||
if r.errno != 0 {
|
|
||||||
ec.errno = r.errno
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
inch = nil
|
|
||||||
outch = cmdsToHandler
|
|
||||||
cmd = r.cmd
|
|
||||||
evtype = r.eventType
|
|
||||||
evdata = r.eventData
|
|
||||||
case outch <- ChangeRequest{cmd, evtype, evdata, status}:
|
|
||||||
inch = s.c
|
|
||||||
outch = nil
|
|
||||||
case c := <-changesFromHandler:
|
|
||||||
err := s.updateStatus(&c, &ec)
|
|
||||||
if err != nil {
|
|
||||||
// best suitable error number
|
|
||||||
ec.errno = sysErrSetServiceStatusFailed
|
|
||||||
if err2, ok := err.(syscall.Errno); ok {
|
|
||||||
ec.errno = uint32(err2)
|
|
||||||
}
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
status = c
|
|
||||||
case ec = <-exitFromHandler:
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.updateStatus(&Status{State: Stopped}, &ec)
|
|
||||||
s.cWaits.Set()
|
|
||||||
}
|
|
||||||
|
|
||||||
func newCallback(fn interface{}) (cb uintptr, err error) {
|
|
||||||
defer func() {
|
|
||||||
r := recover()
|
|
||||||
if r == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cb = 0
|
|
||||||
switch v := r.(type) {
|
|
||||||
case string:
|
|
||||||
err = errors.New(v)
|
|
||||||
case error:
|
|
||||||
err = v
|
|
||||||
default:
|
|
||||||
err = errors.New("unexpected panic in syscall.NewCallback")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return syscall.NewCallback(fn), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BUG(brainman): There is no mechanism to run multiple services
|
|
||||||
// inside one single executable. Perhaps, it can be overcome by
|
|
||||||
// using RegisterServiceCtrlHandlerEx Windows api.
|
|
||||||
|
|
||||||
// Run executes service name by calling appropriate handler function.
|
|
||||||
func Run(name string, handler Handler) error {
|
|
||||||
runtime.LockOSThread()
|
|
||||||
|
|
||||||
tid := windows.GetCurrentThreadId()
|
|
||||||
|
|
||||||
s, err := newService(name, handler)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ctlHandler := func(ctl uint32, evtype uint32, evdata uintptr, context uintptr) uintptr {
|
|
||||||
e := ctlEvent{cmd: Cmd(ctl), eventType: evtype, eventData: evdata}
|
|
||||||
// We assume that this callback function is running on
|
|
||||||
// the same thread as Run. Nowhere in MS documentation
|
|
||||||
// I could find statement to guarantee that. So putting
|
|
||||||
// check here to verify, otherwise things will go bad
|
|
||||||
// quickly, if ignored.
|
|
||||||
i := windows.GetCurrentThreadId()
|
|
||||||
if i != tid {
|
|
||||||
e.errno = sysErrNewThreadInCallback
|
|
||||||
}
|
|
||||||
s.c <- e
|
|
||||||
// Always return NO_ERROR (0) for now.
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var svcmain uintptr
|
|
||||||
getServiceMain(&svcmain)
|
|
||||||
t := []windows.SERVICE_TABLE_ENTRY{
|
|
||||||
{syscall.StringToUTF16Ptr(s.name), svcmain},
|
|
||||||
{nil, 0},
|
|
||||||
}
|
|
||||||
|
|
||||||
goWaitsH = uintptr(s.goWaits.h)
|
|
||||||
cWaitsH = uintptr(s.cWaits.h)
|
|
||||||
sName = t[0].ServiceName
|
|
||||||
ctlHandlerExProc, err = newCallback(ctlHandler)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
go s.run()
|
|
||||||
|
|
||||||
err = windows.StartServiceCtrlDispatcher(&t[0])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StatusHandle returns service status handle. It is safe to call this function
|
|
||||||
// from inside the Handler.Execute because then it is guaranteed to be set.
|
|
||||||
// This code will have to change once multiple services are possible per process.
|
|
||||||
func StatusHandle() windows.Handle {
|
|
||||||
return windows.Handle(ssHandle)
|
|
||||||
}
|
|
68
vendor/golang.org/x/sys/windows/svc/sys_386.s
generated
vendored
68
vendor/golang.org/x/sys/windows/svc/sys_386.s
generated
vendored
@ -1,68 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
// func servicemain(argc uint32, argv **uint16)
|
|
||||||
TEXT ·servicemain(SB),7,$0
|
|
||||||
MOVL argc+0(FP), AX
|
|
||||||
MOVL AX, ·sArgc(SB)
|
|
||||||
MOVL argv+4(FP), AX
|
|
||||||
MOVL AX, ·sArgv(SB)
|
|
||||||
|
|
||||||
PUSHL BP
|
|
||||||
PUSHL BX
|
|
||||||
PUSHL SI
|
|
||||||
PUSHL DI
|
|
||||||
|
|
||||||
SUBL $12, SP
|
|
||||||
|
|
||||||
MOVL ·sName(SB), AX
|
|
||||||
MOVL AX, (SP)
|
|
||||||
MOVL $·servicectlhandler(SB), AX
|
|
||||||
MOVL AX, 4(SP)
|
|
||||||
MOVL $0, 8(SP)
|
|
||||||
MOVL ·cRegisterServiceCtrlHandlerExW(SB), AX
|
|
||||||
MOVL SP, BP
|
|
||||||
CALL AX
|
|
||||||
MOVL BP, SP
|
|
||||||
CMPL AX, $0
|
|
||||||
JE exit
|
|
||||||
MOVL AX, ·ssHandle(SB)
|
|
||||||
|
|
||||||
MOVL ·goWaitsH(SB), AX
|
|
||||||
MOVL AX, (SP)
|
|
||||||
MOVL ·cSetEvent(SB), AX
|
|
||||||
MOVL SP, BP
|
|
||||||
CALL AX
|
|
||||||
MOVL BP, SP
|
|
||||||
|
|
||||||
MOVL ·cWaitsH(SB), AX
|
|
||||||
MOVL AX, (SP)
|
|
||||||
MOVL $-1, AX
|
|
||||||
MOVL AX, 4(SP)
|
|
||||||
MOVL ·cWaitForSingleObject(SB), AX
|
|
||||||
MOVL SP, BP
|
|
||||||
CALL AX
|
|
||||||
MOVL BP, SP
|
|
||||||
|
|
||||||
exit:
|
|
||||||
ADDL $12, SP
|
|
||||||
|
|
||||||
POPL DI
|
|
||||||
POPL SI
|
|
||||||
POPL BX
|
|
||||||
POPL BP
|
|
||||||
|
|
||||||
MOVL 0(SP), CX
|
|
||||||
ADDL $12, SP
|
|
||||||
JMP CX
|
|
||||||
|
|
||||||
// I do not know why, but this seems to be the only way to call
|
|
||||||
// ctlHandlerProc on Windows 7.
|
|
||||||
|
|
||||||
// func servicectlhandler(ctl uint32, evtype uint32, evdata uintptr, context uintptr) uintptr {
|
|
||||||
TEXT ·servicectlhandler(SB),7,$0
|
|
||||||
MOVL ·ctlHandlerExProc(SB), CX
|
|
||||||
JMP CX
|
|
42
vendor/golang.org/x/sys/windows/svc/sys_amd64.s
generated
vendored
42
vendor/golang.org/x/sys/windows/svc/sys_amd64.s
generated
vendored
@ -1,42 +0,0 @@
|
|||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
// func servicemain(argc uint32, argv **uint16)
|
|
||||||
TEXT ·servicemain(SB),7,$0
|
|
||||||
MOVL CX, ·sArgc(SB)
|
|
||||||
MOVL DX, ·sArgv(SB)
|
|
||||||
|
|
||||||
SUBQ $32, SP // stack for the first 4 syscall params
|
|
||||||
|
|
||||||
MOVQ ·sName(SB), CX
|
|
||||||
MOVQ $·servicectlhandler(SB), DX
|
|
||||||
// BUG(pastarmovj): Figure out a way to pass in context in R8.
|
|
||||||
MOVQ ·cRegisterServiceCtrlHandlerExW(SB), AX
|
|
||||||
CALL AX
|
|
||||||
CMPQ AX, $0
|
|
||||||
JE exit
|
|
||||||
MOVQ AX, ·ssHandle(SB)
|
|
||||||
|
|
||||||
MOVQ ·goWaitsH(SB), CX
|
|
||||||
MOVQ ·cSetEvent(SB), AX
|
|
||||||
CALL AX
|
|
||||||
|
|
||||||
MOVQ ·cWaitsH(SB), CX
|
|
||||||
MOVQ $4294967295, DX
|
|
||||||
MOVQ ·cWaitForSingleObject(SB), AX
|
|
||||||
CALL AX
|
|
||||||
|
|
||||||
exit:
|
|
||||||
ADDQ $32, SP
|
|
||||||
RET
|
|
||||||
|
|
||||||
// I do not know why, but this seems to be the only way to call
|
|
||||||
// ctlHandlerProc on Windows 7.
|
|
||||||
|
|
||||||
// func ·servicectlhandler(ctl uint32, evtype uint32, evdata uintptr, context uintptr) uintptr {
|
|
||||||
TEXT ·servicectlhandler(SB),7,$0
|
|
||||||
MOVQ ·ctlHandlerExProc(SB), AX
|
|
||||||
JMP AX
|
|
129
vendor/k8s.io/kubernetes/build/README.md
generated
vendored
129
vendor/k8s.io/kubernetes/build/README.md
generated
vendored
@ -1,129 +0,0 @@
|
|||||||
# Building Kubernetes
|
|
||||||
|
|
||||||
Building Kubernetes is easy if you take advantage of the containerized build environment. This document will help guide you through understanding this build process.
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
1. Docker, using one of the following configurations:
|
|
||||||
* **macOS** You can either use Docker for Mac or docker-machine. See installation instructions [here](https://docs.docker.com/docker-for-mac/).
|
|
||||||
**Note**: You will want to set the Docker VM to have at least 4.5GB of initial memory or building will likely fail. (See: [#11852]( http://issue.k8s.io/11852)).
|
|
||||||
* **Linux with local Docker** Install Docker according to the [instructions](https://docs.docker.com/installation/#installation) for your OS.
|
|
||||||
* **Remote Docker engine** Use a big machine in the cloud to build faster. This is a little trickier so look at the section later on.
|
|
||||||
2. **Optional** [Google Cloud SDK](https://developers.google.com/cloud/sdk/)
|
|
||||||
|
|
||||||
You must install and configure Google Cloud SDK if you want to upload your release to Google Cloud Storage and may safely omit this otherwise.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
While it is possible to build Kubernetes using a local golang installation, we have a build process that runs in a Docker container. This simplifies initial set up and provides for a very consistent build and test environment.
|
|
||||||
|
|
||||||
## Key scripts
|
|
||||||
|
|
||||||
The following scripts are found in the `build/` directory. Note that all scripts must be run from the Kubernetes root directory.
|
|
||||||
|
|
||||||
* `build/run.sh`: Run a command in a build docker container. Common invocations:
|
|
||||||
* `build/run.sh make`: Build just linux binaries in the container. Pass options and packages as necessary.
|
|
||||||
* `build/run.sh make cross`: Build all binaries for all platforms
|
|
||||||
* `build/run.sh make test`: Run all unit tests
|
|
||||||
* `build/run.sh make test-integration`: Run integration test
|
|
||||||
* `build/run.sh make test-cmd`: Run CLI tests
|
|
||||||
* `build/copy-output.sh`: This will copy the contents of `_output/dockerized/bin` from the Docker container to the local `_output/dockerized/bin`. It will also copy out specific file patterns that are generated as part of the build process. This is run automatically as part of `build/run.sh`.
|
|
||||||
* `build/make-clean.sh`: Clean out the contents of `_output`, remove any locally built container images and remove the data container.
|
|
||||||
* `/build/shell.sh`: Drop into a `bash` shell in a build container with a snapshot of the current repo code.
|
|
||||||
|
|
||||||
## Basic Flow
|
|
||||||
|
|
||||||
The scripts directly under `build/` are used to build and test. They will ensure that the `kube-build` Docker image is built (based on `build/build-image/Dockerfile`) and then execute the appropriate command in that container. These scripts will both ensure that the right data is cached from run to run for incremental builds and will copy the results back out of the container.
|
|
||||||
|
|
||||||
The `kube-build` container image is built by first creating a "context" directory in `_output/images/build-image`. It is done there instead of at the root of the Kubernetes repo to minimize the amount of data we need to package up when building the image.
|
|
||||||
|
|
||||||
There are 3 different containers instances that are run from this image. The first is a "data" container to store all data that needs to persist across to support incremental builds. Next there is an "rsync" container that is used to transfer data in and out to the data container. Lastly there is a "build" container that is used for actually doing build actions. The data container persists across runs while the rsync and build containers are deleted after each use.
|
|
||||||
|
|
||||||
`rsync` is used transparently behind the scenes to efficiently move data in and out of the container. This will use an ephemeral port picked by Docker. You can modify this by setting the `KUBE_RSYNC_PORT` env variable.
|
|
||||||
|
|
||||||
All Docker names are suffixed with a hash derived from the file path (to allow concurrent usage on things like CI machines) and a version number. When the version number changes all state is cleared and clean build is started. This allows the build infrastructure to be changed and signal to CI systems that old artifacts need to be deleted.
|
|
||||||
|
|
||||||
## Proxy Settings
|
|
||||||
|
|
||||||
If you are behind a proxy and you are letting these scripts use `docker-machine` to set up your local VM for you on macOS, you need to export proxy settings for Kubernetes build, the following environment variables should be defined.
|
|
||||||
|
|
||||||
```
|
|
||||||
export KUBERNETES_HTTP_PROXY=http://username:password@proxyaddr:proxyport
|
|
||||||
export KUBERNETES_HTTPS_PROXY=https://username:password@proxyaddr:proxyport
|
|
||||||
```
|
|
||||||
|
|
||||||
Optionally, you can specify addresses of no proxy for Kubernetes build, for example
|
|
||||||
|
|
||||||
```
|
|
||||||
export KUBERNETES_NO_PROXY=127.0.0.1
|
|
||||||
```
|
|
||||||
|
|
||||||
If you are using sudo to make Kubernetes build for example make quick-release, you need run `sudo -E make quick-release` to pass the environment variables.
|
|
||||||
|
|
||||||
## Really Remote Docker Engine
|
|
||||||
|
|
||||||
It is possible to use a Docker Engine that is running remotely (under your desk or in the cloud). Docker must be configured to connect to that machine and the local rsync port must be forwarded (via SSH or nc) from localhost to the remote machine.
|
|
||||||
|
|
||||||
To do this easily with GCE and `docker-machine`, do something like this:
|
|
||||||
```
|
|
||||||
# Create the remote docker machine on GCE. This is a pretty beefy machine with SSD disk.
|
|
||||||
KUBE_BUILD_VM=k8s-build
|
|
||||||
KUBE_BUILD_GCE_PROJECT=<project>
|
|
||||||
docker-machine create \
|
|
||||||
--driver=google \
|
|
||||||
--google-project=${KUBE_BUILD_GCE_PROJECT} \
|
|
||||||
--google-zone=us-west1-a \
|
|
||||||
--google-machine-type=n1-standard-8 \
|
|
||||||
--google-disk-size=50 \
|
|
||||||
--google-disk-type=pd-ssd \
|
|
||||||
${KUBE_BUILD_VM}
|
|
||||||
|
|
||||||
# Set up local docker to talk to that machine
|
|
||||||
eval $(docker-machine env ${KUBE_BUILD_VM})
|
|
||||||
|
|
||||||
# Pin down the port that rsync will be exposed on on the remote machine
|
|
||||||
export KUBE_RSYNC_PORT=8730
|
|
||||||
|
|
||||||
# forward local 8730 to that machine so that rsync works
|
|
||||||
docker-machine ssh ${KUBE_BUILD_VM} -L ${KUBE_RSYNC_PORT}:localhost:${KUBE_RSYNC_PORT} -N &
|
|
||||||
```
|
|
||||||
|
|
||||||
Look at `docker-machine stop`, `docker-machine start` and `docker-machine rm` to manage this VM.
|
|
||||||
|
|
||||||
## Releasing
|
|
||||||
|
|
||||||
The `build/release.sh` script will build a release. It will build binaries, run tests, (optionally) build runtime Docker images.
|
|
||||||
|
|
||||||
The main output is a tar file: `kubernetes.tar.gz`. This includes:
|
|
||||||
* Cross compiled client utilities.
|
|
||||||
* Script (`kubectl`) for picking and running the right client binary based on platform.
|
|
||||||
* Examples
|
|
||||||
* Cluster deployment scripts for various clouds
|
|
||||||
* Tar file containing all server binaries
|
|
||||||
|
|
||||||
In addition, there are some other tar files that are created:
|
|
||||||
* `kubernetes-client-*.tar.gz` Client binaries for a specific platform.
|
|
||||||
* `kubernetes-server-*.tar.gz` Server binaries for a specific platform.
|
|
||||||
|
|
||||||
When building final release tars, they are first staged into `_output/release-stage` before being tar'd up and put into `_output/release-tars`.
|
|
||||||
|
|
||||||
## Reproducibility
|
|
||||||
`make release`, its variant `make quick-release`, and Bazel all provide a
|
|
||||||
hermetic build environment which should provide some level of reproducibility
|
|
||||||
for builds. `make` itself is **not** hermetic.
|
|
||||||
|
|
||||||
The Kubernetes build environment supports the [`SOURCE_DATE_EPOCH` environment
|
|
||||||
variable](https://reproducible-builds.org/specs/source-date-epoch/) specified by
|
|
||||||
the Reproducible Builds project, which can be set to a UNIX epoch timestamp.
|
|
||||||
This will be used for the build timestamps embedded in compiled Go binaries,
|
|
||||||
and maybe someday also Docker images.
|
|
||||||
|
|
||||||
One reasonable setting for this variable is to use the commit timestamp from the
|
|
||||||
tip of the tree being built; this is what the Kubernetes CI system uses. For
|
|
||||||
example, you could use the following one-liner:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
SOURCE_DATE_EPOCH=$(git show -s --format=format:%ct HEAD)
|
|
||||||
```
|
|
||||||
|
|
||||||
[]()
|
|
36
vendor/k8s.io/kubernetes/build/pause/orphan.c
generated
vendored
36
vendor/k8s.io/kubernetes/build/pause/orphan.c
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2016 The Kubernetes 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Creates a zombie to be reaped by init. Useful for testing. */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
pid_t pid;
|
|
||||||
pid = fork();
|
|
||||||
if (pid == 0) {
|
|
||||||
while (getppid() > 1)
|
|
||||||
;
|
|
||||||
printf("Child exiting: pid=%d ppid=%d\n", getpid(), getppid());
|
|
||||||
return 0;
|
|
||||||
} else if (pid > 0) {
|
|
||||||
printf("Parent exiting: pid=%d ppid=%d\n", getpid(), getppid());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
perror("Could not create child");
|
|
||||||
return 1;
|
|
||||||
}
|
|
68
vendor/k8s.io/kubernetes/build/pause/pause.c
generated
vendored
68
vendor/k8s.io/kubernetes/build/pause/pause.c
generated
vendored
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2016 The Kubernetes 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#define STRINGIFY(x) #x
|
|
||||||
#define VERSION_STRING(x) STRINGIFY(x)
|
|
||||||
|
|
||||||
#ifndef VERSION
|
|
||||||
#define VERSION HEAD
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void sigdown(int signo) {
|
|
||||||
psignal(signo, "Shutting down, got signal");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sigreap(int signo) {
|
|
||||||
while (waitpid(-1, NULL, WNOHANG) > 0)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
int i;
|
|
||||||
for (i = 1; i < argc; ++i) {
|
|
||||||
if (!strcasecmp(argv[i], "-v")) {
|
|
||||||
printf("pause.c %s\n", VERSION_STRING(VERSION));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getpid() != 1)
|
|
||||||
/* Not an error because pause sees use outside of infra containers. */
|
|
||||||
fprintf(stderr, "Warning: pause should be the first process\n");
|
|
||||||
|
|
||||||
if (sigaction(SIGINT, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)
|
|
||||||
return 1;
|
|
||||||
if (sigaction(SIGTERM, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0)
|
|
||||||
return 2;
|
|
||||||
if (sigaction(SIGCHLD, &(struct sigaction){.sa_handler = sigreap,
|
|
||||||
.sa_flags = SA_NOCLDSTOP},
|
|
||||||
NULL) < 0)
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
pause();
|
|
||||||
fprintf(stderr, "Error: infinite loop terminated\n");
|
|
||||||
return 42;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user