mirror of https://github.com/k3s-io/k3s
commit
b5217e2888
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
"github.com/natefinch/lumberjack"
|
||||
"github.com/opencontainers/runc/libcontainer/system"
|
||||
util2 "github.com/rancher/k3s/pkg/agent/util"
|
||||
"github.com/rancher/k3s/pkg/daemons/config"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -27,10 +28,15 @@ const (
|
|||
maxMsgSize = 1024 * 1024 * 16
|
||||
configToml = `
|
||||
[plugins.opt]
|
||||
path = "%OPT%"
|
||||
path = "%OPT%"
|
||||
[plugins.cri]
|
||||
stream_server_address = "%NODE%"
|
||||
stream_server_port = "10010"
|
||||
`
|
||||
configUserNSToml = `
|
||||
disable_cgroup = true
|
||||
disable_apparmor = true
|
||||
restrict_oom_score_adj = true
|
||||
`
|
||||
configCNIToml = `
|
||||
[plugins.cri.cni]
|
||||
|
@ -49,6 +55,9 @@ func Run(ctx context.Context, cfg *config.Node) error {
|
|||
}
|
||||
|
||||
template := configToml
|
||||
if system.RunningInUserNS() {
|
||||
template += configUserNSToml
|
||||
}
|
||||
if !cfg.NoFlannel {
|
||||
template += configCNIToml
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/rancher/k3s/pkg/agent/tunnel"
|
||||
"github.com/rancher/k3s/pkg/cli/cmds"
|
||||
"github.com/rancher/k3s/pkg/daemons/agent"
|
||||
"github.com/rancher/k3s/pkg/rootless"
|
||||
"github.com/rancher/norman/pkg/clientaccess"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -69,6 +70,12 @@ func Run(ctx context.Context, cfg cmds.Agent) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if cfg.Rootless {
|
||||
if err := rootless.Rootless(cfg.DataDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cfg.DataDir = filepath.Join(cfg.DataDir, "agent")
|
||||
|
||||
if cfg.ClusterSecret != "" {
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
"github.com/rancher/k3s/pkg/agent"
|
||||
"github.com/rancher/k3s/pkg/cli/cmds"
|
||||
"github.com/rancher/norman/pkg/resolvehome"
|
||||
"github.com/rancher/k3s/pkg/datadir"
|
||||
"github.com/rancher/norman/signal"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
|
@ -57,7 +57,7 @@ func Run(ctx *cli.Context) error {
|
|||
|
||||
logrus.Infof("Starting k3s agent %s", ctx.App.Version)
|
||||
|
||||
dataDir, err := resolvehome.Resolve(cmds.AgentConfig.DataDir)
|
||||
dataDir, err := datadir.LocalHome(cmds.AgentConfig.DataDir, cmds.AgentConfig.Rootless)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ type Agent struct {
|
|||
ContainerRuntimeEndpoint string
|
||||
NoFlannel bool
|
||||
Debug bool
|
||||
Rootless bool
|
||||
AgentShared
|
||||
ExtraKubeletArgs cli.StringSlice
|
||||
ExtraKubeProxyArgs cli.StringSlice
|
||||
|
@ -113,6 +114,11 @@ func NewAgentCommand(action func(ctx *cli.Context) error) cli.Command {
|
|||
Destination: &AgentConfig.ClusterSecret,
|
||||
EnvVar: "K3S_CLUSTER_SECRET",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "rootless",
|
||||
Usage: "(experimental) Run rootless",
|
||||
Destination: &AgentConfig.Rootless,
|
||||
},
|
||||
DockerFlag,
|
||||
FlannelFlag,
|
||||
NodeNameFlag,
|
||||
|
|
|
@ -21,6 +21,7 @@ type Server struct {
|
|||
ExtraAPIArgs cli.StringSlice
|
||||
ExtraSchedulerArgs cli.StringSlice
|
||||
ExtraControllerArgs cli.StringSlice
|
||||
Rootless bool
|
||||
}
|
||||
|
||||
var ServerConfig Server
|
||||
|
@ -124,6 +125,11 @@ func NewServerCommand(action func(*cli.Context) error) cli.Command {
|
|||
Usage: "Customized flag for kube-controller-manager process",
|
||||
Value: &ServerConfig.ExtraControllerArgs,
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "rootless",
|
||||
Usage: "(experimental) Run rootless",
|
||||
Destination: &ServerConfig.Rootless,
|
||||
},
|
||||
NodeIPFlag,
|
||||
NodeNameFlag,
|
||||
DockerFlag,
|
||||
|
|
|
@ -15,12 +15,14 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
"github.com/rancher/k3s/pkg/agent"
|
||||
"github.com/rancher/k3s/pkg/cli/cmds"
|
||||
"github.com/rancher/k3s/pkg/datadir"
|
||||
"github.com/rancher/k3s/pkg/rootless"
|
||||
"github.com/rancher/k3s/pkg/server"
|
||||
"github.com/rancher/norman/signal"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
"k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/csi"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3" // ensure we have sqlite
|
||||
)
|
||||
|
@ -67,18 +69,30 @@ func run(app *cli.Context, cfg *cmds.Server) error {
|
|||
|
||||
setupLogging(app)
|
||||
|
||||
if !cfg.DisableAgent && os.Getuid() != 0 {
|
||||
if !cfg.DisableAgent && os.Getuid() != 0 && !cfg.Rootless {
|
||||
return fmt.Errorf("must run as root unless --disable-agent is specified")
|
||||
}
|
||||
|
||||
if cfg.Rootless {
|
||||
dataDir, err := datadir.LocalHome(cfg.DataDir, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.DataDir = dataDir
|
||||
if err := rootless.Rootless(dataDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// If running agent in server, set this so that CSI initializes properly
|
||||
volume.WaitForValidHost = !cfg.DisableAgent
|
||||
csi.WaitForValidHostName = !cfg.DisableAgent
|
||||
|
||||
serverConfig := server.Config{}
|
||||
serverConfig.ControlConfig.ClusterSecret = cfg.ClusterSecret
|
||||
serverConfig.ControlConfig.DataDir = cfg.DataDir
|
||||
serverConfig.ControlConfig.KubeConfigOutput = cfg.KubeConfigOutput
|
||||
serverConfig.ControlConfig.KubeConfigMode = cfg.KubeConfigMode
|
||||
serverConfig.Rootless = cfg.Rootless
|
||||
serverConfig.TLSConfig.HTTPSPort = cfg.HTTPSPort
|
||||
serverConfig.TLSConfig.HTTPPort = cfg.HTTPPort
|
||||
serverConfig.TLSConfig.KnownIPs = knownIPs(cfg.KnownIPs)
|
||||
|
|
|
@ -9,12 +9,14 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/system"
|
||||
"github.com/rancher/k3s/pkg/daemons/config"
|
||||
"github.com/sirupsen/logrus"
|
||||
"k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/component-base/logs"
|
||||
app2 "k8s.io/kubernetes/cmd/kube-proxy/app"
|
||||
"k8s.io/kubernetes/cmd/kubelet/app"
|
||||
|
||||
_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
|
||||
_ "k8s.io/kubernetes/pkg/version/prometheus" // for version metric registration
|
||||
)
|
||||
|
@ -107,8 +109,11 @@ func kubelet(cfg *config.Agent) {
|
|||
argsMap["runtime-cgroups"] = root
|
||||
argsMap["kubelet-cgroups"] = root
|
||||
}
|
||||
args := config.GetArgsList(argsMap, cfg.ExtraKubeletArgs)
|
||||
if system.RunningInUserNS() {
|
||||
argsMap["feature-gates"] = "DevicePlugins=false"
|
||||
}
|
||||
|
||||
args := config.GetArgsList(argsMap, cfg.ExtraKubeletArgs)
|
||||
command.SetArgs(args)
|
||||
|
||||
go func() {
|
||||
|
|
|
@ -15,8 +15,12 @@ const (
|
|||
)
|
||||
|
||||
func Resolve(dataDir string) (string, error) {
|
||||
return LocalHome(dataDir, false)
|
||||
}
|
||||
|
||||
func LocalHome(dataDir string, forceLocal bool) (string, error) {
|
||||
if dataDir == "" {
|
||||
if os.Getuid() == 0 {
|
||||
if os.Getuid() == 0 && !forceLocal {
|
||||
dataDir = DefaultDataDir
|
||||
} else {
|
||||
dataDir = DefaultHomeDataDir
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
func Main() {
|
||||
kubenv := os.Getenv("KUBECONFIG")
|
||||
if kubenv == "" {
|
||||
config, err := server.HomeKubeConfig(false)
|
||||
config, err := server.HomeKubeConfig(false, false)
|
||||
if _, serr := os.Stat(config); err == nil && serr == nil {
|
||||
os.Setenv("KUBECONFIG", config)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package rootless
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func setupMounts(stateDir string) error {
|
||||
mountMap := [][]string{
|
||||
{"/run", ""},
|
||||
{"/var/run", ""},
|
||||
{"/var/log", filepath.Join(stateDir, "logs")},
|
||||
{"/var/lib/cni", filepath.Join(stateDir, "cni")},
|
||||
}
|
||||
|
||||
for _, v := range mountMap {
|
||||
if err := setupMount(v[0], v[1]); err != nil {
|
||||
return errors.Wrapf(err, "failed to setup mount %s => %s", v[0], v[1])
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupMount(target, dir string) error {
|
||||
toCreate := target
|
||||
for {
|
||||
if toCreate == "/" {
|
||||
return fmt.Errorf("missing /%s on the root filesystem", strings.Split(target, "/")[0])
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(toCreate, 0700); err == nil {
|
||||
break
|
||||
}
|
||||
|
||||
toCreate = filepath.Base(toCreate)
|
||||
}
|
||||
|
||||
logrus.Debug("Mounting none ", toCreate, " tmpfs")
|
||||
if err := unix.Mount("none", toCreate, "tmpfs", 0, ""); err != nil {
|
||||
return errors.Wrapf(err, "failed to mount tmpfs to %s", toCreate)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(target, 0700); err != nil {
|
||||
return errors.Wrapf(err, "failed to create directory %s")
|
||||
}
|
||||
|
||||
if dir == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||
return errors.Wrapf(err, "failed to create directory %s")
|
||||
}
|
||||
|
||||
logrus.Debug("Mounting ", dir, target, " none bind")
|
||||
return unix.Mount(dir, target, "none", unix.MS_BIND, "")
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
package rootless
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/child"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/copyup/tmpfssymlink"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/network/slirp4netns"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/parent"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port/socat"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
pipeFD = "_K3S_ROOTLESS_FD"
|
||||
childEnv = "_K3S_ROOTLESS_SOCK"
|
||||
Sock = ""
|
||||
)
|
||||
|
||||
func Rootless(stateDir string) error {
|
||||
defer func() {
|
||||
os.Unsetenv(pipeFD)
|
||||
os.Unsetenv(childEnv)
|
||||
}()
|
||||
|
||||
hasFD := os.Getenv(pipeFD) != ""
|
||||
hasChildEnv := os.Getenv(childEnv) != ""
|
||||
|
||||
if hasFD {
|
||||
logrus.Debug("Running rootless child")
|
||||
childOpt, err := createChildOpt()
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
if err := child.Child(*childOpt); err != nil {
|
||||
logrus.Fatal("child died", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hasChildEnv {
|
||||
Sock = os.Getenv(childEnv)
|
||||
logrus.Debug("Running rootless process")
|
||||
return setupMounts(stateDir)
|
||||
}
|
||||
|
||||
logrus.Debug("Running rootless parent")
|
||||
parentOpt, err := createParentOpt(filepath.Join(stateDir, "rootless"))
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
|
||||
os.Setenv(childEnv, filepath.Join(parentOpt.StateDir, parent.StateFileAPISock))
|
||||
if err := parent.Parent(*parentOpt); err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
os.Exit(0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseCIDR(s string) (*net.IPNet, error) {
|
||||
if s == "" {
|
||||
return nil, nil
|
||||
}
|
||||
ip, ipnet, err := net.ParseCIDR(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ip.Equal(ipnet.IP) {
|
||||
return nil, errors.Errorf("cidr must be like 10.0.2.0/24, not like 10.0.2.100/24")
|
||||
}
|
||||
return ipnet, nil
|
||||
}
|
||||
|
||||
func createParentOpt(stateDir string) (*parent.Opt, error) {
|
||||
if err := os.MkdirAll(stateDir, 0755); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to mkdir %s", stateDir)
|
||||
}
|
||||
|
||||
stateDir, err := ioutil.TempDir("", "rootless")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
opt := &parent.Opt{
|
||||
StateDir: stateDir,
|
||||
}
|
||||
|
||||
mtu := 0
|
||||
ipnet, err := parseCIDR("10.41.0.0/16")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disableHostLoopback := true
|
||||
binary := "slirp4netns"
|
||||
if _, err := exec.LookPath(binary); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opt.NetworkDriver = slirp4netns.NewParentDriver(binary, mtu, ipnet, disableHostLoopback, "")
|
||||
opt.PortDriver, err = socat.NewParentDriver(&logrusDebugWriter{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
opt.PipeFDEnvKey = pipeFD
|
||||
|
||||
return opt, nil
|
||||
}
|
||||
|
||||
type logrusDebugWriter struct {
|
||||
}
|
||||
|
||||
func (w *logrusDebugWriter) Write(p []byte) (int, error) {
|
||||
s := strings.TrimSuffix(string(p), "\n")
|
||||
logrus.Debug(s)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func createChildOpt() (*child.Opt, error) {
|
||||
opt := &child.Opt{}
|
||||
opt.TargetCmd = os.Args
|
||||
opt.PipeFDEnvKey = pipeFD
|
||||
opt.NetworkDriver = slirp4netns.NewChildDriver()
|
||||
opt.CopyUpDirs = []string{"/etc", "/run"}
|
||||
opt.CopyUpDriver = tmpfssymlink.NewChildDriver()
|
||||
return opt, nil
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
package rootlessports
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/rancher/k3s/pkg/rootless"
|
||||
coreClients "github.com/rancher/k3s/types/apis/core/v1"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/api/client"
|
||||
"github.com/rootless-containers/rootlesskit/pkg/port"
|
||||
"github.com/sirupsen/logrus"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
all = "_all_"
|
||||
)
|
||||
|
||||
func Register(ctx context.Context, httpsPort int) error {
|
||||
var (
|
||||
err error
|
||||
rootlessClient client.Client
|
||||
)
|
||||
|
||||
if rootless.Sock == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
coreClients := coreClients.ClientsFrom(ctx)
|
||||
for i := 0; i < 30; i++ {
|
||||
rootlessClient, err = client.New(rootless.Sock)
|
||||
if err == nil {
|
||||
break
|
||||
} else {
|
||||
logrus.Infof("waiting for rootless API socket %s: %v", rootless.Sock, err)
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h := &handler{
|
||||
rootlessClient: rootlessClient,
|
||||
serviceClient: coreClients.Service,
|
||||
serviceCache: coreClients.Service.Cache(),
|
||||
httpsPort: httpsPort,
|
||||
ctx: ctx,
|
||||
}
|
||||
coreClients.Service.Interface().Controller().AddHandler(ctx, "rootlessports", h.serviceChanged)
|
||||
coreClients.Service.Enqueue("", all)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
rootlessClient client.Client
|
||||
serviceClient coreClients.ServiceClient
|
||||
serviceCache coreClients.ServiceClientCache
|
||||
httpsPort int
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (h *handler) serviceChanged(key string, svc *v1.Service) (runtime.Object, error) {
|
||||
if key != all {
|
||||
h.serviceClient.Enqueue("", all)
|
||||
return svc, nil
|
||||
}
|
||||
|
||||
ports, err := h.rootlessClient.PortManager().ListPorts(h.ctx)
|
||||
if err != nil {
|
||||
return svc, err
|
||||
}
|
||||
|
||||
boundPorts := map[int]int{}
|
||||
for _, port := range ports {
|
||||
boundPorts[port.Spec.ParentPort] = port.ID
|
||||
}
|
||||
|
||||
toBindPort, err := h.toBindPorts()
|
||||
if err != nil {
|
||||
return svc, err
|
||||
}
|
||||
|
||||
for bindPort, childBindPort := range toBindPort {
|
||||
if _, ok := boundPorts[bindPort]; ok {
|
||||
logrus.Debugf("Parent port %d to child already bound", bindPort)
|
||||
delete(boundPorts, bindPort)
|
||||
continue
|
||||
}
|
||||
|
||||
status, err := h.rootlessClient.PortManager().AddPort(h.ctx, port.Spec{
|
||||
Proto: "tcp",
|
||||
ParentPort: bindPort,
|
||||
ChildPort: childBindPort,
|
||||
})
|
||||
if err != nil {
|
||||
return svc, err
|
||||
}
|
||||
|
||||
logrus.Infof("Bound parent port %s:%d to child namespace port %d", status.Spec.ParentIP,
|
||||
status.Spec.ParentPort, status.Spec.ChildPort)
|
||||
}
|
||||
|
||||
for bindPort, id := range boundPorts {
|
||||
if err := h.rootlessClient.PortManager().RemovePort(h.ctx, id); err != nil {
|
||||
return svc, err
|
||||
}
|
||||
|
||||
logrus.Infof("Removed parent port %d to child namespace", bindPort)
|
||||
}
|
||||
|
||||
return svc, nil
|
||||
}
|
||||
|
||||
func (h *handler) toBindPorts() (map[int]int, error) {
|
||||
svcs, err := h.serviceCache.List("", labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
toBindPorts := map[int]int{
|
||||
h.httpsPort: h.httpsPort,
|
||||
}
|
||||
for _, svc := range svcs {
|
||||
for _, ingress := range svc.Status.LoadBalancer.Ingress {
|
||||
if ingress.IP == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, port := range svc.Spec.Ports {
|
||||
if port.Protocol != v1.ProtocolTCP {
|
||||
continue
|
||||
}
|
||||
|
||||
if port.Port != 0 {
|
||||
if port.Port <= 1024 {
|
||||
toBindPorts[10000+int(port.Port)] = int(port.Port)
|
||||
} else {
|
||||
toBindPorts[int(port.Port)] = int(port.Port)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return toBindPorts, nil
|
||||
}
|
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/rancher/k3s/pkg/datadir"
|
||||
"github.com/rancher/k3s/pkg/deploy"
|
||||
"github.com/rancher/k3s/pkg/helm"
|
||||
"github.com/rancher/k3s/pkg/rootlessports"
|
||||
"github.com/rancher/k3s/pkg/servicelb"
|
||||
"github.com/rancher/k3s/pkg/static"
|
||||
"github.com/rancher/k3s/pkg/tls"
|
||||
|
@ -36,16 +37,8 @@ import (
|
|||
)
|
||||
|
||||
func resolveDataDir(dataDir string) (string, error) {
|
||||
if dataDir == "" {
|
||||
if os.Getuid() == 0 {
|
||||
dataDir = "/var/lib/rancher/k3s"
|
||||
} else {
|
||||
dataDir = "${HOME}/.rancher/k3s"
|
||||
}
|
||||
}
|
||||
|
||||
dataDir = filepath.Join(dataDir, "server")
|
||||
return resolvehome.Resolve(dataDir)
|
||||
dataDir, err := datadir.Resolve(dataDir)
|
||||
return filepath.Join(dataDir, "server"), err
|
||||
}
|
||||
|
||||
func StartServer(ctx context.Context, config *Config) (string, error) {
|
||||
|
@ -72,7 +65,7 @@ func StartServer(ctx context.Context, config *Config) (string, error) {
|
|||
}
|
||||
printTokens(certs, ip.String(), &config.TLSConfig, &config.ControlConfig)
|
||||
|
||||
writeKubeConfig(certs, &config.TLSConfig, &config.ControlConfig)
|
||||
writeKubeConfig(certs, &config.TLSConfig, config)
|
||||
|
||||
return certs, nil
|
||||
}
|
||||
|
@ -121,7 +114,8 @@ func startNorman(ctx context.Context, config *Config) (string, error) {
|
|||
MasterControllers: []norman.ControllerRegister{
|
||||
helm.Register,
|
||||
func(ctx context.Context) error {
|
||||
return servicelb.Register(ctx, norman.GetServer(ctx).K8sClient, !config.DisableServiceLB)
|
||||
return servicelb.Register(ctx, norman.GetServer(ctx).K8sClient, !config.DisableServiceLB,
|
||||
config.Rootless)
|
||||
},
|
||||
func(ctx context.Context) error {
|
||||
dataDir := filepath.Join(controlConfig.DataDir, "static")
|
||||
|
@ -138,6 +132,12 @@ func startNorman(ctx context.Context, config *Config) (string, error) {
|
|||
}
|
||||
return nil
|
||||
},
|
||||
func(ctx context.Context) error {
|
||||
if !config.DisableServiceLB && config.Rootless {
|
||||
return rootlessports.Register(ctx, config.TLSConfig.HTTPSPort)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -156,9 +156,9 @@ func startNorman(ctx context.Context, config *Config) (string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func HomeKubeConfig(write bool) (string, error) {
|
||||
func HomeKubeConfig(write, rootless bool) (string, error) {
|
||||
if write {
|
||||
if os.Getuid() == 0 {
|
||||
if os.Getuid() == 0 && !rootless {
|
||||
return datadir.GlobalConfig, nil
|
||||
}
|
||||
return resolvehome.Resolve(datadir.HomeConfig)
|
||||
|
@ -194,30 +194,30 @@ func printTokens(certs, advertiseIP string, tlsConfig *dynamiclistener.UserConfi
|
|||
|
||||
}
|
||||
|
||||
func writeKubeConfig(certs string, tlsConfig *dynamiclistener.UserConfig, config *config.Control) {
|
||||
clientToken := FormatToken(config.Runtime.ClientToken, certs)
|
||||
func writeKubeConfig(certs string, tlsConfig *dynamiclistener.UserConfig, config *Config) {
|
||||
clientToken := FormatToken(config.ControlConfig.Runtime.ClientToken, certs)
|
||||
ip := tlsConfig.BindAddress
|
||||
if ip == "" {
|
||||
ip = "localhost"
|
||||
}
|
||||
url := fmt.Sprintf("https://%s:%d", ip, tlsConfig.HTTPSPort)
|
||||
kubeConfig, err := HomeKubeConfig(true)
|
||||
kubeConfig, err := HomeKubeConfig(true, config.Rootless)
|
||||
def := true
|
||||
if err != nil {
|
||||
kubeConfig = filepath.Join(config.DataDir, "kubeconfig-k3s.yaml")
|
||||
kubeConfig = filepath.Join(config.ControlConfig.DataDir, "kubeconfig-k3s.yaml")
|
||||
def = false
|
||||
}
|
||||
|
||||
if config.KubeConfigOutput != "" {
|
||||
kubeConfig = config.KubeConfigOutput
|
||||
if config.ControlConfig.KubeConfigOutput != "" {
|
||||
kubeConfig = config.ControlConfig.KubeConfigOutput
|
||||
}
|
||||
|
||||
if err = clientaccess.AgentAccessInfoToKubeConfig(kubeConfig, url, clientToken); err != nil {
|
||||
logrus.Errorf("Failed to generate kubeconfig: %v", err)
|
||||
}
|
||||
|
||||
if config.KubeConfigMode != "" {
|
||||
mode, err := strconv.ParseInt(config.KubeConfigMode, 8, 0)
|
||||
if config.ControlConfig.KubeConfigMode != "" {
|
||||
mode, err := strconv.ParseInt(config.ControlConfig.KubeConfigMode, 8, 0)
|
||||
if err == nil {
|
||||
os.Chmod(kubeConfig, os.FileMode(mode))
|
||||
} else {
|
||||
|
|
|
@ -10,4 +10,5 @@ type Config struct {
|
|||
DisableServiceLB bool
|
||||
TLSConfig dynamiclistener.UserConfig
|
||||
ControlConfig config.Control
|
||||
Rootless bool
|
||||
}
|
||||
|
|
|
@ -34,11 +34,12 @@ var (
|
|||
trueVal = true
|
||||
)
|
||||
|
||||
func Register(ctx context.Context, kubernetes kubernetes.Interface, enabled bool) error {
|
||||
func Register(ctx context.Context, kubernetes kubernetes.Interface, enabled, rootless bool) error {
|
||||
clients := coreclient.ClientsFrom(ctx)
|
||||
appClients := appclient.ClientsFrom(ctx)
|
||||
|
||||
h := &handler{
|
||||
rootless: rootless,
|
||||
enabled: enabled,
|
||||
nodeCache: clients.Node.Cache(),
|
||||
podCache: clients.Pod.Cache(),
|
||||
|
@ -59,6 +60,7 @@ func Register(ctx context.Context, kubernetes kubernetes.Interface, enabled bool
|
|||
}
|
||||
|
||||
type handler struct {
|
||||
rootless bool
|
||||
enabled bool
|
||||
nodeCache coreclient.NodeClientCache
|
||||
podCache coreclient.PodClientCache
|
||||
|
@ -189,6 +191,11 @@ func (h *handler) podIPs(pods []*core.Pod) ([]string, error) {
|
|||
for k := range ips {
|
||||
ipList = append(ipList, k)
|
||||
}
|
||||
|
||||
if len(ipList) > 0 && h.rootless {
|
||||
return []string{"127.0.0.1"}, nil
|
||||
}
|
||||
|
||||
return ipList, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -5,4 +5,9 @@ mkdir -p $(dirname $0)/../bin
|
|||
cd $(dirname $0)/../bin
|
||||
|
||||
echo Running
|
||||
go run -tags "apparmor" ../main.go --debug server --disable-agent "$@"
|
||||
ARGS="--disable-agent"
|
||||
if echo -- "$@" | grep -q rootless; then
|
||||
ARGS=""
|
||||
PATH=$(pwd):$PATH
|
||||
fi
|
||||
go run -tags "apparmor" ../main.go server $ARGS "$@"
|
||||
|
|
|
@ -4,7 +4,7 @@ source $(dirname $0)/version.sh
|
|||
|
||||
cd $(dirname $0)/..
|
||||
|
||||
ROOT_VERSION=v0.0.1
|
||||
ROOT_VERSION=v0.1.1
|
||||
TRAEFIK_VERSION=1.64.0
|
||||
CHARTS_DIR=build/static/charts
|
||||
|
||||
|
|
261
trash.lock
261
trash.lock
|
@ -22,7 +22,8 @@ import:
|
|||
- package: github.com/containerd/continuity
|
||||
version: bd77b46c8352f74eb12c85bdc01f4b90f69d66b4
|
||||
- package: github.com/containerd/cri
|
||||
version: eb926cd79d3bac188dcc4ed7694fc9298f8831be
|
||||
version: v1.2-k3s.2
|
||||
repo: https://github.com/rancher/cri.git
|
||||
- package: github.com/containerd/fifo
|
||||
version: 3d5202aec260678c48179c56f40e6f38a095738c
|
||||
- package: github.com/containerd/go-cni
|
||||
|
@ -49,6 +50,8 @@ import:
|
|||
version: v1.1.0
|
||||
- package: github.com/docker/distribution
|
||||
version: 0d3efadf0154c2b8a4e7b6621fff9809655cc580
|
||||
- package: github.com/docker/docker
|
||||
version: c12f09bf99b54f274a5ae241dd154fa74020cbab
|
||||
- package: github.com/docker/go-events
|
||||
version: 9461782956ad83b30282bf90e31fa6a70c255ba9
|
||||
- package: github.com/docker/go-metrics
|
||||
|
@ -94,6 +97,8 @@ import:
|
|||
version: 1.0.3
|
||||
- package: github.com/modern-go/reflect2
|
||||
version: 1.0.1
|
||||
- package: github.com/morikuni/aec
|
||||
version: 39771216ff4c63d11f5e604076f9c45e8be1067b
|
||||
- package: github.com/natefinch/lumberjack
|
||||
version: aee4629129445bbdfb69aa565537dcfa16544311
|
||||
- package: github.com/opencontainers/go-digest
|
||||
|
@ -113,6 +118,8 @@ import:
|
|||
- package: github.com/rancher/norman
|
||||
version: 50017efee23caa79542ef685b65a7b783e0a73ca
|
||||
repo: https://github.com/ibuildthecloud/norman.git
|
||||
- package: github.com/rootless-containers/rootlesskit
|
||||
version: 893c1c3de71f54c301fdb85a7c0dd15c1933c159
|
||||
- package: github.com/seccomp/libseccomp-golang
|
||||
version: 32f571b70023028bd57d9288c20efbcb237f3ce0
|
||||
- package: github.com/sirupsen/logrus
|
||||
|
@ -121,6 +128,8 @@ import:
|
|||
version: db04d3cc01c8b54962a58ec7e491717d06cfcc16
|
||||
- package: github.com/tchap/go-patricia
|
||||
version: v2.2.6
|
||||
- package: github.com/theckman/go-flock
|
||||
version: v0.7.1
|
||||
- package: github.com/urfave/cli
|
||||
version: 8e01ec4cd3e2d84ab2fe90d8210528ffbb06d8ff
|
||||
- package: github.com/xeipuuv/gojsonpointer
|
||||
|
@ -155,148 +164,144 @@ import:
|
|||
- package: gopkg.in/yaml.v2
|
||||
version: v2.2.1
|
||||
- package: k8s.io/kubernetes
|
||||
version: v1.14.1-k3s.1
|
||||
version: v1.14.1-k3s.2
|
||||
repo: https://github.com/rancher/k3s.git
|
||||
transitive: true
|
||||
staging: true
|
||||
- package: vbom.ml/util
|
||||
version: db5cfe13f5cc80a4990d98e2e1b0707a4d1a5394
|
||||
- package: github.com/mxk/go-flowrate
|
||||
version: cca7078d478f8520f85629ad7c68962d31ed7682
|
||||
- package: github.com/ugorji/go
|
||||
version: bdcc60b419d136a85cdf2e7cbcac34b3f1cd6e57
|
||||
- package: github.com/sigma/go-inotify
|
||||
version: c87b6cf5033d2c6486046f045eeebdc3d910fd38
|
||||
- package: github.com/spf13/cobra
|
||||
version: v0.0.1-34-gc439c4fa093711
|
||||
- package: github.com/liggitt/tabwriter
|
||||
version: 89fcab3d43de07060e4fd4c1547430ed57e87f24
|
||||
- package: github.com/mindprince/gonvml
|
||||
version: fee913ce8fb235edf54739d259ca0ecc226c7b8a
|
||||
- package: github.com/mistifyio/go-zfs
|
||||
version: v2.1.1-5-g1b4ae6fb4e77b0
|
||||
- package: github.com/peterbourgon/diskv
|
||||
version: v2.0.1
|
||||
- package: github.com/russross/blackfriday
|
||||
version: v1.4-2-g300106c228d52c
|
||||
- package: github.com/inconshreveable/mousetrap
|
||||
version: v1.0
|
||||
- package: github.com/prometheus/client_model
|
||||
version: model-0.0.2-12-gfa8ad6fec33561
|
||||
- package: github.com/imdario/mergo
|
||||
version: v0.3.5
|
||||
- package: github.com/vishvananda/netns
|
||||
version: be1fbeda19366dea804f00efff2dd73a1642fdcc
|
||||
- package: github.com/prometheus/client_golang
|
||||
version: v0.9.2
|
||||
- package: github.com/mattn/go-shellwords
|
||||
version: v1.0.3-20-gf8471b0a71ded0
|
||||
- package: github.com/prometheus/procfs
|
||||
version: 65c1f6f8f0fc1e2185eb9863a3bc751496404259
|
||||
- package: github.com/fsnotify/fsnotify
|
||||
version: v1.3.1-1-gf12c6236fe7b5c
|
||||
- package: github.com/cloudflare/cfssl
|
||||
version: 1.3.2-21-g56268a613adfed
|
||||
- package: github.com/spf13/cobra
|
||||
version: v0.0.1-34-gc439c4fa093711
|
||||
- package: github.com/vishvananda/netlink
|
||||
version: b2de5d10e38ecce8607e6b438b6d174f389a004e
|
||||
- package: github.com/chai2010/gettext-go
|
||||
version: c6fed771bfd517099caf0f7a961671fa8ed08723
|
||||
- package: github.com/container-storage-interface/spec
|
||||
version: v1.1.0
|
||||
- package: github.com/hashicorp/golang-lru
|
||||
version: v0.5.0
|
||||
- package: github.com/spf13/pflag
|
||||
version: v1.0.1
|
||||
- package: github.com/google/certificate-transparency-go
|
||||
version: v1.0.21
|
||||
- package: github.com/coreos/pkg
|
||||
version: v4
|
||||
- package: vbom.ml/util
|
||||
version: db5cfe13f5cc80a4990d98e2e1b0707a4d1a5394
|
||||
- package: github.com/miekg/dns
|
||||
version: 5d001d020961ae1c184f9f8152fdc73810481677
|
||||
- package: github.com/munnerz/goautoneg
|
||||
version: a547fc61f48d567d5b4ec6f8aee5573d8efce11d
|
||||
- package: github.com/google/btree
|
||||
version: 7d79101e329e5a3adf994758c578dab82b90c017
|
||||
- package: github.com/karrick/godirwalk
|
||||
version: v1.7.5
|
||||
- package: github.com/coreos/etcd
|
||||
version: v3.3.10
|
||||
- package: github.com/gregjones/httpcache
|
||||
version: 787624de3eb7bd915c329cba748687a3b22666a6
|
||||
- package: github.com/armon/circbuf
|
||||
version: bbbad097214e2918d8543d5201d12bfd7bca254d
|
||||
- package: github.com/docker/libnetwork
|
||||
version: v0.8.0-dev.2-1265-ga9cd636e378982
|
||||
- package: github.com/jonboulle/clockwork
|
||||
version: 72f9bd7c4e0c2a40055ab3d0f09654f730cce982
|
||||
- package: k8s.io/gengo
|
||||
version: 51747d6e00da1fc578d5a333a93bb2abcbce7a95
|
||||
- package: github.com/JeffAshton/win_pdh
|
||||
version: 76bb4ee9f0ab50f77826f2a2ee7fb9d3880d6ec2
|
||||
- package: github.com/robfig/cron
|
||||
version: v1-53-gdf38d32658d878
|
||||
- package: github.com/shurcooL/sanitized_anchor_name
|
||||
version: 10ef21a441db47d8b13ebcc5fd2310f636973c77
|
||||
- package: github.com/MakeNowJust/heredoc
|
||||
version: bb23615498cded5e105af4ce27de75b089cbe851
|
||||
- package: github.com/ugorji/go
|
||||
version: bdcc60b419d136a85cdf2e7cbcac34b3f1cd6e57
|
||||
- package: github.com/fatih/camelcase
|
||||
version: f6a740d52f961c60348ebb109adde9f4635d7540
|
||||
- package: github.com/hashicorp/golang-lru
|
||||
version: v0.5.0
|
||||
- package: github.com/prometheus/common
|
||||
version: v0.2.0
|
||||
- package: github.com/coreos/go-semver
|
||||
version: v0.2.0-9-ge214231b295a8e
|
||||
- package: github.com/sigma/go-inotify
|
||||
version: c87b6cf5033d2c6486046f045eeebdc3d910fd38
|
||||
- package: sigs.k8s.io/yaml
|
||||
version: v1.1.0
|
||||
- package: k8s.io/heapster
|
||||
version: v1.2.0-beta.1
|
||||
- package: github.com/golang/groupcache
|
||||
version: 02826c3e79038b59d737d3b1c0a1d937f71a4433
|
||||
- package: gopkg.in/square/go-jose.v2
|
||||
version: v2.1.6-4-g89060dee6a84df
|
||||
- package: github.com/Azure/go-ansiterm
|
||||
version: d6e3b3328b783f23731bc4d058875b0371ff8109
|
||||
- package: github.com/mattn/go-shellwords
|
||||
version: v1.0.3-20-gf8471b0a71ded0
|
||||
- package: github.com/prometheus/client_golang
|
||||
version: v0.9.2
|
||||
- package: github.com/docker/go-units
|
||||
version: v0.3.1-11-g9e638d38cf6977
|
||||
- package: github.com/chai2010/gettext-go
|
||||
version: c6fed771bfd517099caf0f7a961671fa8ed08723
|
||||
- package: github.com/daviddengcn/go-colortext
|
||||
version: 511bcaf42ccd42c38aba7427b6673277bf19e2a1
|
||||
- package: github.com/vishvananda/netns
|
||||
version: be1fbeda19366dea804f00efff2dd73a1642fdcc
|
||||
- package: github.com/docker/go-connections
|
||||
version: v0.3.0
|
||||
- package: gopkg.in/natefinch/lumberjack.v2
|
||||
version: v1.0-16-g20b71e5b60d756
|
||||
- package: github.com/russross/blackfriday
|
||||
version: v1.4-2-g300106c228d52c
|
||||
- package: github.com/google/cadvisor
|
||||
version: v0.33.1-k3s.1
|
||||
repo: https://github.com/ibuildthecloud/cadvisor.git
|
||||
- package: github.com/cyphar/filepath-securejoin
|
||||
version: v0.2.1-1-gae69057f2299fb
|
||||
- package: github.com/ibuildthecloud/kvsql
|
||||
version: 0e798b1475327aadf3b8da5d2d1f99bb93dfd667
|
||||
- package: github.com/JeffAshton/win_pdh
|
||||
version: 76bb4ee9f0ab50f77826f2a2ee7fb9d3880d6ec2
|
||||
- package: github.com/prometheus/client_model
|
||||
version: model-0.0.2-12-gfa8ad6fec33561
|
||||
- package: github.com/miekg/dns
|
||||
version: 5d001d020961ae1c184f9f8152fdc73810481677
|
||||
- package: github.com/daviddengcn/go-colortext
|
||||
version: 511bcaf42ccd42c38aba7427b6673277bf19e2a1
|
||||
- package: github.com/gregjones/httpcache
|
||||
version: 787624de3eb7bd915c329cba748687a3b22666a6
|
||||
- package: github.com/karrick/godirwalk
|
||||
version: v1.7.5
|
||||
- package: k8s.io/gengo
|
||||
version: 51747d6e00da1fc578d5a333a93bb2abcbce7a95
|
||||
- package: k8s.io/heapster
|
||||
version: v1.2.0-beta.1
|
||||
- package: github.com/checkpoint-restore/go-criu
|
||||
version: v3.11
|
||||
- package: github.com/google/btree
|
||||
version: 7d79101e329e5a3adf994758c578dab82b90c017
|
||||
- package: github.com/google/certificate-transparency-go
|
||||
version: v1.0.21
|
||||
- package: github.com/robfig/cron
|
||||
version: v1-53-gdf38d32658d878
|
||||
- package: github.com/mrunalp/fileutils
|
||||
version: 4ee1cc9a80582a0c75febdd5cfa779ee4361cbca
|
||||
- package: github.com/Nvveen/Gotty
|
||||
version: cd527374f1e5bff4938207604a14f2e38a9cf512
|
||||
- package: github.com/exponent-io/jsonpath
|
||||
version: d6023ce2651d8eafb5c75bb0c7167536102ec9f5
|
||||
- package: github.com/fsnotify/fsnotify
|
||||
version: v1.3.1-1-gf12c6236fe7b5c
|
||||
- package: github.com/jteeuwen/go-bindata
|
||||
version: v3.0.7-72-ga0ff2567cfb709
|
||||
- package: gopkg.in/square/go-jose.v2
|
||||
version: v2.1.6-4-g89060dee6a84df
|
||||
- package: k8s.io/klog
|
||||
version: v0.2.0-14-g8e90cee79f8237
|
||||
- package: github.com/munnerz/goautoneg
|
||||
version: a547fc61f48d567d5b4ec6f8aee5573d8efce11d
|
||||
- package: github.com/docker/go-units
|
||||
version: v0.3.1-11-g9e638d38cf6977
|
||||
- package: github.com/fatih/camelcase
|
||||
version: f6a740d52f961c60348ebb109adde9f4635d7540
|
||||
- package: k8s.io/utils
|
||||
version: c2654d5206da6b7b6ace12841e8f359bb89b443c
|
||||
- package: github.com/coreos/etcd
|
||||
version: v3.3.10
|
||||
- package: github.com/docker/go-connections
|
||||
version: v0.3.0
|
||||
- package: github.com/golang/groupcache
|
||||
version: 02826c3e79038b59d737d3b1c0a1d937f71a4433
|
||||
- package: gopkg.in/natefinch/lumberjack.v2
|
||||
version: v1.0-16-g20b71e5b60d756
|
||||
- package: github.com/spf13/pflag
|
||||
version: v1.0.1
|
||||
- package: github.com/mistifyio/go-zfs
|
||||
version: v2.1.1-5-g1b4ae6fb4e77b0
|
||||
- package: github.com/mitchellh/go-wordwrap
|
||||
version: ad45545899c7b13c020ea92b2072220eefad42b8
|
||||
- package: github.com/docker/libnetwork
|
||||
version: v0.8.0-dev.2-1265-ga9cd636e378982
|
||||
- package: sigs.k8s.io/yaml
|
||||
version: v1.1.0
|
||||
- package: github.com/euank/go-kmsg-parser
|
||||
version: v2.0.0
|
||||
- package: github.com/evanphx/json-patch
|
||||
version: v4.1.0-19-g5858425f75500d
|
||||
- package: github.com/lithammer/dedent
|
||||
version: v1.1.0
|
||||
- package: github.com/jonboulle/clockwork
|
||||
version: 72f9bd7c4e0c2a40055ab3d0f09654f730cce982
|
||||
- package: github.com/cloudflare/cfssl
|
||||
version: 1.3.2-21-g56268a613adfed
|
||||
- package: github.com/docker/docker
|
||||
version: docs-v1.12.0-rc4-2016-07-15-9510-ga9fbbdc8dd8794
|
||||
- package: github.com/coreos/pkg
|
||||
version: v4
|
||||
- package: github.com/Azure/go-ansiterm
|
||||
version: d6e3b3328b783f23731bc4d058875b0371ff8109
|
||||
- package: github.com/armon/circbuf
|
||||
version: bbbad097214e2918d8543d5201d12bfd7bca254d
|
||||
- package: golang.org/x/tools
|
||||
version: 7f7074d5bcfd282eb16bc382b0bb3da762461985
|
||||
- package: github.com/pborman/uuid
|
||||
version: ca53cad383cad2479bbba7f7a1a05797ec1386e4
|
||||
- package: github.com/ibuildthecloud/kvsql
|
||||
version: 0e798b1475327aadf3b8da5d2d1f99bb93dfd667
|
||||
- package: github.com/googleapis/gnostic
|
||||
version: 0c5108395e2debce0d731cf0287ddf7242066aba
|
||||
- package: github.com/inconshreveable/mousetrap
|
||||
version: v1.0
|
||||
- package: github.com/container-storage-interface/spec
|
||||
version: v1.1.0
|
||||
- package: github.com/cyphar/filepath-securejoin
|
||||
version: v0.2.1-1-gae69057f2299fb
|
||||
- package: github.com/mrunalp/fileutils
|
||||
version: 4ee1cc9a80582a0c75febdd5cfa779ee4361cbca
|
||||
- package: github.com/lithammer/dedent
|
||||
version: v1.1.0
|
||||
- package: github.com/mxk/go-flowrate
|
||||
version: cca7078d478f8520f85629ad7c68962d31ed7682
|
||||
- package: github.com/peterbourgon/diskv
|
||||
version: v2.0.1
|
||||
- package: github.com/prometheus/procfs
|
||||
version: 65c1f6f8f0fc1e2185eb9863a3bc751496404259
|
||||
- package: github.com/jteeuwen/go-bindata
|
||||
version: v3.0.7-72-ga0ff2567cfb709
|
||||
- package: github.com/pborman/uuid
|
||||
version: ca53cad383cad2479bbba7f7a1a05797ec1386e4
|
||||
- package: github.com/checkpoint-restore/go-criu
|
||||
version: v3.11
|
||||
- package: github.com/MakeNowJust/heredoc
|
||||
version: bb23615498cded5e105af4ce27de75b089cbe851
|
||||
- package: github.com/liggitt/tabwriter
|
||||
version: 89fcab3d43de07060e4fd4c1547430ed57e87f24
|
||||
- package: github.com/exponent-io/jsonpath
|
||||
version: d6023ce2651d8eafb5c75bb0c7167536102ec9f5
|
||||
- package: golang.org/x/tools
|
||||
version: 7f7074d5bcfd282eb16bc382b0bb3da762461985
|
||||
- package: github.com/evanphx/json-patch
|
||||
version: v4.1.0-19-g5858425f75500d
|
||||
- package: github.com/mindprince/gonvml
|
||||
version: fee913ce8fb235edf54739d259ca0ecc226c7b8a
|
||||
- package: k8s.io/klog
|
||||
version: v0.2.0-14-g8e90cee79f8237
|
||||
- package: github.com/coreos/go-semver
|
||||
version: v0.2.0-9-ge214231b295a8e
|
||||
- package: github.com/euank/go-kmsg-parser
|
||||
version: v2.0.0
|
||||
- package: k8s.io/utils
|
||||
version: c2654d5206da6b7b6ace12841e8f359bb89b443c
|
||||
|
|
12
vendor.conf
12
vendor.conf
|
@ -9,7 +9,7 @@ package=github.com/opencontainers/runc/libcontainer/nsenter
|
|||
package=github.com/opencontainers/runc/libcontainer/specconv
|
||||
package=github.com/opencontainers/runc/contrib/cmd/recvtty
|
||||
|
||||
k8s.io/kubernetes v1.14.1-k3s.1 https://github.com/rancher/k3s.git transitive=true,staging=true
|
||||
k8s.io/kubernetes v1.14.1-k3s.2 https://github.com/rancher/k3s.git transitive=true,staging=true
|
||||
|
||||
github.com/rancher/norman 50017efee23caa79542ef685b65a7b783e0a73ca https://github.com/ibuildthecloud/norman.git
|
||||
github.com/coreos/flannel 823afe66b2266bf71f5bec24e6e28b26d70cfc7c https://github.com/ibuildthecloud/flannel.git
|
||||
|
@ -85,14 +85,14 @@ go.etcd.io/bbolt v1.3.1-etcd.8
|
|||
github.com/kubernetes-sigs/cri-tools c465773e3ad8c941d1756c0a467d550b04a8f65b https://github.com/ibuildthecloud/cri-tools.git
|
||||
|
||||
# cri dependencies
|
||||
github.com/containerd/cri eb926cd79d3bac188dcc4ed7694fc9298f8831be # release/1.2 branch
|
||||
github.com/containerd/cri v1.2-k3s.2 https://github.com/rancher/cri.git
|
||||
github.com/containerd/go-cni 40bcf8ec8acd7372be1d77031d585d5d8e561c90
|
||||
github.com/blang/semver v3.1.0
|
||||
github.com/containernetworking/cni v0.6.0
|
||||
#github.com/containernetworking/plugins v0.7.5
|
||||
github.com/davecgh/go-spew v1.1.0
|
||||
github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580
|
||||
#github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00
|
||||
github.com/docker/docker c12f09bf99b54f274a5ae241dd154fa74020cbab
|
||||
github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
|
||||
github.com/emicklei/go-restful v2.2.1
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
|
@ -115,3 +115,9 @@ golang.org/x/oauth2 a6bd8cefa1811bd24b86f8902872e4e8225f74c4
|
|||
golang.org/x/time f51c12702a4d776e4c1fa9b0fabab841babae631
|
||||
gopkg.in/inf.v0 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
|
||||
gopkg.in/yaml.v2 v2.2.1
|
||||
|
||||
# rootless
|
||||
github.com/rootless-containers/rootlesskit 893c1c3de71f54c301fdb85a7c0dd15c1933c159
|
||||
github.com/theckman/go-flock v0.7.1
|
||||
|
||||
github.com/morikuni/aec 39771216ff4c63d11f5e604076f9c45e8be1067b
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
Copyright (c) 2012, Neal van Veen (nealvanveen@gmail.com)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
|
@ -1,5 +0,0 @@
|
|||
Gotty is a library written in Go that determines and reads termcap database
|
||||
files to produce an interface for interacting with the capabilities of a
|
||||
terminal.
|
||||
See the godoc documentation or the source code for more information about
|
||||
function usage.
|
|
@ -1,3 +0,0 @@
|
|||
gotty.go:// TODO add more concurrency to name lookup, look for more opportunities.
|
||||
all:// TODO add more documentation, with function usage in a doc.go file.
|
||||
all:// TODO add more testing/benchmarking with go test.
|
|
@ -1,514 +0,0 @@
|
|||
// Copyright 2012 Neal van Veen. All rights reserved.
|
||||
// Usage of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package gotty
|
||||
|
||||
// Boolean capabilities
|
||||
var BoolAttr = [...]string{
|
||||
"auto_left_margin", "bw",
|
||||
"auto_right_margin", "am",
|
||||
"no_esc_ctlc", "xsb",
|
||||
"ceol_standout_glitch", "xhp",
|
||||
"eat_newline_glitch", "xenl",
|
||||
"erase_overstrike", "eo",
|
||||
"generic_type", "gn",
|
||||
"hard_copy", "hc",
|
||||
"has_meta_key", "km",
|
||||
"has_status_line", "hs",
|
||||
"insert_null_glitch", "in",
|
||||
"memory_above", "da",
|
||||
"memory_below", "db",
|
||||
"move_insert_mode", "mir",
|
||||
"move_standout_mode", "msgr",
|
||||
"over_strike", "os",
|
||||
"status_line_esc_ok", "eslok",
|
||||
"dest_tabs_magic_smso", "xt",
|
||||
"tilde_glitch", "hz",
|
||||
"transparent_underline", "ul",
|
||||
"xon_xoff", "nxon",
|
||||
"needs_xon_xoff", "nxon",
|
||||
"prtr_silent", "mc5i",
|
||||
"hard_cursor", "chts",
|
||||
"non_rev_rmcup", "nrrmc",
|
||||
"no_pad_char", "npc",
|
||||
"non_dest_scroll_region", "ndscr",
|
||||
"can_change", "ccc",
|
||||
"back_color_erase", "bce",
|
||||
"hue_lightness_saturation", "hls",
|
||||
"col_addr_glitch", "xhpa",
|
||||
"cr_cancels_micro_mode", "crxm",
|
||||
"has_print_wheel", "daisy",
|
||||
"row_addr_glitch", "xvpa",
|
||||
"semi_auto_right_margin", "sam",
|
||||
"cpi_changes_res", "cpix",
|
||||
"lpi_changes_res", "lpix",
|
||||
"backspaces_with_bs", "",
|
||||
"crt_no_scrolling", "",
|
||||
"no_correctly_working_cr", "",
|
||||
"gnu_has_meta_key", "",
|
||||
"linefeed_is_newline", "",
|
||||
"has_hardware_tabs", "",
|
||||
"return_does_clr_eol", "",
|
||||
}
|
||||
|
||||
// Numerical capabilities
|
||||
var NumAttr = [...]string{
|
||||
"columns", "cols",
|
||||
"init_tabs", "it",
|
||||
"lines", "lines",
|
||||
"lines_of_memory", "lm",
|
||||
"magic_cookie_glitch", "xmc",
|
||||
"padding_baud_rate", "pb",
|
||||
"virtual_terminal", "vt",
|
||||
"width_status_line", "wsl",
|
||||
"num_labels", "nlab",
|
||||
"label_height", "lh",
|
||||
"label_width", "lw",
|
||||
"max_attributes", "ma",
|
||||
"maximum_windows", "wnum",
|
||||
"max_colors", "colors",
|
||||
"max_pairs", "pairs",
|
||||
"no_color_video", "ncv",
|
||||
"buffer_capacity", "bufsz",
|
||||
"dot_vert_spacing", "spinv",
|
||||
"dot_horz_spacing", "spinh",
|
||||
"max_micro_address", "maddr",
|
||||
"max_micro_jump", "mjump",
|
||||
"micro_col_size", "mcs",
|
||||
"micro_line_size", "mls",
|
||||
"number_of_pins", "npins",
|
||||
"output_res_char", "orc",
|
||||
"output_res_line", "orl",
|
||||
"output_res_horz_inch", "orhi",
|
||||
"output_res_vert_inch", "orvi",
|
||||
"print_rate", "cps",
|
||||
"wide_char_size", "widcs",
|
||||
"buttons", "btns",
|
||||
"bit_image_entwining", "bitwin",
|
||||
"bit_image_type", "bitype",
|
||||
"magic_cookie_glitch_ul", "",
|
||||
"carriage_return_delay", "",
|
||||
"new_line_delay", "",
|
||||
"backspace_delay", "",
|
||||
"horizontal_tab_delay", "",
|
||||
"number_of_function_keys", "",
|
||||
}
|
||||
|
||||
// String capabilities
|
||||
var StrAttr = [...]string{
|
||||
"back_tab", "cbt",
|
||||
"bell", "bel",
|
||||
"carriage_return", "cr",
|
||||
"change_scroll_region", "csr",
|
||||
"clear_all_tabs", "tbc",
|
||||
"clear_screen", "clear",
|
||||
"clr_eol", "el",
|
||||
"clr_eos", "ed",
|
||||
"column_address", "hpa",
|
||||
"command_character", "cmdch",
|
||||
"cursor_address", "cup",
|
||||
"cursor_down", "cud1",
|
||||
"cursor_home", "home",
|
||||
"cursor_invisible", "civis",
|
||||
"cursor_left", "cub1",
|
||||
"cursor_mem_address", "mrcup",
|
||||
"cursor_normal", "cnorm",
|
||||
"cursor_right", "cuf1",
|
||||
"cursor_to_ll", "ll",
|
||||
"cursor_up", "cuu1",
|
||||
"cursor_visible", "cvvis",
|
||||
"delete_character", "dch1",
|
||||
"delete_line", "dl1",
|
||||
"dis_status_line", "dsl",
|
||||
"down_half_line", "hd",
|
||||
"enter_alt_charset_mode", "smacs",
|
||||
"enter_blink_mode", "blink",
|
||||
"enter_bold_mode", "bold",
|
||||
"enter_ca_mode", "smcup",
|
||||
"enter_delete_mode", "smdc",
|
||||
"enter_dim_mode", "dim",
|
||||
"enter_insert_mode", "smir",
|
||||
"enter_secure_mode", "invis",
|
||||
"enter_protected_mode", "prot",
|
||||
"enter_reverse_mode", "rev",
|
||||
"enter_standout_mode", "smso",
|
||||
"enter_underline_mode", "smul",
|
||||
"erase_chars", "ech",
|
||||
"exit_alt_charset_mode", "rmacs",
|
||||
"exit_attribute_mode", "sgr0",
|
||||
"exit_ca_mode", "rmcup",
|
||||
"exit_delete_mode", "rmdc",
|
||||
"exit_insert_mode", "rmir",
|
||||
"exit_standout_mode", "rmso",
|
||||
"exit_underline_mode", "rmul",
|
||||
"flash_screen", "flash",
|
||||
"form_feed", "ff",
|
||||
"from_status_line", "fsl",
|
||||
"init_1string", "is1",
|
||||
"init_2string", "is2",
|
||||
"init_3string", "is3",
|
||||
"init_file", "if",
|
||||
"insert_character", "ich1",
|
||||
"insert_line", "il1",
|
||||
"insert_padding", "ip",
|
||||
"key_backspace", "kbs",
|
||||
"key_catab", "ktbc",
|
||||
"key_clear", "kclr",
|
||||
"key_ctab", "kctab",
|
||||
"key_dc", "kdch1",
|
||||
"key_dl", "kdl1",
|
||||
"key_down", "kcud1",
|
||||
"key_eic", "krmir",
|
||||
"key_eol", "kel",
|
||||
"key_eos", "ked",
|
||||
"key_f0", "kf0",
|
||||
"key_f1", "kf1",
|
||||
"key_f10", "kf10",
|
||||
"key_f2", "kf2",
|
||||
"key_f3", "kf3",
|
||||
"key_f4", "kf4",
|
||||
"key_f5", "kf5",
|
||||
"key_f6", "kf6",
|
||||
"key_f7", "kf7",
|
||||
"key_f8", "kf8",
|
||||
"key_f9", "kf9",
|
||||
"key_home", "khome",
|
||||
"key_ic", "kich1",
|
||||
"key_il", "kil1",
|
||||
"key_left", "kcub1",
|
||||
"key_ll", "kll",
|
||||
"key_npage", "knp",
|
||||
"key_ppage", "kpp",
|
||||
"key_right", "kcuf1",
|
||||
"key_sf", "kind",
|
||||
"key_sr", "kri",
|
||||
"key_stab", "khts",
|
||||
"key_up", "kcuu1",
|
||||
"keypad_local", "rmkx",
|
||||
"keypad_xmit", "smkx",
|
||||
"lab_f0", "lf0",
|
||||
"lab_f1", "lf1",
|
||||
"lab_f10", "lf10",
|
||||
"lab_f2", "lf2",
|
||||
"lab_f3", "lf3",
|
||||
"lab_f4", "lf4",
|
||||
"lab_f5", "lf5",
|
||||
"lab_f6", "lf6",
|
||||
"lab_f7", "lf7",
|
||||
"lab_f8", "lf8",
|
||||
"lab_f9", "lf9",
|
||||
"meta_off", "rmm",
|
||||
"meta_on", "smm",
|
||||
"newline", "_glitch",
|
||||
"pad_char", "npc",
|
||||
"parm_dch", "dch",
|
||||
"parm_delete_line", "dl",
|
||||
"parm_down_cursor", "cud",
|
||||
"parm_ich", "ich",
|
||||
"parm_index", "indn",
|
||||
"parm_insert_line", "il",
|
||||
"parm_left_cursor", "cub",
|
||||
"parm_right_cursor", "cuf",
|
||||
"parm_rindex", "rin",
|
||||
"parm_up_cursor", "cuu",
|
||||
"pkey_key", "pfkey",
|
||||
"pkey_local", "pfloc",
|
||||
"pkey_xmit", "pfx",
|
||||
"print_screen", "mc0",
|
||||
"prtr_off", "mc4",
|
||||
"prtr_on", "mc5",
|
||||
"repeat_char", "rep",
|
||||
"reset_1string", "rs1",
|
||||
"reset_2string", "rs2",
|
||||
"reset_3string", "rs3",
|
||||
"reset_file", "rf",
|
||||
"restore_cursor", "rc",
|
||||
"row_address", "mvpa",
|
||||
"save_cursor", "row_address",
|
||||
"scroll_forward", "ind",
|
||||
"scroll_reverse", "ri",
|
||||
"set_attributes", "sgr",
|
||||
"set_tab", "hts",
|
||||
"set_window", "wind",
|
||||
"tab", "s_magic_smso",
|
||||
"to_status_line", "tsl",
|
||||
"underline_char", "uc",
|
||||
"up_half_line", "hu",
|
||||
"init_prog", "iprog",
|
||||
"key_a1", "ka1",
|
||||
"key_a3", "ka3",
|
||||
"key_b2", "kb2",
|
||||
"key_c1", "kc1",
|
||||
"key_c3", "kc3",
|
||||
"prtr_non", "mc5p",
|
||||
"char_padding", "rmp",
|
||||
"acs_chars", "acsc",
|
||||
"plab_norm", "pln",
|
||||
"key_btab", "kcbt",
|
||||
"enter_xon_mode", "smxon",
|
||||
"exit_xon_mode", "rmxon",
|
||||
"enter_am_mode", "smam",
|
||||
"exit_am_mode", "rmam",
|
||||
"xon_character", "xonc",
|
||||
"xoff_character", "xoffc",
|
||||
"ena_acs", "enacs",
|
||||
"label_on", "smln",
|
||||
"label_off", "rmln",
|
||||
"key_beg", "kbeg",
|
||||
"key_cancel", "kcan",
|
||||
"key_close", "kclo",
|
||||
"key_command", "kcmd",
|
||||
"key_copy", "kcpy",
|
||||
"key_create", "kcrt",
|
||||
"key_end", "kend",
|
||||
"key_enter", "kent",
|
||||
"key_exit", "kext",
|
||||
"key_find", "kfnd",
|
||||
"key_help", "khlp",
|
||||
"key_mark", "kmrk",
|
||||
"key_message", "kmsg",
|
||||
"key_move", "kmov",
|
||||
"key_next", "knxt",
|
||||
"key_open", "kopn",
|
||||
"key_options", "kopt",
|
||||
"key_previous", "kprv",
|
||||
"key_print", "kprt",
|
||||
"key_redo", "krdo",
|
||||
"key_reference", "kref",
|
||||
"key_refresh", "krfr",
|
||||
"key_replace", "krpl",
|
||||
"key_restart", "krst",
|
||||
"key_resume", "kres",
|
||||
"key_save", "ksav",
|
||||
"key_suspend", "kspd",
|
||||
"key_undo", "kund",
|
||||
"key_sbeg", "kBEG",
|
||||
"key_scancel", "kCAN",
|
||||
"key_scommand", "kCMD",
|
||||
"key_scopy", "kCPY",
|
||||
"key_screate", "kCRT",
|
||||
"key_sdc", "kDC",
|
||||
"key_sdl", "kDL",
|
||||
"key_select", "kslt",
|
||||
"key_send", "kEND",
|
||||
"key_seol", "kEOL",
|
||||
"key_sexit", "kEXT",
|
||||
"key_sfind", "kFND",
|
||||
"key_shelp", "kHLP",
|
||||
"key_shome", "kHOM",
|
||||
"key_sic", "kIC",
|
||||
"key_sleft", "kLFT",
|
||||
"key_smessage", "kMSG",
|
||||
"key_smove", "kMOV",
|
||||
"key_snext", "kNXT",
|
||||
"key_soptions", "kOPT",
|
||||
"key_sprevious", "kPRV",
|
||||
"key_sprint", "kPRT",
|
||||
"key_sredo", "kRDO",
|
||||
"key_sreplace", "kRPL",
|
||||
"key_sright", "kRIT",
|
||||
"key_srsume", "kRES",
|
||||
"key_ssave", "kSAV",
|
||||
"key_ssuspend", "kSPD",
|
||||
"key_sundo", "kUND",
|
||||
"req_for_input", "rfi",
|
||||
"key_f11", "kf11",
|
||||
"key_f12", "kf12",
|
||||
"key_f13", "kf13",
|
||||
"key_f14", "kf14",
|
||||
"key_f15", "kf15",
|
||||
"key_f16", "kf16",
|
||||
"key_f17", "kf17",
|
||||
"key_f18", "kf18",
|
||||
"key_f19", "kf19",
|
||||
"key_f20", "kf20",
|
||||
"key_f21", "kf21",
|
||||
"key_f22", "kf22",
|
||||
"key_f23", "kf23",
|
||||
"key_f24", "kf24",
|
||||
"key_f25", "kf25",
|
||||
"key_f26", "kf26",
|
||||
"key_f27", "kf27",
|
||||
"key_f28", "kf28",
|
||||
"key_f29", "kf29",
|
||||
"key_f30", "kf30",
|
||||
"key_f31", "kf31",
|
||||
"key_f32", "kf32",
|
||||
"key_f33", "kf33",
|
||||
"key_f34", "kf34",
|
||||
"key_f35", "kf35",
|
||||
"key_f36", "kf36",
|
||||
"key_f37", "kf37",
|
||||
"key_f38", "kf38",
|
||||
"key_f39", "kf39",
|
||||
"key_f40", "kf40",
|
||||
"key_f41", "kf41",
|
||||
"key_f42", "kf42",
|
||||
"key_f43", "kf43",
|
||||
"key_f44", "kf44",
|
||||
"key_f45", "kf45",
|
||||
"key_f46", "kf46",
|
||||
"key_f47", "kf47",
|
||||
"key_f48", "kf48",
|
||||
"key_f49", "kf49",
|
||||
"key_f50", "kf50",
|
||||
"key_f51", "kf51",
|
||||
"key_f52", "kf52",
|
||||
"key_f53", "kf53",
|
||||
"key_f54", "kf54",
|
||||
"key_f55", "kf55",
|
||||
"key_f56", "kf56",
|
||||
"key_f57", "kf57",
|
||||
"key_f58", "kf58",
|
||||
"key_f59", "kf59",
|
||||
"key_f60", "kf60",
|
||||
"key_f61", "kf61",
|
||||
"key_f62", "kf62",
|
||||
"key_f63", "kf63",
|
||||
"clr_bol", "el1",
|
||||
"clear_margins", "mgc",
|
||||
"set_left_margin", "smgl",
|
||||
"set_right_margin", "smgr",
|
||||
"label_format", "fln",
|
||||
"set_clock", "sclk",
|
||||
"display_clock", "dclk",
|
||||
"remove_clock", "rmclk",
|
||||
"create_window", "cwin",
|
||||
"goto_window", "wingo",
|
||||
"hangup", "hup",
|
||||
"dial_phone", "dial",
|
||||
"quick_dial", "qdial",
|
||||
"tone", "tone",
|
||||
"pulse", "pulse",
|
||||
"flash_hook", "hook",
|
||||
"fixed_pause", "pause",
|
||||
"wait_tone", "wait",
|
||||
"user0", "u0",
|
||||
"user1", "u1",
|
||||
"user2", "u2",
|
||||
"user3", "u3",
|
||||
"user4", "u4",
|
||||
"user5", "u5",
|
||||
"user6", "u6",
|
||||
"user7", "u7",
|
||||
"user8", "u8",
|
||||
"user9", "u9",
|
||||
"orig_pair", "op",
|
||||
"orig_colors", "oc",
|
||||
"initialize_color", "initc",
|
||||
"initialize_pair", "initp",
|
||||
"set_color_pair", "scp",
|
||||
"set_foreground", "setf",
|
||||
"set_background", "setb",
|
||||
"change_char_pitch", "cpi",
|
||||
"change_line_pitch", "lpi",
|
||||
"change_res_horz", "chr",
|
||||
"change_res_vert", "cvr",
|
||||
"define_char", "defc",
|
||||
"enter_doublewide_mode", "swidm",
|
||||
"enter_draft_quality", "sdrfq",
|
||||
"enter_italics_mode", "sitm",
|
||||
"enter_leftward_mode", "slm",
|
||||
"enter_micro_mode", "smicm",
|
||||
"enter_near_letter_quality", "snlq",
|
||||
"enter_normal_quality", "snrmq",
|
||||
"enter_shadow_mode", "sshm",
|
||||
"enter_subscript_mode", "ssubm",
|
||||
"enter_superscript_mode", "ssupm",
|
||||
"enter_upward_mode", "sum",
|
||||
"exit_doublewide_mode", "rwidm",
|
||||
"exit_italics_mode", "ritm",
|
||||
"exit_leftward_mode", "rlm",
|
||||
"exit_micro_mode", "rmicm",
|
||||
"exit_shadow_mode", "rshm",
|
||||
"exit_subscript_mode", "rsubm",
|
||||
"exit_superscript_mode", "rsupm",
|
||||
"exit_upward_mode", "rum",
|
||||
"micro_column_address", "mhpa",
|
||||
"micro_down", "mcud1",
|
||||
"micro_left", "mcub1",
|
||||
"micro_right", "mcuf1",
|
||||
"micro_row_address", "mvpa",
|
||||
"micro_up", "mcuu1",
|
||||
"order_of_pins", "porder",
|
||||
"parm_down_micro", "mcud",
|
||||
"parm_left_micro", "mcub",
|
||||
"parm_right_micro", "mcuf",
|
||||
"parm_up_micro", "mcuu",
|
||||
"select_char_set", "scs",
|
||||
"set_bottom_margin", "smgb",
|
||||
"set_bottom_margin_parm", "smgbp",
|
||||
"set_left_margin_parm", "smglp",
|
||||
"set_right_margin_parm", "smgrp",
|
||||
"set_top_margin", "smgt",
|
||||
"set_top_margin_parm", "smgtp",
|
||||
"start_bit_image", "sbim",
|
||||
"start_char_set_def", "scsd",
|
||||
"stop_bit_image", "rbim",
|
||||
"stop_char_set_def", "rcsd",
|
||||
"subscript_characters", "subcs",
|
||||
"superscript_characters", "supcs",
|
||||
"these_cause_cr", "docr",
|
||||
"zero_motion", "zerom",
|
||||
"char_set_names", "csnm",
|
||||
"key_mouse", "kmous",
|
||||
"mouse_info", "minfo",
|
||||
"req_mouse_pos", "reqmp",
|
||||
"get_mouse", "getm",
|
||||
"set_a_foreground", "setaf",
|
||||
"set_a_background", "setab",
|
||||
"pkey_plab", "pfxl",
|
||||
"device_type", "devt",
|
||||
"code_set_init", "csin",
|
||||
"set0_des_seq", "s0ds",
|
||||
"set1_des_seq", "s1ds",
|
||||
"set2_des_seq", "s2ds",
|
||||
"set3_des_seq", "s3ds",
|
||||
"set_lr_margin", "smglr",
|
||||
"set_tb_margin", "smgtb",
|
||||
"bit_image_repeat", "birep",
|
||||
"bit_image_newline", "binel",
|
||||
"bit_image_carriage_return", "bicr",
|
||||
"color_names", "colornm",
|
||||
"define_bit_image_region", "defbi",
|
||||
"end_bit_image_region", "endbi",
|
||||
"set_color_band", "setcolor",
|
||||
"set_page_length", "slines",
|
||||
"display_pc_char", "dispc",
|
||||
"enter_pc_charset_mode", "smpch",
|
||||
"exit_pc_charset_mode", "rmpch",
|
||||
"enter_scancode_mode", "smsc",
|
||||
"exit_scancode_mode", "rmsc",
|
||||
"pc_term_options", "pctrm",
|
||||
"scancode_escape", "scesc",
|
||||
"alt_scancode_esc", "scesa",
|
||||
"enter_horizontal_hl_mode", "ehhlm",
|
||||
"enter_left_hl_mode", "elhlm",
|
||||
"enter_low_hl_mode", "elohlm",
|
||||
"enter_right_hl_mode", "erhlm",
|
||||
"enter_top_hl_mode", "ethlm",
|
||||
"enter_vertical_hl_mode", "evhlm",
|
||||
"set_a_attributes", "sgr1",
|
||||
"set_pglen_inch", "slength",
|
||||
"termcap_init2", "",
|
||||
"termcap_reset", "",
|
||||
"linefeed_if_not_lf", "",
|
||||
"backspace_if_not_bs", "",
|
||||
"other_non_function_keys", "",
|
||||
"arrow_key_map", "",
|
||||
"acs_ulcorner", "",
|
||||
"acs_llcorner", "",
|
||||
"acs_urcorner", "",
|
||||
"acs_lrcorner", "",
|
||||
"acs_ltee", "",
|
||||
"acs_rtee", "",
|
||||
"acs_btee", "",
|
||||
"acs_ttee", "",
|
||||
"acs_hline", "",
|
||||
"acs_vline", "",
|
||||
"acs_plus", "",
|
||||
"memory_lock", "",
|
||||
"memory_unlock", "",
|
||||
"box_chars_1", "",
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
// Copyright 2012 Neal van Veen. All rights reserved.
|
||||
// Usage of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Gotty is a Go-package for reading and parsing the terminfo database
|
||||
package gotty
|
||||
|
||||
// TODO add more concurrency to name lookup, look for more opportunities.
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Open a terminfo file by the name given and construct a TermInfo object.
|
||||
// If something went wrong reading the terminfo database file, an error is
|
||||
// returned.
|
||||
func OpenTermInfo(termName string) (*TermInfo, error) {
|
||||
var term *TermInfo
|
||||
var err error
|
||||
// Find the environment variables
|
||||
termloc := os.Getenv("TERMINFO")
|
||||
if len(termloc) == 0 {
|
||||
// Search like ncurses
|
||||
locations := []string{os.Getenv("HOME") + "/.terminfo/", "/etc/terminfo/",
|
||||
"/lib/terminfo/", "/usr/share/terminfo/"}
|
||||
var path string
|
||||
for _, str := range locations {
|
||||
// Construct path
|
||||
path = str + string(termName[0]) + "/" + termName
|
||||
// Check if path can be opened
|
||||
file, _ := os.Open(path)
|
||||
if file != nil {
|
||||
// Path can open, fall out and use current path
|
||||
file.Close()
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(path) > 0 {
|
||||
term, err = readTermInfo(path)
|
||||
} else {
|
||||
err = errors.New(fmt.Sprintf("No terminfo file(-location) found"))
|
||||
}
|
||||
}
|
||||
return term, err
|
||||
}
|
||||
|
||||
// Open a terminfo file from the environment variable containing the current
|
||||
// terminal name and construct a TermInfo object. If something went wrong
|
||||
// reading the terminfo database file, an error is returned.
|
||||
func OpenTermInfoEnv() (*TermInfo, error) {
|
||||
termenv := os.Getenv("TERM")
|
||||
return OpenTermInfo(termenv)
|
||||
}
|
||||
|
||||
// Return an attribute by the name attr provided. If none can be found,
|
||||
// an error is returned.
|
||||
func (term *TermInfo) GetAttribute(attr string) (stacker, error) {
|
||||
// Channel to store the main value in.
|
||||
var value stacker
|
||||
// Add a blocking WaitGroup
|
||||
var block sync.WaitGroup
|
||||
// Keep track of variable being written.
|
||||
written := false
|
||||
// Function to put into goroutine.
|
||||
f := func(ats interface{}) {
|
||||
var ok bool
|
||||
var v stacker
|
||||
// Switch on type of map to use and assign value to it.
|
||||
switch reflect.TypeOf(ats).Elem().Kind() {
|
||||
case reflect.Bool:
|
||||
v, ok = ats.(map[string]bool)[attr]
|
||||
case reflect.Int16:
|
||||
v, ok = ats.(map[string]int16)[attr]
|
||||
case reflect.String:
|
||||
v, ok = ats.(map[string]string)[attr]
|
||||
}
|
||||
// If ok, a value is found, so we can write.
|
||||
if ok {
|
||||
value = v
|
||||
written = true
|
||||
}
|
||||
// Goroutine is done
|
||||
block.Done()
|
||||
}
|
||||
block.Add(3)
|
||||
// Go for all 3 attribute lists.
|
||||
go f(term.boolAttributes)
|
||||
go f(term.numAttributes)
|
||||
go f(term.strAttributes)
|
||||
// Wait until every goroutine is done.
|
||||
block.Wait()
|
||||
// If a value has been written, return it.
|
||||
if written {
|
||||
return value, nil
|
||||
}
|
||||
// Otherwise, error.
|
||||
return nil, fmt.Errorf("Erorr finding attribute")
|
||||
}
|
||||
|
||||
// Return an attribute by the name attr provided. If none can be found,
|
||||
// an error is returned. A name is first converted to its termcap value.
|
||||
func (term *TermInfo) GetAttributeName(name string) (stacker, error) {
|
||||
tc := GetTermcapName(name)
|
||||
return term.GetAttribute(tc)
|
||||
}
|
||||
|
||||
// A utility function that finds and returns the termcap equivalent of a
|
||||
// variable name.
|
||||
func GetTermcapName(name string) string {
|
||||
// Termcap name
|
||||
var tc string
|
||||
// Blocking group
|
||||
var wait sync.WaitGroup
|
||||
// Function to put into a goroutine
|
||||
f := func(attrs []string) {
|
||||
// Find the string corresponding to the name
|
||||
for i, s := range attrs {
|
||||
if s == name {
|
||||
tc = attrs[i+1]
|
||||
}
|
||||
}
|
||||
// Goroutine is finished
|
||||
wait.Done()
|
||||
}
|
||||
wait.Add(3)
|
||||
// Go for all 3 attribute lists
|
||||
go f(BoolAttr[:])
|
||||
go f(NumAttr[:])
|
||||
go f(StrAttr[:])
|
||||
// Wait until every goroutine is done
|
||||
wait.Wait()
|
||||
// Return the termcap name
|
||||
return tc
|
||||
}
|
||||
|
||||
// This function takes a path to a terminfo file and reads it in binary
|
||||
// form to construct the actual TermInfo file.
|
||||
func readTermInfo(path string) (*TermInfo, error) {
|
||||
// Open the terminfo file
|
||||
file, err := os.Open(path)
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// magic, nameSize, boolSize, nrSNum, nrOffsetsStr, strSize
|
||||
// Header is composed of the magic 0432 octal number, size of the name
|
||||
// section, size of the boolean section, the amount of number values,
|
||||
// the number of offsets of strings, and the size of the string section.
|
||||
var header [6]int16
|
||||
// Byte array is used to read in byte values
|
||||
var byteArray []byte
|
||||
// Short array is used to read in short values
|
||||
var shArray []int16
|
||||
// TermInfo object to store values
|
||||
var term TermInfo
|
||||
|
||||
// Read in the header
|
||||
err = binary.Read(file, binary.LittleEndian, &header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If magic number isn't there or isn't correct, we have the wrong filetype
|
||||
if header[0] != 0432 {
|
||||
return nil, errors.New(fmt.Sprintf("Wrong filetype"))
|
||||
}
|
||||
|
||||
// Read in the names
|
||||
byteArray = make([]byte, header[1])
|
||||
err = binary.Read(file, binary.LittleEndian, &byteArray)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
term.Names = strings.Split(string(byteArray), "|")
|
||||
|
||||
// Read in the booleans
|
||||
byteArray = make([]byte, header[2])
|
||||
err = binary.Read(file, binary.LittleEndian, &byteArray)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
term.boolAttributes = make(map[string]bool)
|
||||
for i, b := range byteArray {
|
||||
if b == 1 {
|
||||
term.boolAttributes[BoolAttr[i*2+1]] = true
|
||||
}
|
||||
}
|
||||
// If the number of bytes read is not even, a byte for alignment is added
|
||||
if len(byteArray)%2 != 0 {
|
||||
err = binary.Read(file, binary.LittleEndian, make([]byte, 1))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Read in shorts
|
||||
shArray = make([]int16, header[3])
|
||||
err = binary.Read(file, binary.LittleEndian, &shArray)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
term.numAttributes = make(map[string]int16)
|
||||
for i, n := range shArray {
|
||||
if n != 0377 && n > -1 {
|
||||
term.numAttributes[NumAttr[i*2+1]] = n
|
||||
}
|
||||
}
|
||||
|
||||
// Read the offsets into the short array
|
||||
shArray = make([]int16, header[4])
|
||||
err = binary.Read(file, binary.LittleEndian, &shArray)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Read the actual strings in the byte array
|
||||
byteArray = make([]byte, header[5])
|
||||
err = binary.Read(file, binary.LittleEndian, &byteArray)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
term.strAttributes = make(map[string]string)
|
||||
// We get an offset, and then iterate until the string is null-terminated
|
||||
for i, offset := range shArray {
|
||||
if offset > -1 {
|
||||
r := offset
|
||||
for ; byteArray[r] != 0; r++ {
|
||||
}
|
||||
term.strAttributes[StrAttr[i*2+1]] = string(byteArray[offset:r])
|
||||
}
|
||||
}
|
||||
return &term, nil
|
||||
}
|
|
@ -1,362 +0,0 @@
|
|||
// Copyright 2012 Neal van Veen. All rights reserved.
|
||||
// Usage of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package gotty
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var exp = [...]string{
|
||||
"%%",
|
||||
"%c",
|
||||
"%s",
|
||||
"%p(\\d)",
|
||||
"%P([A-z])",
|
||||
"%g([A-z])",
|
||||
"%'(.)'",
|
||||
"%{([0-9]+)}",
|
||||
"%l",
|
||||
"%\\+|%-|%\\*|%/|%m",
|
||||
"%&|%\\||%\\^",
|
||||
"%=|%>|%<",
|
||||
"%A|%O",
|
||||
"%!|%~",
|
||||
"%i",
|
||||
"%(:[\\ #\\-\\+]{0,4})?(\\d+\\.\\d+|\\d+)?[doxXs]",
|
||||
"%\\?(.*?);",
|
||||
}
|
||||
|
||||
var regex *regexp.Regexp
|
||||
var staticVar map[byte]stacker
|
||||
|
||||
// Parses the attribute that is received with name attr and parameters params.
|
||||
func (term *TermInfo) Parse(attr string, params ...interface{}) (string, error) {
|
||||
// Get the attribute name first.
|
||||
iface, err := term.GetAttribute(attr)
|
||||
str, ok := iface.(string)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !ok {
|
||||
return str, errors.New("Only string capabilities can be parsed.")
|
||||
}
|
||||
// Construct the hidden parser struct so we can use a recursive stack based
|
||||
// parser.
|
||||
ps := &parser{}
|
||||
// Dynamic variables only exist in this context.
|
||||
ps.dynamicVar = make(map[byte]stacker, 26)
|
||||
ps.parameters = make([]stacker, len(params))
|
||||
// Convert the parameters to insert them into the parser struct.
|
||||
for i, x := range params {
|
||||
ps.parameters[i] = x
|
||||
}
|
||||
// Recursively walk and return.
|
||||
result, err := ps.walk(str)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Parses the attribute that is received with name attr and parameters params.
|
||||
// Only works on full name of a capability that is given, which it uses to
|
||||
// search for the termcap name.
|
||||
func (term *TermInfo) ParseName(attr string, params ...interface{}) (string, error) {
|
||||
tc := GetTermcapName(attr)
|
||||
return term.Parse(tc, params)
|
||||
}
|
||||
|
||||
// Identify each token in a stack based manner and do the actual parsing.
|
||||
func (ps *parser) walk(attr string) (string, error) {
|
||||
// We use a buffer to get the modified string.
|
||||
var buf bytes.Buffer
|
||||
// Next, find and identify all tokens by their indices and strings.
|
||||
tokens := regex.FindAllStringSubmatch(attr, -1)
|
||||
if len(tokens) == 0 {
|
||||
return attr, nil
|
||||
}
|
||||
indices := regex.FindAllStringIndex(attr, -1)
|
||||
q := 0 // q counts the matches of one token
|
||||
// Iterate through the string per character.
|
||||
for i := 0; i < len(attr); i++ {
|
||||
// If the current position is an identified token, execute the following
|
||||
// steps.
|
||||
if q < len(indices) && i >= indices[q][0] && i < indices[q][1] {
|
||||
// Switch on token.
|
||||
switch {
|
||||
case tokens[q][0][:2] == "%%":
|
||||
// Literal percentage character.
|
||||
buf.WriteByte('%')
|
||||
case tokens[q][0][:2] == "%c":
|
||||
// Pop a character.
|
||||
c, err := ps.st.pop()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
buf.WriteByte(c.(byte))
|
||||
case tokens[q][0][:2] == "%s":
|
||||
// Pop a string.
|
||||
str, err := ps.st.pop()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
if _, ok := str.(string); !ok {
|
||||
return buf.String(), errors.New("Stack head is not a string")
|
||||
}
|
||||
buf.WriteString(str.(string))
|
||||
case tokens[q][0][:2] == "%p":
|
||||
// Push a parameter on the stack.
|
||||
index, err := strconv.ParseInt(tokens[q][1], 10, 8)
|
||||
index--
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
if int(index) >= len(ps.parameters) {
|
||||
return buf.String(), errors.New("Parameters index out of bound")
|
||||
}
|
||||
ps.st.push(ps.parameters[index])
|
||||
case tokens[q][0][:2] == "%P":
|
||||
// Pop a variable from the stack as a dynamic or static variable.
|
||||
val, err := ps.st.pop()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
index := tokens[q][2]
|
||||
if len(index) > 1 {
|
||||
errorStr := fmt.Sprintf("%s is not a valid dynamic variables index",
|
||||
index)
|
||||
return buf.String(), errors.New(errorStr)
|
||||
}
|
||||
// Specify either dynamic or static.
|
||||
if index[0] >= 'a' && index[0] <= 'z' {
|
||||
ps.dynamicVar[index[0]] = val
|
||||
} else if index[0] >= 'A' && index[0] <= 'Z' {
|
||||
staticVar[index[0]] = val
|
||||
}
|
||||
case tokens[q][0][:2] == "%g":
|
||||
// Push a variable from the stack as a dynamic or static variable.
|
||||
index := tokens[q][3]
|
||||
if len(index) > 1 {
|
||||
errorStr := fmt.Sprintf("%s is not a valid static variables index",
|
||||
index)
|
||||
return buf.String(), errors.New(errorStr)
|
||||
}
|
||||
var val stacker
|
||||
if index[0] >= 'a' && index[0] <= 'z' {
|
||||
val = ps.dynamicVar[index[0]]
|
||||
} else if index[0] >= 'A' && index[0] <= 'Z' {
|
||||
val = staticVar[index[0]]
|
||||
}
|
||||
ps.st.push(val)
|
||||
case tokens[q][0][:2] == "%'":
|
||||
// Push a character constant.
|
||||
con := tokens[q][4]
|
||||
if len(con) > 1 {
|
||||
errorStr := fmt.Sprintf("%s is not a valid character constant", con)
|
||||
return buf.String(), errors.New(errorStr)
|
||||
}
|
||||
ps.st.push(con[0])
|
||||
case tokens[q][0][:2] == "%{":
|
||||
// Push an integer constant.
|
||||
con, err := strconv.ParseInt(tokens[q][5], 10, 32)
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
ps.st.push(con)
|
||||
case tokens[q][0][:2] == "%l":
|
||||
// Push the length of the string that is popped from the stack.
|
||||
popStr, err := ps.st.pop()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
if _, ok := popStr.(string); !ok {
|
||||
errStr := fmt.Sprintf("Stack head is not a string")
|
||||
return buf.String(), errors.New(errStr)
|
||||
}
|
||||
ps.st.push(len(popStr.(string)))
|
||||
case tokens[q][0][:2] == "%?":
|
||||
// If-then-else construct. First, the whole string is identified and
|
||||
// then inside this substring, we can specify which parts to switch on.
|
||||
ifReg, _ := regexp.Compile("%\\?(.*)%t(.*)%e(.*);|%\\?(.*)%t(.*);")
|
||||
ifTokens := ifReg.FindStringSubmatch(tokens[q][0])
|
||||
var (
|
||||
ifStr string
|
||||
err error
|
||||
)
|
||||
// Parse the if-part to determine if-else.
|
||||
if len(ifTokens[1]) > 0 {
|
||||
ifStr, err = ps.walk(ifTokens[1])
|
||||
} else { // else
|
||||
ifStr, err = ps.walk(ifTokens[4])
|
||||
}
|
||||
// Return any errors
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
} else if len(ifStr) > 0 {
|
||||
// Self-defined limitation, not sure if this is correct, but didn't
|
||||
// seem like it.
|
||||
return buf.String(), errors.New("If-clause cannot print statements")
|
||||
}
|
||||
var thenStr string
|
||||
// Pop the first value that is set by parsing the if-clause.
|
||||
choose, err := ps.st.pop()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
// Switch to if or else.
|
||||
if choose.(int) == 0 && len(ifTokens[1]) > 0 {
|
||||
thenStr, err = ps.walk(ifTokens[3])
|
||||
} else if choose.(int) != 0 {
|
||||
if len(ifTokens[1]) > 0 {
|
||||
thenStr, err = ps.walk(ifTokens[2])
|
||||
} else {
|
||||
thenStr, err = ps.walk(ifTokens[5])
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
buf.WriteString(thenStr)
|
||||
case tokens[q][0][len(tokens[q][0])-1] == 'd': // Fallthrough for printing
|
||||
fallthrough
|
||||
case tokens[q][0][len(tokens[q][0])-1] == 'o': // digits.
|
||||
fallthrough
|
||||
case tokens[q][0][len(tokens[q][0])-1] == 'x':
|
||||
fallthrough
|
||||
case tokens[q][0][len(tokens[q][0])-1] == 'X':
|
||||
fallthrough
|
||||
case tokens[q][0][len(tokens[q][0])-1] == 's':
|
||||
token := tokens[q][0]
|
||||
// Remove the : that comes before a flag.
|
||||
if token[1] == ':' {
|
||||
token = token[:1] + token[2:]
|
||||
}
|
||||
digit, err := ps.st.pop()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
// The rest is determined like the normal formatted prints.
|
||||
digitStr := fmt.Sprintf(token, digit.(int))
|
||||
buf.WriteString(digitStr)
|
||||
case tokens[q][0][:2] == "%i":
|
||||
// Increment the parameters by one.
|
||||
if len(ps.parameters) < 2 {
|
||||
return buf.String(), errors.New("Not enough parameters to increment.")
|
||||
}
|
||||
val1, val2 := ps.parameters[0].(int), ps.parameters[1].(int)
|
||||
val1++
|
||||
val2++
|
||||
ps.parameters[0], ps.parameters[1] = val1, val2
|
||||
default:
|
||||
// The rest of the tokens is a special case, where two values are
|
||||
// popped and then operated on by the token that comes after them.
|
||||
op1, err := ps.st.pop()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
op2, err := ps.st.pop()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
var result stacker
|
||||
switch tokens[q][0][:2] {
|
||||
case "%+":
|
||||
// Addition
|
||||
result = op2.(int) + op1.(int)
|
||||
case "%-":
|
||||
// Subtraction
|
||||
result = op2.(int) - op1.(int)
|
||||
case "%*":
|
||||
// Multiplication
|
||||
result = op2.(int) * op1.(int)
|
||||
case "%/":
|
||||
// Division
|
||||
result = op2.(int) / op1.(int)
|
||||
case "%m":
|
||||
// Modulo
|
||||
result = op2.(int) % op1.(int)
|
||||
case "%&":
|
||||
// Bitwise AND
|
||||
result = op2.(int) & op1.(int)
|
||||
case "%|":
|
||||
// Bitwise OR
|
||||
result = op2.(int) | op1.(int)
|
||||
case "%^":
|
||||
// Bitwise XOR
|
||||
result = op2.(int) ^ op1.(int)
|
||||
case "%=":
|
||||
// Equals
|
||||
result = op2 == op1
|
||||
case "%>":
|
||||
// Greater-than
|
||||
result = op2.(int) > op1.(int)
|
||||
case "%<":
|
||||
// Lesser-than
|
||||
result = op2.(int) < op1.(int)
|
||||
case "%A":
|
||||
// Logical AND
|
||||
result = op2.(bool) && op1.(bool)
|
||||
case "%O":
|
||||
// Logical OR
|
||||
result = op2.(bool) || op1.(bool)
|
||||
case "%!":
|
||||
// Logical complement
|
||||
result = !op1.(bool)
|
||||
case "%~":
|
||||
// Bitwise complement
|
||||
result = ^(op1.(int))
|
||||
}
|
||||
ps.st.push(result)
|
||||
}
|
||||
|
||||
i = indices[q][1] - 1
|
||||
q++
|
||||
} else {
|
||||
// We are not "inside" a token, so just skip until the end or the next
|
||||
// token, and add all characters to the buffer.
|
||||
j := i
|
||||
if q != len(indices) {
|
||||
for !(j >= indices[q][0] && j < indices[q][1]) {
|
||||
j++
|
||||
}
|
||||
} else {
|
||||
j = len(attr)
|
||||
}
|
||||
buf.WriteString(string(attr[i:j]))
|
||||
i = j
|
||||
}
|
||||
}
|
||||
// Return the buffer as a string.
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// Push a stacker-value onto the stack.
|
||||
func (st *stack) push(s stacker) {
|
||||
*st = append(*st, s)
|
||||
}
|
||||
|
||||
// Pop a stacker-value from the stack.
|
||||
func (st *stack) pop() (stacker, error) {
|
||||
if len(*st) == 0 {
|
||||
return nil, errors.New("Stack is empty.")
|
||||
}
|
||||
newStack := make(stack, len(*st)-1)
|
||||
val := (*st)[len(*st)-1]
|
||||
copy(newStack, (*st)[:len(*st)-1])
|
||||
*st = newStack
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// Initialize regexes and the static vars (that don't get changed between
|
||||
// calls.
|
||||
func init() {
|
||||
// Initialize the main regex.
|
||||
expStr := strings.Join(exp[:], "|")
|
||||
regex, _ = regexp.Compile(expStr)
|
||||
// Initialize the static variables.
|
||||
staticVar = make(map[byte]stacker, 26)
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright 2012 Neal van Veen. All rights reserved.
|
||||
// Usage of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package gotty
|
||||
|
||||
type TermInfo struct {
|
||||
boolAttributes map[string]bool
|
||||
numAttributes map[string]int16
|
||||
strAttributes map[string]string
|
||||
// The various names of the TermInfo file.
|
||||
Names []string
|
||||
}
|
||||
|
||||
type stacker interface {
|
||||
}
|
||||
type stack []stacker
|
||||
|
||||
type parser struct {
|
||||
st stack
|
||||
parameters []stacker
|
||||
dynamicVar map[byte]stacker
|
||||
}
|
|
@ -142,6 +142,16 @@ type PluginConfig struct {
|
|||
// Log line longer than the limit will be split into multiple lines. Non-positive
|
||||
// value means no limit.
|
||||
MaxContainerLogLineSize int `toml:"max_container_log_line_size" json:"maxContainerLogSize"`
|
||||
// DisableCgroup indicates to disable the cgroup support.
|
||||
// This is useful when the containerd does not have permission to access cgroup.
|
||||
DisableCgroup bool `toml:"disable_cgroup" json:"disableCgroup"`
|
||||
// DisableApparmor indicates to disable the apparmor support.
|
||||
// This is useful when the containerd does not have permission to access Apparmor.
|
||||
DisableApparmor bool `toml:"disable_apparmor" json:"disableApparmor"`
|
||||
// RestrictOOMScoreAdj indicates to limit the lower bound of OOMScoreAdj to the containerd's
|
||||
// current OOMScoreADj.
|
||||
// This is useful when the containerd does not have permission to decrease OOMScoreAdj.
|
||||
RestrictOOMScoreAdj bool `toml:"restrict_oom_score_adj" json:"restrictOOMScoreAdj"`
|
||||
}
|
||||
|
||||
// X509KeyPairStreaming contains the x509 configuration for streaming
|
||||
|
|
|
@ -416,12 +416,18 @@ func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxP
|
|||
|
||||
g.SetRootReadonly(securityContext.GetReadonlyRootfs())
|
||||
|
||||
setOCILinuxResource(&g, config.GetLinux().GetResources())
|
||||
|
||||
if sandboxConfig.GetLinux().GetCgroupParent() != "" {
|
||||
cgroupsPath := getCgroupsPath(sandboxConfig.GetLinux().GetCgroupParent(), id,
|
||||
c.config.SystemdCgroup)
|
||||
g.SetLinuxCgroupsPath(cgroupsPath)
|
||||
if c.config.DisableCgroup {
|
||||
g.SetLinuxCgroupsPath("")
|
||||
} else {
|
||||
setOCILinuxResourceCgroup(&g, config.GetLinux().GetResources())
|
||||
if sandboxConfig.GetLinux().GetCgroupParent() != "" {
|
||||
cgroupsPath := getCgroupsPath(sandboxConfig.GetLinux().GetCgroupParent(), id,
|
||||
c.config.SystemdCgroup)
|
||||
g.SetLinuxCgroupsPath(cgroupsPath)
|
||||
}
|
||||
}
|
||||
if err := setOCILinuxResourceOOMScoreAdj(&g, config.GetLinux().GetResources(), c.config.RestrictOOMScoreAdj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set namespaces, share namespace with sandbox container.
|
||||
|
@ -759,8 +765,8 @@ func setOCIBindMountsPrivileged(g *generator) {
|
|||
spec.Linux.MaskedPaths = nil
|
||||
}
|
||||
|
||||
// setOCILinuxResource set container resource limit.
|
||||
func setOCILinuxResource(g *generator, resources *runtime.LinuxContainerResources) {
|
||||
// setOCILinuxResourceCgroup set container cgroup resource limit.
|
||||
func setOCILinuxResourceCgroup(g *generator, resources *runtime.LinuxContainerResources) {
|
||||
if resources == nil {
|
||||
return
|
||||
}
|
||||
|
@ -768,11 +774,28 @@ func setOCILinuxResource(g *generator, resources *runtime.LinuxContainerResource
|
|||
g.SetLinuxResourcesCPUQuota(resources.GetCpuQuota())
|
||||
g.SetLinuxResourcesCPUShares(uint64(resources.GetCpuShares()))
|
||||
g.SetLinuxResourcesMemoryLimit(resources.GetMemoryLimitInBytes())
|
||||
g.SetProcessOOMScoreAdj(int(resources.GetOomScoreAdj()))
|
||||
g.SetLinuxResourcesCPUCpus(resources.GetCpusetCpus())
|
||||
g.SetLinuxResourcesCPUMems(resources.GetCpusetMems())
|
||||
}
|
||||
|
||||
// setOCILinuxResourceOOMScoreAdj set container OOMScoreAdj resource limit.
|
||||
func setOCILinuxResourceOOMScoreAdj(g *generator, resources *runtime.LinuxContainerResources, restrictOOMScoreAdjFlag bool) error {
|
||||
if resources == nil {
|
||||
return nil
|
||||
}
|
||||
adj := int(resources.GetOomScoreAdj())
|
||||
if restrictOOMScoreAdjFlag {
|
||||
var err error
|
||||
adj, err = restrictOOMScoreAdj(adj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
g.SetProcessOOMScoreAdj(adj)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getOCICapabilitiesList returns a list of all available capabilities.
|
||||
func getOCICapabilitiesList() []string {
|
||||
var caps []string
|
||||
|
|
|
@ -18,6 +18,7 @@ package server
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
@ -143,9 +144,9 @@ const (
|
|||
// generated is unique as long as sandbox metadata is unique.
|
||||
func makeSandboxName(s *runtime.PodSandboxMetadata) string {
|
||||
return strings.Join([]string{
|
||||
s.Name, // 0
|
||||
s.Namespace, // 1
|
||||
s.Uid, // 2
|
||||
s.Name, // 0
|
||||
s.Namespace, // 1
|
||||
s.Uid, // 2
|
||||
fmt.Sprintf("%d", s.Attempt), // 3
|
||||
}, nameDelimiter)
|
||||
}
|
||||
|
@ -155,10 +156,10 @@ func makeSandboxName(s *runtime.PodSandboxMetadata) string {
|
|||
// unique.
|
||||
func makeContainerName(c *runtime.ContainerMetadata, s *runtime.PodSandboxMetadata) string {
|
||||
return strings.Join([]string{
|
||||
c.Name, // 0
|
||||
s.Name, // 1: pod name
|
||||
s.Namespace, // 2: pod namespace
|
||||
s.Uid, // 3: pod uid
|
||||
c.Name, // 0
|
||||
s.Name, // 1: pod name
|
||||
s.Namespace, // 2: pod namespace
|
||||
s.Uid, // 3: pod uid
|
||||
fmt.Sprintf("%d", c.Attempt), // 4
|
||||
}, nameDelimiter)
|
||||
}
|
||||
|
@ -603,3 +604,27 @@ func getTaskStatus(ctx context.Context, task containerd.Task) (containerd.Status
|
|||
}
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func getCurrentOOMScoreAdj() (int, error) {
|
||||
b, err := ioutil.ReadFile("/proc/self/oom_score_adj")
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "could not get the daemon oom_score_adj")
|
||||
}
|
||||
s := strings.TrimSpace(string(b))
|
||||
i, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "could not get the daemon oom_score_adj")
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func restrictOOMScoreAdj(preferredOOMScoreAdj int) (int, error) {
|
||||
currentOOMScoreAdj, err := getCurrentOOMScoreAdj()
|
||||
if err != nil {
|
||||
return preferredOOMScoreAdj, err
|
||||
}
|
||||
if preferredOOMScoreAdj < currentOOMScoreAdj {
|
||||
return currentOOMScoreAdj, nil
|
||||
}
|
||||
return preferredOOMScoreAdj, nil
|
||||
}
|
||||
|
|
|
@ -371,10 +371,14 @@ func (c *criService) generateSandboxContainerSpec(id string, config *runtime.Pod
|
|||
// TODO(random-liu): [P2] Consider whether to add labels and annotations to the container.
|
||||
|
||||
// Set cgroups parent.
|
||||
if config.GetLinux().GetCgroupParent() != "" {
|
||||
cgroupsPath := getCgroupsPath(config.GetLinux().GetCgroupParent(), id,
|
||||
c.config.SystemdCgroup)
|
||||
g.SetLinuxCgroupsPath(cgroupsPath)
|
||||
if c.config.DisableCgroup {
|
||||
g.SetLinuxCgroupsPath("")
|
||||
} else {
|
||||
if config.GetLinux().GetCgroupParent() != "" {
|
||||
cgroupsPath := getCgroupsPath(config.GetLinux().GetCgroupParent(), id,
|
||||
c.config.SystemdCgroup)
|
||||
g.SetLinuxCgroupsPath(cgroupsPath)
|
||||
}
|
||||
}
|
||||
// When cgroup parent is not set, containerd-shim will create container in a child cgroup
|
||||
// of the cgroup itself is in.
|
||||
|
@ -431,8 +435,17 @@ func (c *criService) generateSandboxContainerSpec(id string, config *runtime.Pod
|
|||
|
||||
// Note: LinuxSandboxSecurityContext does not currently provide an apparmor profile
|
||||
|
||||
g.SetLinuxResourcesCPUShares(uint64(defaultSandboxCPUshares))
|
||||
g.SetProcessOOMScoreAdj(int(defaultSandboxOOMAdj))
|
||||
if !c.config.DisableCgroup {
|
||||
g.SetLinuxResourcesCPUShares(uint64(defaultSandboxCPUshares))
|
||||
}
|
||||
adj := int(defaultSandboxOOMAdj)
|
||||
if c.config.RestrictOOMScoreAdj {
|
||||
adj, err = restrictOOMScoreAdj(adj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
g.SetProcessOOMScoreAdj(adj)
|
||||
|
||||
g.AddAnnotation(annotations.ContainerType, annotations.ContainerTypeSandbox)
|
||||
g.AddAnnotation(annotations.SandboxID, id)
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
cni "github.com/containerd/go-cni"
|
||||
runcapparmor "github.com/opencontainers/runc/libcontainer/apparmor"
|
||||
runcseccomp "github.com/opencontainers/runc/libcontainer/seccomp"
|
||||
runcsystem "github.com/opencontainers/runc/libcontainer/system"
|
||||
"github.com/opencontainers/selinux/go-selinux"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -108,7 +109,7 @@ func NewCRIService(config criconfig.Config, client *containerd.Client) (CRIServi
|
|||
c := &criService{
|
||||
config: config,
|
||||
client: client,
|
||||
apparmorEnabled: runcapparmor.IsEnabled(),
|
||||
apparmorEnabled: runcapparmor.IsEnabled() && !config.DisableApparmor,
|
||||
seccompEnabled: runcseccomp.IsEnabled(),
|
||||
os: osinterface.RealOS{},
|
||||
sandboxStore: sandboxstore.NewStore(),
|
||||
|
@ -120,6 +121,12 @@ func NewCRIService(config criconfig.Config, client *containerd.Client) (CRIServi
|
|||
initialized: atomic.NewBool(false),
|
||||
}
|
||||
|
||||
if runcsystem.RunningInUserNS() {
|
||||
if !(config.DisableCgroup && !c.apparmorEnabled && config.RestrictOOMScoreAdj) {
|
||||
logrus.Warn("Running containerd in a user namespace typically requires disable_cgroup, disable_apparmor, restrict_oom_score_adj set to be true")
|
||||
}
|
||||
}
|
||||
|
||||
if c.config.EnableSelinux {
|
||||
if !selinux.GetEnabled() {
|
||||
logrus.Warn("Selinux is not supported")
|
||||
|
|
267
vendor/github.com/docker/distribution/registry/api/errcode/errors.go
generated
vendored
Normal file
267
vendor/github.com/docker/distribution/registry/api/errcode/errors.go
generated
vendored
Normal file
|
@ -0,0 +1,267 @@
|
|||
package errcode
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ErrorCoder is the base interface for ErrorCode and Error allowing
|
||||
// users of each to just call ErrorCode to get the real ID of each
|
||||
type ErrorCoder interface {
|
||||
ErrorCode() ErrorCode
|
||||
}
|
||||
|
||||
// ErrorCode represents the error type. The errors are serialized via strings
|
||||
// and the integer format may change and should *never* be exported.
|
||||
type ErrorCode int
|
||||
|
||||
var _ error = ErrorCode(0)
|
||||
|
||||
// ErrorCode just returns itself
|
||||
func (ec ErrorCode) ErrorCode() ErrorCode {
|
||||
return ec
|
||||
}
|
||||
|
||||
// Error returns the ID/Value
|
||||
func (ec ErrorCode) Error() string {
|
||||
// NOTE(stevvooe): Cannot use message here since it may have unpopulated args.
|
||||
return strings.ToLower(strings.Replace(ec.String(), "_", " ", -1))
|
||||
}
|
||||
|
||||
// Descriptor returns the descriptor for the error code.
|
||||
func (ec ErrorCode) Descriptor() ErrorDescriptor {
|
||||
d, ok := errorCodeToDescriptors[ec]
|
||||
|
||||
if !ok {
|
||||
return ErrorCodeUnknown.Descriptor()
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// String returns the canonical identifier for this error code.
|
||||
func (ec ErrorCode) String() string {
|
||||
return ec.Descriptor().Value
|
||||
}
|
||||
|
||||
// Message returned the human-readable error message for this error code.
|
||||
func (ec ErrorCode) Message() string {
|
||||
return ec.Descriptor().Message
|
||||
}
|
||||
|
||||
// MarshalText encodes the receiver into UTF-8-encoded text and returns the
|
||||
// result.
|
||||
func (ec ErrorCode) MarshalText() (text []byte, err error) {
|
||||
return []byte(ec.String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText decodes the form generated by MarshalText.
|
||||
func (ec *ErrorCode) UnmarshalText(text []byte) error {
|
||||
desc, ok := idToDescriptors[string(text)]
|
||||
|
||||
if !ok {
|
||||
desc = ErrorCodeUnknown.Descriptor()
|
||||
}
|
||||
|
||||
*ec = desc.Code
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithMessage creates a new Error struct based on the passed-in info and
|
||||
// overrides the Message property.
|
||||
func (ec ErrorCode) WithMessage(message string) Error {
|
||||
return Error{
|
||||
Code: ec,
|
||||
Message: message,
|
||||
}
|
||||
}
|
||||
|
||||
// WithDetail creates a new Error struct based on the passed-in info and
|
||||
// set the Detail property appropriately
|
||||
func (ec ErrorCode) WithDetail(detail interface{}) Error {
|
||||
return Error{
|
||||
Code: ec,
|
||||
Message: ec.Message(),
|
||||
}.WithDetail(detail)
|
||||
}
|
||||
|
||||
// WithArgs creates a new Error struct and sets the Args slice
|
||||
func (ec ErrorCode) WithArgs(args ...interface{}) Error {
|
||||
return Error{
|
||||
Code: ec,
|
||||
Message: ec.Message(),
|
||||
}.WithArgs(args...)
|
||||
}
|
||||
|
||||
// Error provides a wrapper around ErrorCode with extra Details provided.
|
||||
type Error struct {
|
||||
Code ErrorCode `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Detail interface{} `json:"detail,omitempty"`
|
||||
|
||||
// TODO(duglin): See if we need an "args" property so we can do the
|
||||
// variable substitution right before showing the message to the user
|
||||
}
|
||||
|
||||
var _ error = Error{}
|
||||
|
||||
// ErrorCode returns the ID/Value of this Error
|
||||
func (e Error) ErrorCode() ErrorCode {
|
||||
return e.Code
|
||||
}
|
||||
|
||||
// Error returns a human readable representation of the error.
|
||||
func (e Error) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.Code.Error(), e.Message)
|
||||
}
|
||||
|
||||
// WithDetail will return a new Error, based on the current one, but with
|
||||
// some Detail info added
|
||||
func (e Error) WithDetail(detail interface{}) Error {
|
||||
return Error{
|
||||
Code: e.Code,
|
||||
Message: e.Message,
|
||||
Detail: detail,
|
||||
}
|
||||
}
|
||||
|
||||
// WithArgs uses the passed-in list of interface{} as the substitution
|
||||
// variables in the Error's Message string, but returns a new Error
|
||||
func (e Error) WithArgs(args ...interface{}) Error {
|
||||
return Error{
|
||||
Code: e.Code,
|
||||
Message: fmt.Sprintf(e.Code.Message(), args...),
|
||||
Detail: e.Detail,
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorDescriptor provides relevant information about a given error code.
|
||||
type ErrorDescriptor struct {
|
||||
// Code is the error code that this descriptor describes.
|
||||
Code ErrorCode
|
||||
|
||||
// Value provides a unique, string key, often captilized with
|
||||
// underscores, to identify the error code. This value is used as the
|
||||
// keyed value when serializing api errors.
|
||||
Value string
|
||||
|
||||
// Message is a short, human readable decription of the error condition
|
||||
// included in API responses.
|
||||
Message string
|
||||
|
||||
// Description provides a complete account of the errors purpose, suitable
|
||||
// for use in documentation.
|
||||
Description string
|
||||
|
||||
// HTTPStatusCode provides the http status code that is associated with
|
||||
// this error condition.
|
||||
HTTPStatusCode int
|
||||
}
|
||||
|
||||
// ParseErrorCode returns the value by the string error code.
|
||||
// `ErrorCodeUnknown` will be returned if the error is not known.
|
||||
func ParseErrorCode(value string) ErrorCode {
|
||||
ed, ok := idToDescriptors[value]
|
||||
if ok {
|
||||
return ed.Code
|
||||
}
|
||||
|
||||
return ErrorCodeUnknown
|
||||
}
|
||||
|
||||
// Errors provides the envelope for multiple errors and a few sugar methods
|
||||
// for use within the application.
|
||||
type Errors []error
|
||||
|
||||
var _ error = Errors{}
|
||||
|
||||
func (errs Errors) Error() string {
|
||||
switch len(errs) {
|
||||
case 0:
|
||||
return "<nil>"
|
||||
case 1:
|
||||
return errs[0].Error()
|
||||
default:
|
||||
msg := "errors:\n"
|
||||
for _, err := range errs {
|
||||
msg += err.Error() + "\n"
|
||||
}
|
||||
return msg
|
||||
}
|
||||
}
|
||||
|
||||
// Len returns the current number of errors.
|
||||
func (errs Errors) Len() int {
|
||||
return len(errs)
|
||||
}
|
||||
|
||||
// MarshalJSON converts slice of error, ErrorCode or Error into a
|
||||
// slice of Error - then serializes
|
||||
func (errs Errors) MarshalJSON() ([]byte, error) {
|
||||
var tmpErrs struct {
|
||||
Errors []Error `json:"errors,omitempty"`
|
||||
}
|
||||
|
||||
for _, daErr := range errs {
|
||||
var err Error
|
||||
|
||||
switch daErr := daErr.(type) {
|
||||
case ErrorCode:
|
||||
err = daErr.WithDetail(nil)
|
||||
case Error:
|
||||
err = daErr
|
||||
default:
|
||||
err = ErrorCodeUnknown.WithDetail(daErr)
|
||||
|
||||
}
|
||||
|
||||
// If the Error struct was setup and they forgot to set the
|
||||
// Message field (meaning its "") then grab it from the ErrCode
|
||||
msg := err.Message
|
||||
if msg == "" {
|
||||
msg = err.Code.Message()
|
||||
}
|
||||
|
||||
tmpErrs.Errors = append(tmpErrs.Errors, Error{
|
||||
Code: err.Code,
|
||||
Message: msg,
|
||||
Detail: err.Detail,
|
||||
})
|
||||
}
|
||||
|
||||
return json.Marshal(tmpErrs)
|
||||
}
|
||||
|
||||
// UnmarshalJSON deserializes []Error and then converts it into slice of
|
||||
// Error or ErrorCode
|
||||
func (errs *Errors) UnmarshalJSON(data []byte) error {
|
||||
var tmpErrs struct {
|
||||
Errors []Error
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &tmpErrs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var newErrs Errors
|
||||
for _, daErr := range tmpErrs.Errors {
|
||||
// If Message is empty or exactly matches the Code's message string
|
||||
// then just use the Code, no need for a full Error struct
|
||||
if daErr.Detail == nil && (daErr.Message == "" || daErr.Message == daErr.Code.Message()) {
|
||||
// Error's w/o details get converted to ErrorCode
|
||||
newErrs = append(newErrs, daErr.Code)
|
||||
} else {
|
||||
// Error's w/ details are untouched
|
||||
newErrs = append(newErrs, Error{
|
||||
Code: daErr.Code,
|
||||
Message: daErr.Message,
|
||||
Detail: daErr.Detail,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
*errs = newErrs
|
||||
return nil
|
||||
}
|
40
vendor/github.com/docker/distribution/registry/api/errcode/handler.go
generated
vendored
Normal file
40
vendor/github.com/docker/distribution/registry/api/errcode/handler.go
generated
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
package errcode
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ServeJSON attempts to serve the errcode in a JSON envelope. It marshals err
|
||||
// and sets the content-type header to 'application/json'. It will handle
|
||||
// ErrorCoder and Errors, and if necessary will create an envelope.
|
||||
func ServeJSON(w http.ResponseWriter, err error) error {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
var sc int
|
||||
|
||||
switch errs := err.(type) {
|
||||
case Errors:
|
||||
if len(errs) < 1 {
|
||||
break
|
||||
}
|
||||
|
||||
if err, ok := errs[0].(ErrorCoder); ok {
|
||||
sc = err.ErrorCode().Descriptor().HTTPStatusCode
|
||||
}
|
||||
case ErrorCoder:
|
||||
sc = errs.ErrorCode().Descriptor().HTTPStatusCode
|
||||
err = Errors{err} // create an envelope.
|
||||
default:
|
||||
// We just have an unhandled error type, so just place in an envelope
|
||||
// and move along.
|
||||
err = Errors{err}
|
||||
}
|
||||
|
||||
if sc == 0 {
|
||||
sc = http.StatusInternalServerError
|
||||
}
|
||||
|
||||
w.WriteHeader(sc)
|
||||
|
||||
return json.NewEncoder(w).Encode(err)
|
||||
}
|
138
vendor/github.com/docker/distribution/registry/api/errcode/register.go
generated
vendored
Normal file
138
vendor/github.com/docker/distribution/registry/api/errcode/register.go
generated
vendored
Normal file
|
@ -0,0 +1,138 @@
|
|||
package errcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
errorCodeToDescriptors = map[ErrorCode]ErrorDescriptor{}
|
||||
idToDescriptors = map[string]ErrorDescriptor{}
|
||||
groupToDescriptors = map[string][]ErrorDescriptor{}
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrorCodeUnknown is a generic error that can be used as a last
|
||||
// resort if there is no situation-specific error message that can be used
|
||||
ErrorCodeUnknown = Register("errcode", ErrorDescriptor{
|
||||
Value: "UNKNOWN",
|
||||
Message: "unknown error",
|
||||
Description: `Generic error returned when the error does not have an
|
||||
API classification.`,
|
||||
HTTPStatusCode: http.StatusInternalServerError,
|
||||
})
|
||||
|
||||
// ErrorCodeUnsupported is returned when an operation is not supported.
|
||||
ErrorCodeUnsupported = Register("errcode", ErrorDescriptor{
|
||||
Value: "UNSUPPORTED",
|
||||
Message: "The operation is unsupported.",
|
||||
Description: `The operation was unsupported due to a missing
|
||||
implementation or invalid set of parameters.`,
|
||||
HTTPStatusCode: http.StatusMethodNotAllowed,
|
||||
})
|
||||
|
||||
// ErrorCodeUnauthorized is returned if a request requires
|
||||
// authentication.
|
||||
ErrorCodeUnauthorized = Register("errcode", ErrorDescriptor{
|
||||
Value: "UNAUTHORIZED",
|
||||
Message: "authentication required",
|
||||
Description: `The access controller was unable to authenticate
|
||||
the client. Often this will be accompanied by a
|
||||
Www-Authenticate HTTP response header indicating how to
|
||||
authenticate.`,
|
||||
HTTPStatusCode: http.StatusUnauthorized,
|
||||
})
|
||||
|
||||
// ErrorCodeDenied is returned if a client does not have sufficient
|
||||
// permission to perform an action.
|
||||
ErrorCodeDenied = Register("errcode", ErrorDescriptor{
|
||||
Value: "DENIED",
|
||||
Message: "requested access to the resource is denied",
|
||||
Description: `The access controller denied access for the
|
||||
operation on a resource.`,
|
||||
HTTPStatusCode: http.StatusForbidden,
|
||||
})
|
||||
|
||||
// ErrorCodeUnavailable provides a common error to report unavailability
|
||||
// of a service or endpoint.
|
||||
ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{
|
||||
Value: "UNAVAILABLE",
|
||||
Message: "service unavailable",
|
||||
Description: "Returned when a service is not available",
|
||||
HTTPStatusCode: http.StatusServiceUnavailable,
|
||||
})
|
||||
|
||||
// ErrorCodeTooManyRequests is returned if a client attempts too many
|
||||
// times to contact a service endpoint.
|
||||
ErrorCodeTooManyRequests = Register("errcode", ErrorDescriptor{
|
||||
Value: "TOOMANYREQUESTS",
|
||||
Message: "too many requests",
|
||||
Description: `Returned when a client attempts to contact a
|
||||
service too many times`,
|
||||
HTTPStatusCode: http.StatusTooManyRequests,
|
||||
})
|
||||
)
|
||||
|
||||
var nextCode = 1000
|
||||
var registerLock sync.Mutex
|
||||
|
||||
// Register will make the passed-in error known to the environment and
|
||||
// return a new ErrorCode
|
||||
func Register(group string, descriptor ErrorDescriptor) ErrorCode {
|
||||
registerLock.Lock()
|
||||
defer registerLock.Unlock()
|
||||
|
||||
descriptor.Code = ErrorCode(nextCode)
|
||||
|
||||
if _, ok := idToDescriptors[descriptor.Value]; ok {
|
||||
panic(fmt.Sprintf("ErrorValue %q is already registered", descriptor.Value))
|
||||
}
|
||||
if _, ok := errorCodeToDescriptors[descriptor.Code]; ok {
|
||||
panic(fmt.Sprintf("ErrorCode %v is already registered", descriptor.Code))
|
||||
}
|
||||
|
||||
groupToDescriptors[group] = append(groupToDescriptors[group], descriptor)
|
||||
errorCodeToDescriptors[descriptor.Code] = descriptor
|
||||
idToDescriptors[descriptor.Value] = descriptor
|
||||
|
||||
nextCode++
|
||||
return descriptor.Code
|
||||
}
|
||||
|
||||
type byValue []ErrorDescriptor
|
||||
|
||||
func (a byValue) Len() int { return len(a) }
|
||||
func (a byValue) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a byValue) Less(i, j int) bool { return a[i].Value < a[j].Value }
|
||||
|
||||
// GetGroupNames returns the list of Error group names that are registered
|
||||
func GetGroupNames() []string {
|
||||
keys := []string{}
|
||||
|
||||
for k := range groupToDescriptors {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// GetErrorCodeGroup returns the named group of error descriptors
|
||||
func GetErrorCodeGroup(name string) []ErrorDescriptor {
|
||||
desc := groupToDescriptors[name]
|
||||
sort.Sort(byValue(desc))
|
||||
return desc
|
||||
}
|
||||
|
||||
// GetErrorAllDescriptors returns a slice of all ErrorDescriptors that are
|
||||
// registered, irrespective of what group they're in
|
||||
func GetErrorAllDescriptors() []ErrorDescriptor {
|
||||
result := []ErrorDescriptor{}
|
||||
|
||||
for _, group := range GetGroupNames() {
|
||||
result = append(result, GetErrorCodeGroup(group)...)
|
||||
}
|
||||
sort.Sort(byValue(result))
|
||||
return result
|
||||
}
|
|
@ -7,7 +7,9 @@ curators:
|
|||
- ehazlett
|
||||
- fntlnz
|
||||
- gianarb
|
||||
- kolyshkin
|
||||
- mgoelzer
|
||||
- olljanat
|
||||
- programmerq
|
||||
- rheinwein
|
||||
- ripcurld0
|
||||
|
@ -15,3 +17,5 @@ curators:
|
|||
|
||||
features:
|
||||
- comments
|
||||
- pr_description_required
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@ Allen Sun <allensun.shl@alibaba-inc.com> <allen.sun@daocloud.io>
|
|||
Allen Sun <allensun.shl@alibaba-inc.com> <shlallen1990@gmail.com>
|
||||
Andrew Weiss <andrew.weiss@docker.com> <andrew.weiss@microsoft.com>
|
||||
Andrew Weiss <andrew.weiss@docker.com> <andrew.weiss@outlook.com>
|
||||
Andrey Kolomentsev <andrey.kolomentsev@docker.com>
|
||||
Andrey Kolomentsev <andrey.kolomentsev@docker.com> <andrey.kolomentsev@gmail.com>
|
||||
André Martins <aanm90@gmail.com> <martins@noironetworks.com>
|
||||
Andy Rothfusz <github@developersupport.net> <github@metaliveblog.com>
|
||||
Andy Smith <github@anarkystic.com>
|
||||
|
@ -55,9 +57,11 @@ Ben Bonnefoy <frenchben@docker.com>
|
|||
Ben Golub <ben.golub@dotcloud.com>
|
||||
Ben Toews <mastahyeti@gmail.com> <mastahyeti@users.noreply.github.com>
|
||||
Benoit Chesneau <bchesneau@gmail.com>
|
||||
Bevisy Zhang <binbin36520@gmail.com>
|
||||
Bhiraj Butala <abhiraj.butala@gmail.com>
|
||||
Bhumika Bayani <bhumikabayani@gmail.com>
|
||||
Bilal Amarni <bilal.amarni@gmail.com> <bamarni@users.noreply.github.com>
|
||||
Bily Zhang <xcoder@tenxcloud.com>
|
||||
Bill Wang <ozbillwang@gmail.com> <SydOps@users.noreply.github.com>
|
||||
Bin Liu <liubin0329@gmail.com>
|
||||
Bin Liu <liubin0329@gmail.com> <liubin0329@users.noreply.github.com>
|
||||
|
@ -77,6 +81,7 @@ Chen Chuanliang <chen.chuanliang@zte.com.cn>
|
|||
Chen Mingjie <chenmingjie0828@163.com>
|
||||
Chen Qiu <cheney-90@hotmail.com>
|
||||
Chen Qiu <cheney-90@hotmail.com> <21321229@zju.edu.cn>
|
||||
Chengfei Shang <cfshang@alauda.io>
|
||||
Chris Dias <cdias@microsoft.com>
|
||||
Chris McKinnel <chris.mckinnel@tangentlabs.co.uk>
|
||||
Christopher Biscardi <biscarch@sketcht.com>
|
||||
|
@ -97,6 +102,7 @@ Daniel Garcia <daniel@danielgarcia.info>
|
|||
Daniel Gasienica <daniel@gasienica.ch> <dgasienica@zynga.com>
|
||||
Daniel Goosen <daniel.goosen@surveysampling.com> <djgoosen@users.noreply.github.com>
|
||||
Daniel Grunwell <mwgrunny@gmail.com>
|
||||
Daniel Hiltgen <daniel.hiltgen@docker.com> <dhiltgen@users.noreply.github.com>
|
||||
Daniel J Walsh <dwalsh@redhat.com>
|
||||
Daniel Mizyrycki <daniel.mizyrycki@dotcloud.com> <daniel@dotcloud.com>
|
||||
Daniel Mizyrycki <daniel.mizyrycki@dotcloud.com> <mzdaniel@glidelink.net>
|
||||
|
@ -104,6 +110,7 @@ Daniel Mizyrycki <daniel.mizyrycki@dotcloud.com> <root@vagrant-ubuntu-12.10.vagr
|
|||
Daniel Nephin <dnephin@docker.com> <dnephin@gmail.com>
|
||||
Daniel Norberg <dano@spotify.com> <daniel.norberg@gmail.com>
|
||||
Daniel Watkins <daniel@daniel-watkins.co.uk>
|
||||
Daniel Zhang <jmzwcn@gmail.com>
|
||||
Danny Yates <danny@codeaholics.org> <Danny.Yates@mailonline.co.uk>
|
||||
Darren Shepherd <darren.s.shepherd@gmail.com> <darren@rancher.com>
|
||||
Dattatraya Kumbhar <dattatraya.kumbhar@gslab.com>
|
||||
|
@ -149,6 +156,7 @@ Frederick F. Kautz IV <fkautz@redhat.com> <fkautz@alumni.cmu.edu>
|
|||
Gabriel Nicolas Avellaneda <avellaneda.gabriel@gmail.com>
|
||||
Gaetan de Villele <gdevillele@gmail.com>
|
||||
Gang Qiao <qiaohai8866@gmail.com> <1373319223@qq.com>
|
||||
Geon Kim <geon0250@gmail.com>
|
||||
George Kontridze <george@bugsnag.com>
|
||||
Gerwim Feiken <g.feiken@tfe.nl> <gerwim@gmail.com>
|
||||
Giampaolo Mancini <giampaolo@trampolineup.com>
|
||||
|
@ -175,6 +183,7 @@ Harry Zhang <harryz@hyper.sh> <resouer@gmail.com>
|
|||
Harry Zhang <resouer@163.com>
|
||||
Harshal Patil <harshal.patil@in.ibm.com> <harche@users.noreply.github.com>
|
||||
Helen Xie <chenjg@harmonycloud.cn>
|
||||
Hiroyuki Sasagawa <hs19870702@gmail.com>
|
||||
Hollie Teal <hollie@docker.com>
|
||||
Hollie Teal <hollie@docker.com> <hollie.teal@docker.com>
|
||||
Hollie Teal <hollie@docker.com> <hollietealok@users.noreply.github.com>
|
||||
|
@ -183,26 +192,32 @@ Huu Nguyen <huu@prismskylabs.com> <whoshuu@gmail.com>
|
|||
Hyzhou Zhy <hyzhou.zhy@alibaba-inc.com>
|
||||
Hyzhou Zhy <hyzhou.zhy@alibaba-inc.com> <1187766782@qq.com>
|
||||
Ilya Khlopotov <ilya.khlopotov@gmail.com>
|
||||
Iskander Sharipov <quasilyte@gmail.com>
|
||||
Ivan Markin <sw@nogoegst.net> <twim@riseup.net>
|
||||
Jack Laxson <jackjrabbit@gmail.com>
|
||||
Jacob Atzen <jacob@jacobatzen.dk> <jatzen@gmail.com>
|
||||
Jacob Tomlinson <jacob@tom.linson.uk> <jacobtomlinson@users.noreply.github.com>
|
||||
Jaivish Kothari <janonymous.codevulture@gmail.com>
|
||||
Jamie Hannaford <jamie@limetree.org> <jamie.hannaford@rackspace.com>
|
||||
Jean Rouge <rougej+github@gmail.com> <jer329@cornell.edu>
|
||||
Jean-Baptiste Barth <jeanbaptiste.barth@gmail.com>
|
||||
Jean-Baptiste Dalido <jeanbaptiste@appgratis.com>
|
||||
Jean-Tiare Le Bigot <jt@yadutaf.fr> <admin@jtlebi.fr>
|
||||
Jeff Anderson <jeff@docker.com> <jefferya@programmerq.net>
|
||||
Jeff Nickoloff <jeff.nickoloff@gmail.com> <jeff@allingeek.com>
|
||||
Jeroen Franse <jeroenfranse@gmail.com>
|
||||
Jessica Frazelle <jessfraz@google.com>
|
||||
Jessica Frazelle <jessfraz@google.com> <acidburn@docker.com>
|
||||
Jessica Frazelle <jessfraz@google.com> <acidburn@google.com>
|
||||
Jessica Frazelle <jessfraz@google.com> <jess@docker.com>
|
||||
Jessica Frazelle <jessfraz@google.com> <jess@mesosphere.com>
|
||||
Jessica Frazelle <jessfraz@google.com> <jfrazelle@users.noreply.github.com>
|
||||
Jessica Frazelle <jessfraz@google.com> <me@jessfraz.com>
|
||||
Jessica Frazelle <jessfraz@google.com> <princess@docker.com>
|
||||
Jessica Frazelle <acidburn@microsoft.com>
|
||||
Jessica Frazelle <acidburn@microsoft.com> <acidburn@docker.com>
|
||||
Jessica Frazelle <acidburn@microsoft.com> <acidburn@google.com>
|
||||
Jessica Frazelle <acidburn@microsoft.com> <jess@docker.com>
|
||||
Jessica Frazelle <acidburn@microsoft.com> <jess@mesosphere.com>
|
||||
Jessica Frazelle <acidburn@microsoft.com> <jessfraz@google.com>
|
||||
Jessica Frazelle <acidburn@microsoft.com> <jfrazelle@users.noreply.github.com>
|
||||
Jessica Frazelle <acidburn@microsoft.com> <me@jessfraz.com>
|
||||
Jessica Frazelle <acidburn@microsoft.com> <princess@docker.com>
|
||||
Jian Liao <jliao@alauda.io>
|
||||
Jiang Jinyang <jjyruby@gmail.com>
|
||||
Jiang Jinyang <jjyruby@gmail.com> <jiangjinyang@outlook.com>
|
||||
Jim Galasyn <jim.galasyn@docker.com>
|
||||
Jiuyue Ma <majiuyue@huawei.com>
|
||||
Joey Geiger <jgeiger@gmail.com>
|
||||
|
@ -223,7 +238,9 @@ Jon Surrell <jon.surrell@gmail.com> <jon.surrell@automattic.com>
|
|||
Jordan Arentsen <blissdev@gmail.com>
|
||||
Jordan Jennings <jjn2009@gmail.com> <jjn2009@users.noreply.github.com>
|
||||
Jorit Kleine-Möllhoff <joppich@bricknet.de> <joppich@users.noreply.github.com>
|
||||
Jose Diaz-Gonzalez <jose@seatgeek.com> <josegonzalez@users.noreply.github.com>
|
||||
Jose Diaz-Gonzalez <email@josediazgonzalez.com>
|
||||
Jose Diaz-Gonzalez <email@josediazgonzalez.com> <jose@seatgeek.com>
|
||||
Jose Diaz-Gonzalez <email@josediazgonzalez.com> <josegonzalez@users.noreply.github.com>
|
||||
Josh Bonczkowski <josh.bonczkowski@gmail.com>
|
||||
Josh Eveleth <joshe@opendns.com> <jeveleth@users.noreply.github.com>
|
||||
Josh Hawn <josh.hawn@docker.com> <jlhawn@berkeley.edu>
|
||||
|
@ -237,6 +254,7 @@ Justin Cormack <justin.cormack@docker.com>
|
|||
Justin Cormack <justin.cormack@docker.com> <justin.cormack@unikernel.com>
|
||||
Justin Cormack <justin.cormack@docker.com> <justin@specialbusservice.com>
|
||||
Justin Simonelis <justin.p.simonelis@gmail.com> <justin.simonelis@PTS-JSIMON2.toronto.exclamation.com>
|
||||
Justin Terry <juterry@microsoft.com>
|
||||
Jérôme Petazzoni <jerome.petazzoni@docker.com> <jerome.petazzoni@dotcloud.com>
|
||||
Jérôme Petazzoni <jerome.petazzoni@docker.com> <jerome.petazzoni@gmail.com>
|
||||
Jérôme Petazzoni <jerome.petazzoni@docker.com> <jp@enix.org>
|
||||
|
@ -245,8 +263,11 @@ Kai Qiang Wu (Kennan) <wkq5325@gmail.com>
|
|||
Kai Qiang Wu (Kennan) <wkq5325@gmail.com> <wkqwu@cn.ibm.com>
|
||||
Kamil Domański <kamil@domanski.co>
|
||||
Kamjar Gerami <kami.gerami@gmail.com>
|
||||
Karthik Nayak <karthik.188@gmail.com>
|
||||
Karthik Nayak <karthik.188@gmail.com> <Karthik.188@gmail.com>
|
||||
Ken Cochrane <kencochrane@gmail.com> <KenCochrane@gmail.com>
|
||||
Ken Herner <kherner@progress.com> <chosenken@gmail.com>
|
||||
Ken Reese <krrgithub@gmail.com>
|
||||
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com>
|
||||
Kevin Feyrer <kevin.feyrer@btinternet.com> <kevinfeyrer@users.noreply.github.com>
|
||||
Kevin Kern <kaiwentan@harmonycloud.cn>
|
||||
|
@ -260,6 +281,7 @@ Konstantin Pelykh <kpelykh@zettaset.com>
|
|||
Kotaro Yoshimatsu <kotaro.yoshimatsu@gmail.com>
|
||||
Kunal Kushwaha <kushwaha_kunal_v7@lab.ntt.co.jp> <kunal.kushwaha@gmail.com>
|
||||
Lajos Papp <lajos.papp@sequenceiq.com> <lalyos@yahoo.com>
|
||||
Lei Gong <lgong@alauda.io>
|
||||
Lei Jitang <leijitang@huawei.com>
|
||||
Lei Jitang <leijitang@huawei.com> <leijitang@gmail.com>
|
||||
Liang Mingqiang <mqliang.zju@gmail.com>
|
||||
|
@ -268,7 +290,8 @@ Liao Qingwei <liaoqingwei@huawei.com>
|
|||
Linus Heckemann <lheckemann@twig-world.com>
|
||||
Linus Heckemann <lheckemann@twig-world.com> <anonymouse2048@gmail.com>
|
||||
Lokesh Mandvekar <lsm5@fedoraproject.org> <lsm5@redhat.com>
|
||||
Lorenzo Fontana <lo@linux.com> <fontanalorenzo@me.com>
|
||||
Lorenzo Fontana <fontanalorenz@gmail.com> <fontanalorenzo@me.com>
|
||||
Lorenzo Fontana <fontanalorenz@gmail.com> <lo@linux.com>
|
||||
Louis Opter <kalessin@kalessin.fr>
|
||||
Louis Opter <kalessin@kalessin.fr> <louis@dotcloud.com>
|
||||
Luca Favatella <luca.favatella@erlang-solutions.com> <lucafavatella@users.noreply.github.com>
|
||||
|
@ -315,6 +338,8 @@ Michael Nussbaum <michael.nussbaum@getbraintree.com>
|
|||
Michael Nussbaum <michael.nussbaum@getbraintree.com> <code@getbraintree.com>
|
||||
Michael Spetsiotis <michael_spets@hotmail.com>
|
||||
Michal Minář <miminar@redhat.com>
|
||||
Michiel de Jong <michiel@unhosted.org>
|
||||
Mickaël Fortunato <morsi.morsicus@gmail.com>
|
||||
Miguel Angel Alvarez Cabrerizo <doncicuto@gmail.com> <30386061+doncicuto@users.noreply.github.com>
|
||||
Miguel Angel Fernández <elmendalerenda@gmail.com>
|
||||
Mihai Borobocea <MihaiBorob@gmail.com> <MihaiBorobocea@gmail.com>
|
||||
|
@ -327,6 +352,7 @@ Moorthy RS <rsmoorthy@gmail.com> <rsmoorthy@users.noreply.github.com>
|
|||
Moysés Borges <moysesb@gmail.com>
|
||||
Moysés Borges <moysesb@gmail.com> <moyses.furtado@wplex.com.br>
|
||||
Nace Oroz <orkica@gmail.com>
|
||||
Natasha Jarus <linuxmercedes@gmail.com>
|
||||
Nathan LeClaire <nathan.leclaire@docker.com> <nathan.leclaire@gmail.com>
|
||||
Nathan LeClaire <nathan.leclaire@docker.com> <nathanleclaire@gmail.com>
|
||||
Neil Horman <nhorman@tuxdriver.com> <nhorman@hmswarspite.think-freely.org>
|
||||
|
@ -338,6 +364,9 @@ Nolan Darilek <nolan@thewordnerd.info>
|
|||
O.S. Tezer <ostezer@gmail.com>
|
||||
O.S. Tezer <ostezer@gmail.com> <ostezer@users.noreply.github.com>
|
||||
Oh Jinkyun <tintypemolly@gmail.com> <tintypemolly@Ohui-MacBook-Pro.local>
|
||||
Oliver Reason <oli@overrateddev.co>
|
||||
Olli Janatuinen <olli.janatuinen@gmail.com>
|
||||
Olli Janatuinen <olli.janatuinen@gmail.com> <olljanat@users.noreply.github.com>
|
||||
Ouyang Liduo <oyld0210@163.com>
|
||||
Patrick Stapleton <github@gdi2290.com>
|
||||
Paul Liljenberg <liljenberg.paul@gmail.com> <letters@paulnotcom.se>
|
||||
|
@ -359,7 +388,10 @@ Robert Terhaar <rterhaar@atlanticdynamic.com> <robbyt@users.noreply.github.com>
|
|||
Roberto G. Hashioka <roberto.hashioka@docker.com> <roberto_hashioka@hotmail.com>
|
||||
Roberto Muñoz Fernández <robertomf@gmail.com> <roberto.munoz.fernandez.contractor@bbva.com>
|
||||
Roman Dudin <katrmr@gmail.com> <decadent@users.noreply.github.com>
|
||||
Rong Zhang <rongzhang@alauda.io>
|
||||
Rongxiang Song <tinysong1226@gmail.com>
|
||||
Ross Boucher <rboucher@gmail.com>
|
||||
Rui Cao <ruicao@alauda.io>
|
||||
Runshen Zhu <runshen.zhu@gmail.com>
|
||||
Ryan Stelly <ryan.stelly@live.com>
|
||||
Sakeven Jiang <jc5930@sina.cn>
|
||||
|
@ -432,6 +464,7 @@ Tõnis Tiigi <tonistiigi@gmail.com>
|
|||
Trishna Guha <trishnaguha17@gmail.com>
|
||||
Tristan Carel <tristan@cogniteev.com>
|
||||
Tristan Carel <tristan@cogniteev.com> <tristan.carel@gmail.com>
|
||||
Tyler Brown <tylers.pile@gmail.com>
|
||||
Umesh Yadav <umesh4257@gmail.com>
|
||||
Umesh Yadav <umesh4257@gmail.com> <dungeonmaster18@users.noreply.github.com>
|
||||
Victor Lyuboslavsky <victor@victoreda.com>
|
||||
|
@ -464,8 +497,11 @@ Wei Wu <wuwei4455@gmail.com> cizixs <cizixs@163.com>
|
|||
Wenjun Tang <tangwj2@lenovo.com> <dodia@163.com>
|
||||
Wewang Xiaorenfine <wang.xiaoren@zte.com.cn>
|
||||
Will Weaver <monkey@buildingbananas.com>
|
||||
Xian Chaobo <xianchaobo@huawei.com>
|
||||
Xian Chaobo <xianchaobo@huawei.com> <jimmyxian2004@yahoo.com.cn>
|
||||
Xianglin Gao <xlgao@zju.edu.cn>
|
||||
Xianlu Bird <xianlubird@gmail.com>
|
||||
Xiaodong Zhang <a4012017@sina.com>
|
||||
Xiaoyu Zhang <zhang.xiaoyu33@zte.com.cn>
|
||||
Xuecong Liao <satorulogic@gmail.com>
|
||||
Yamasaki Masahide <masahide.y@gmail.com>
|
||||
|
@ -477,15 +513,18 @@ Yi EungJun <eungjun.yi@navercorp.com> <semtlenori@gmail.com>
|
|||
Ying Li <ying.li@docker.com>
|
||||
Ying Li <ying.li@docker.com> <cyli@twistedmatrix.com>
|
||||
Yong Tang <yong.tang.github@outlook.com> <yongtang@users.noreply.github.com>
|
||||
Yongxin Li <yxli@alauda.io>
|
||||
Yosef Fertel <yfertel@gmail.com> <frosforever@users.noreply.github.com>
|
||||
Yu Changchun <yuchangchun1@huawei.com>
|
||||
Yu Chengxia <yuchengxia@huawei.com>
|
||||
Yu Peng <yu.peng36@zte.com.cn>
|
||||
Yu Peng <yu.peng36@zte.com.cn> <yupeng36@zte.com.cn>
|
||||
Yue Zhang <zy675793960@yeah.net>
|
||||
Zachary Jaffee <zjaffee@us.ibm.com> <zij@case.edu>
|
||||
Zachary Jaffee <zjaffee@us.ibm.com> <zjaffee@apache.org>
|
||||
ZhangHang <stevezhang2014@gmail.com>
|
||||
Zhenkun Bi <bi.zhenkun@zte.com.cn>
|
||||
Zhoulin Xie <zhoulin.xie@daocloud.io>
|
||||
Zhou Hao <zhouhao@cn.fujitsu.com>
|
||||
Zhu Kunjia <zhu.kunjia@zte.com.cn>
|
||||
Zou Yu <zouyu7@huawei.com>
|
||||
|
|
|
@ -118,6 +118,7 @@ Andreas Köhler <andi5.py@gmx.net>
|
|||
Andreas Savvides <andreas@editd.com>
|
||||
Andreas Tiefenthaler <at@an-ti.eu>
|
||||
Andrei Gherzan <andrei@resin.io>
|
||||
Andrei Vagin <avagin@gmail.com>
|
||||
Andrew C. Bodine <acbodine@us.ibm.com>
|
||||
Andrew Clay Shafer <andrewcshafer@gmail.com>
|
||||
Andrew Duckworth <grillopress@gmail.com>
|
||||
|
@ -137,6 +138,7 @@ Andrew Po <absourd.noise@gmail.com>
|
|||
Andrew Weiss <andrew.weiss@docker.com>
|
||||
Andrew Williams <williams.andrew@gmail.com>
|
||||
Andrews Medina <andrewsmedina@gmail.com>
|
||||
Andrey Kolomentsev <andrey.kolomentsev@docker.com>
|
||||
Andrey Petrov <andrey.petrov@shazow.net>
|
||||
Andrey Stolbovsky <andrey.stolbovsky@gmail.com>
|
||||
André Martins <aanm90@gmail.com>
|
||||
|
@ -195,23 +197,27 @@ bdevloed <boris.de.vloed@gmail.com>
|
|||
Ben Bonnefoy <frenchben@docker.com>
|
||||
Ben Firshman <ben@firshman.co.uk>
|
||||
Ben Golub <ben.golub@dotcloud.com>
|
||||
Ben Gould <ben@bengould.co.uk>
|
||||
Ben Hall <ben@benhall.me.uk>
|
||||
Ben Sargent <ben@brokendigits.com>
|
||||
Ben Severson <BenSeverson@users.noreply.github.com>
|
||||
Ben Toews <mastahyeti@gmail.com>
|
||||
Ben Wiklund <ben@daisyowl.com>
|
||||
Benjamin Atkin <ben@benatkin.com>
|
||||
Benjamin Baker <Benjamin.baker@utexas.edu>
|
||||
Benjamin Boudreau <boudreau.benjamin@gmail.com>
|
||||
Benjamin Yolken <yolken@stripe.com>
|
||||
Benoit Chesneau <bchesneau@gmail.com>
|
||||
Bernerd Schaefer <bj.schaefer@gmail.com>
|
||||
Bernhard M. Wiedemann <bwiedemann@suse.de>
|
||||
Bert Goethals <bert@bertg.be>
|
||||
Bevisy Zhang <binbin36520@gmail.com>
|
||||
Bharath Thiruveedula <bharath_ves@hotmail.com>
|
||||
Bhiraj Butala <abhiraj.butala@gmail.com>
|
||||
Bhumika Bayani <bhumikabayani@gmail.com>
|
||||
Bilal Amarni <bilal.amarni@gmail.com>
|
||||
Bill Wang <ozbillwang@gmail.com>
|
||||
Bily Zhang <xcoder@tenxcloud.com>
|
||||
Bin Liu <liubin0329@gmail.com>
|
||||
Bingshen Wang <bingshen.wbs@alibaba-inc.com>
|
||||
Blake Geno <blakegeno@gmail.com>
|
||||
|
@ -246,6 +252,7 @@ Brian Torres-Gil <brian@dralth.com>
|
|||
Brian Trump <btrump@yelp.com>
|
||||
Brice Jaglin <bjaglin@teads.tv>
|
||||
Briehan Lombaard <briehan.lombaard@gmail.com>
|
||||
Brielle Broder <bbroder@google.com>
|
||||
Bruno Bigras <bigras.bruno@gmail.com>
|
||||
Bruno Binet <bruno.binet@gmail.com>
|
||||
Bruno Gazzera <bgazzera@paginar.com>
|
||||
|
@ -300,6 +307,7 @@ Chen Min <chenmin46@huawei.com>
|
|||
Chen Mingjie <chenmingjie0828@163.com>
|
||||
Chen Qiu <cheney-90@hotmail.com>
|
||||
Cheng-mean Liu <soccerl@microsoft.com>
|
||||
Chengfei Shang <cfshang@alauda.io>
|
||||
Chengguang Xu <cgxu519@gmx.com>
|
||||
chenyuzhu <chenyuzhi@oschina.cn>
|
||||
Chetan Birajdar <birajdar.chetan@gmail.com>
|
||||
|
@ -325,9 +333,11 @@ Chris Swan <chris.swan@iee.org>
|
|||
Chris Telfer <ctelfer@docker.com>
|
||||
Chris Wahl <github@wahlnetwork.com>
|
||||
Chris Weyl <cweyl@alumni.drew.edu>
|
||||
Chris White <me@cwprogram.com>
|
||||
Christian Berendt <berendt@b1-systems.de>
|
||||
Christian Brauner <christian.brauner@ubuntu.com>
|
||||
Christian Böhme <developement@boehme3d.de>
|
||||
Christian Muehlhaeuser <muesli@gmail.com>
|
||||
Christian Persson <saser@live.se>
|
||||
Christian Rotzoll <ch.rotzoll@gmail.com>
|
||||
Christian Simon <simon@swine.de>
|
||||
|
@ -350,6 +360,7 @@ Cody Roseborough <crrosebo@amazon.com>
|
|||
Coenraad Loubser <coenraad@wish.org.za>
|
||||
Colin Dunklau <colin.dunklau@gmail.com>
|
||||
Colin Hebert <hebert.colin@gmail.com>
|
||||
Colin Panisset <github@clabber.com>
|
||||
Colin Rice <colin@daedrum.net>
|
||||
Colin Walters <walters@verbum.org>
|
||||
Collin Guarino <collin.guarino@gmail.com>
|
||||
|
@ -385,6 +396,7 @@ Dan Levy <dan@danlevy.net>
|
|||
Dan McPherson <dmcphers@redhat.com>
|
||||
Dan Stine <sw@stinemail.com>
|
||||
Dan Williams <me@deedubs.com>
|
||||
Dani Hodovic <dani.hodovic@gmail.com>
|
||||
Dani Louca <dani.louca@docker.com>
|
||||
Daniel Antlinger <d.antlinger@gmx.at>
|
||||
Daniel Dao <dqminh@cloudflare.com>
|
||||
|
@ -438,12 +450,14 @@ David Mackey <tdmackey@booleanhaiku.com>
|
|||
David Mat <david@davidmat.com>
|
||||
David Mcanulty <github@hellspark.com>
|
||||
David McKay <david@rawkode.com>
|
||||
David P Hilton <david.hilton.p@gmail.com>
|
||||
David Pelaez <pelaez89@gmail.com>
|
||||
David R. Jenni <david.r.jenni@gmail.com>
|
||||
David Röthlisberger <david@rothlis.net>
|
||||
David Sheets <dsheets@docker.com>
|
||||
David Sissitka <me@dsissitka.com>
|
||||
David Trott <github@davidtrott.com>
|
||||
David Wang <00107082@163.com>
|
||||
David Williamson <david.williamson@docker.com>
|
||||
David Xia <dxia@spotify.com>
|
||||
David Young <yangboh@cn.ibm.com>
|
||||
|
@ -451,8 +465,10 @@ Davide Ceretti <davide.ceretti@hogarthww.com>
|
|||
Dawn Chen <dawnchen@google.com>
|
||||
dbdd <wangtong2712@gmail.com>
|
||||
dcylabs <dcylabs@gmail.com>
|
||||
Debayan De <debayande@users.noreply.github.com>
|
||||
Deborah Gertrude Digges <deborah.gertrude.digges@gmail.com>
|
||||
deed02392 <georgehafiz@gmail.com>
|
||||
Deep Debroy <ddebroy@docker.com>
|
||||
Deng Guangxing <dengguangxing@huawei.com>
|
||||
Deni Bertovic <deni@kset.org>
|
||||
Denis Defreyne <denis@soundcloud.com>
|
||||
|
@ -477,6 +493,7 @@ Dieter Reuter <dieter.reuter@me.com>
|
|||
Dillon Dixon <dillondixon@gmail.com>
|
||||
Dima Stopel <dima@twistlock.com>
|
||||
Dimitri John Ledkov <dimitri.j.ledkov@intel.com>
|
||||
Dimitris Mandalidis <dimitris.mandalidis@gmail.com>
|
||||
Dimitris Rozakis <dimrozakis@gmail.com>
|
||||
Dimitry Andric <d.andric@activevideo.com>
|
||||
Dinesh Subhraveti <dineshs@altiscale.com>
|
||||
|
@ -503,6 +520,7 @@ Don Kjer <don.kjer@gmail.com>
|
|||
Don Spaulding <donspauldingii@gmail.com>
|
||||
Donald Huang <don.hcd@gmail.com>
|
||||
Dong Chen <dongluo.chen@docker.com>
|
||||
Donghwa Kim <shanytt@gmail.com>
|
||||
Donovan Jones <git@gamma.net.nz>
|
||||
Doron Podoleanu <doronp@il.ibm.com>
|
||||
Doug Davis <dug@us.ibm.com>
|
||||
|
@ -579,7 +597,9 @@ Ewa Czechowska <ewa@ai-traders.com>
|
|||
Eystein Måløy Stenberg <eystein.maloy.stenberg@cfengine.com>
|
||||
ezbercih <cem.ezberci@gmail.com>
|
||||
Ezra Silvera <ezra@il.ibm.com>
|
||||
Fabian Kramm <kramm@covexo.com>
|
||||
Fabian Lauer <kontakt@softwareschmiede-saar.de>
|
||||
Fabian Raetz <fabian.raetz@gmail.com>
|
||||
Fabiano Rosas <farosas@br.ibm.com>
|
||||
Fabio Falci <fabiofalci@gmail.com>
|
||||
Fabio Kung <fabio.kung@gmail.com>
|
||||
|
@ -591,6 +611,7 @@ Faiz Khan <faizkhan00@gmail.com>
|
|||
falmp <chico.lopes@gmail.com>
|
||||
Fangming Fang <fangming.fang@arm.com>
|
||||
Fangyuan Gao <21551127@zju.edu.cn>
|
||||
fanjiyun <fan.jiyun@zte.com.cn>
|
||||
Fareed Dudhia <fareeddudhia@googlemail.com>
|
||||
Fathi Boudra <fathi.boudra@linaro.org>
|
||||
Federico Gimenez <fgimenez@coit.es>
|
||||
|
@ -621,6 +642,7 @@ Florin Patan <florinpatan@gmail.com>
|
|||
fonglh <fonglh@gmail.com>
|
||||
Foysal Iqbal <foysal.iqbal.fb@gmail.com>
|
||||
Francesc Campoy <campoy@google.com>
|
||||
Francesco Mari <mari.francesco@gmail.com>
|
||||
Francis Chuang <francis.chuang@boostport.com>
|
||||
Francisco Carriedo <fcarriedo@gmail.com>
|
||||
Francisco Souza <f@souza.cc>
|
||||
|
@ -653,6 +675,7 @@ Gaël PORTAY <gael.portay@savoirfairelinux.com>
|
|||
Genki Takiuchi <genki@s21g.com>
|
||||
GennadySpb <lipenkov@gmail.com>
|
||||
Geoffrey Bachelet <grosfrais@gmail.com>
|
||||
Geon Kim <geon0250@gmail.com>
|
||||
George Kontridze <george@bugsnag.com>
|
||||
George MacRorie <gmacr31@gmail.com>
|
||||
George Xie <georgexsh@gmail.com>
|
||||
|
@ -676,6 +699,7 @@ Gopikannan Venugopalsamy <gopikannan.venugopalsamy@gmail.com>
|
|||
Gosuke Miyashita <gosukenator@gmail.com>
|
||||
Gou Rao <gou@portworx.com>
|
||||
Govinda Fichtner <govinda.fichtner@googlemail.com>
|
||||
Grant Millar <grant@cylo.io>
|
||||
Grant Reaber <grant.reaber@gmail.com>
|
||||
Graydon Hoare <graydon@pobox.com>
|
||||
Greg Fausak <greg@tacodata.com>
|
||||
|
@ -694,7 +718,9 @@ Guruprasad <lgp171188@gmail.com>
|
|||
Gustav Sinder <gustav.sinder@gmail.com>
|
||||
gwx296173 <gaojing3@huawei.com>
|
||||
Günter Zöchbauer <guenter@gzoechbauer.com>
|
||||
haikuoliu <haikuo@amazon.com>
|
||||
Hakan Özler <hakan.ozler@kodcu.com>
|
||||
Hamish Hutchings <moredhel@aoeu.me>
|
||||
Hans Kristian Flaatten <hans@starefossen.com>
|
||||
Hans Rødtang <hansrodtang@gmail.com>
|
||||
Hao Shu Wei <haosw@cn.ibm.com>
|
||||
|
@ -702,6 +728,7 @@ Hao Zhang <21521210@zju.edu.cn>
|
|||
Harald Albers <github@albersweb.de>
|
||||
Harley Laue <losinggeneration@gmail.com>
|
||||
Harold Cooper <hrldcpr@gmail.com>
|
||||
Harrison Turton <harrisonturton@gmail.com>
|
||||
Harry Zhang <harryz@hyper.sh>
|
||||
Harshal Patil <harshal.patil@in.ibm.com>
|
||||
Harshal Patil <harshalp@linux.vnet.ibm.com>
|
||||
|
@ -713,6 +740,7 @@ Hector Castro <hectcastro@gmail.com>
|
|||
Helen Xie <chenjg@harmonycloud.cn>
|
||||
Henning Sprang <henning.sprang@gmail.com>
|
||||
Hiroshi Hatake <hatake@clear-code.com>
|
||||
Hiroyuki Sasagawa <hs19870702@gmail.com>
|
||||
Hobofan <goisser94@gmail.com>
|
||||
Hollie Teal <hollie@docker.com>
|
||||
Hong Xu <hong@topbug.net>
|
||||
|
@ -735,6 +763,7 @@ Ian Bishop <ianbishop@pace7.com>
|
|||
Ian Bull <irbull@gmail.com>
|
||||
Ian Calvert <ianjcalvert@gmail.com>
|
||||
Ian Campbell <ian.campbell@docker.com>
|
||||
Ian Chen <ianre657@gmail.com>
|
||||
Ian Lee <IanLee1521@gmail.com>
|
||||
Ian Main <imain@redhat.com>
|
||||
Ian Philpot <ian.philpot@microsoft.com>
|
||||
|
@ -752,9 +781,11 @@ Ilya Khlopotov <ilya.khlopotov@gmail.com>
|
|||
imre Fitos <imre.fitos+github@gmail.com>
|
||||
inglesp <peter.inglesby@gmail.com>
|
||||
Ingo Gottwald <in.gottwald@gmail.com>
|
||||
Innovimax <innovimax@gmail.com>
|
||||
Isaac Dupree <antispam@idupree.com>
|
||||
Isabel Jimenez <contact.isabeljimenez@gmail.com>
|
||||
Isao Jonas <isao.jonas@gmail.com>
|
||||
Iskander Sharipov <quasilyte@gmail.com>
|
||||
Ivan Babrou <ibobrik@gmail.com>
|
||||
Ivan Fraixedes <ifcdev@gmail.com>
|
||||
Ivan Grcic <igrcic@gmail.com>
|
||||
|
@ -785,6 +816,7 @@ James Mills <prologic@shortcircuit.net.au>
|
|||
James Nesbitt <james.nesbitt@wunderkraut.com>
|
||||
James Nugent <james@jen20.com>
|
||||
James Turnbull <james@lovedthanlost.net>
|
||||
James Watkins-Harvey <jwatkins@progi-media.com>
|
||||
Jamie Hannaford <jamie@limetree.org>
|
||||
Jamshid Afshar <jafshar@yahoo.com>
|
||||
Jan Keromnes <janx@linux.com>
|
||||
|
@ -817,6 +849,7 @@ jaxgeller <jacksongeller@gmail.com>
|
|||
Jay <imjching@hotmail.com>
|
||||
Jay <teguhwpurwanto@gmail.com>
|
||||
Jay Kamat <github@jgkamat.33mail.com>
|
||||
Jean Rouge <rougej+github@gmail.com>
|
||||
Jean-Baptiste Barth <jeanbaptiste.barth@gmail.com>
|
||||
Jean-Baptiste Dalido <jeanbaptiste@appgratis.com>
|
||||
Jean-Christophe Berthon <huygens@berthon.eu>
|
||||
|
@ -847,11 +880,13 @@ Jeroen Franse <jeroenfranse@gmail.com>
|
|||
Jeroen Jacobs <github@jeroenj.be>
|
||||
Jesse Dearing <jesse.dearing@gmail.com>
|
||||
Jesse Dubay <jesse@thefortytwo.net>
|
||||
Jessica Frazelle <jessfraz@google.com>
|
||||
Jessica Frazelle <acidburn@microsoft.com>
|
||||
Jezeniel Zapanta <jpzapanta22@gmail.com>
|
||||
Jhon Honce <jhonce@redhat.com>
|
||||
Ji.Zhilong <zhilongji@gmail.com>
|
||||
Jian Liao <jliao@alauda.io>
|
||||
Jian Zhang <zhangjian.fnst@cn.fujitsu.com>
|
||||
Jiang Jinyang <jjyruby@gmail.com>
|
||||
Jie Luo <luo612@zju.edu.cn>
|
||||
Jihyun Hwang <jhhwang@telcoware.com>
|
||||
Jilles Oldenbeuving <ojilles@gmail.com>
|
||||
|
@ -862,14 +897,13 @@ Jim Perrin <jperrin@centos.org>
|
|||
Jimmy Cuadra <jimmy@jimmycuadra.com>
|
||||
Jimmy Puckett <jimmy.puckett@spinen.com>
|
||||
Jimmy Song <rootsongjc@gmail.com>
|
||||
jimmyxian <jimmyxian2004@yahoo.com.cn>
|
||||
Jinsoo Park <cellpjs@gmail.com>
|
||||
Jiri Appl <jiria@microsoft.com>
|
||||
Jiri Popelka <jpopelka@redhat.com>
|
||||
Jiuyue Ma <majiuyue@huawei.com>
|
||||
Jiří Župka <jzupka@redhat.com>
|
||||
jjy <jiangjinyang@outlook.com>
|
||||
jmzwcn <jmzwcn@gmail.com>
|
||||
Joao Fernandes <joao.fernandes@docker.com>
|
||||
Joao Trindade <trindade.joao@gmail.com>
|
||||
Joe Beda <joe.github@bedafamily.com>
|
||||
Joe Doliner <jdoliner@pachyderm.io>
|
||||
Joe Ferguson <joe@infosiftr.com>
|
||||
|
@ -908,6 +942,7 @@ Jon Johnson <jonjohnson@google.com>
|
|||
Jon Surrell <jon.surrell@gmail.com>
|
||||
Jon Wedaman <jweede@gmail.com>
|
||||
Jonas Pfenniger <jonas@pfenniger.name>
|
||||
Jonathan A. Schweder <jonathanschweder@gmail.com>
|
||||
Jonathan A. Sternberg <jonathansternberg@gmail.com>
|
||||
Jonathan Boulle <jonathanboulle@gmail.com>
|
||||
Jonathan Camp <jonathan@irondojo.com>
|
||||
|
@ -928,7 +963,7 @@ Jordan Jennings <jjn2009@gmail.com>
|
|||
Jordan Sissel <jls@semicomplete.com>
|
||||
Jorge Marin <chipironcin@users.noreply.github.com>
|
||||
Jorit Kleine-Möllhoff <joppich@bricknet.de>
|
||||
Jose Diaz-Gonzalez <jose@seatgeek.com>
|
||||
Jose Diaz-Gonzalez <email@josediazgonzalez.com>
|
||||
Joseph Anthony Pasquale Holsten <joseph@josephholsten.com>
|
||||
Joseph Hager <ajhager@gmail.com>
|
||||
Joseph Kern <jkern@semafour.net>
|
||||
|
@ -982,7 +1017,8 @@ kargakis <kargakis@users.noreply.github.com>
|
|||
Karl Grzeszczak <karlgrz@gmail.com>
|
||||
Karol Duleba <mr.fuxi@gmail.com>
|
||||
Karthik Karanth <karanth.karthik@gmail.com>
|
||||
Karthik Nayak <Karthik.188@gmail.com>
|
||||
Karthik Nayak <karthik.188@gmail.com>
|
||||
Kasper Fabæch Brandt <poizan@poizan.dk>
|
||||
Kate Heddleston <kate.heddleston@gmail.com>
|
||||
Katie McLaughlin <katie@glasnt.com>
|
||||
Kato Kazuyoshi <kato.kazuyoshi@gmail.com>
|
||||
|
@ -990,6 +1026,7 @@ Katrina Owen <katrina.owen@gmail.com>
|
|||
Kawsar Saiyeed <kawsar.saiyeed@projiris.com>
|
||||
Kay Yan <kay.yan@daocloud.io>
|
||||
kayrus <kay.diam@gmail.com>
|
||||
Kazuhiro Sera <seratch@gmail.com>
|
||||
Ke Li <kel@splunk.com>
|
||||
Ke Xu <leonhartx.k@gmail.com>
|
||||
Kei Ohmura <ohmura.kei@gmail.com>
|
||||
|
@ -998,6 +1035,7 @@ Keli Hu <dev@keli.hu>
|
|||
Ken Cochrane <kencochrane@gmail.com>
|
||||
Ken Herner <kherner@progress.com>
|
||||
Ken ICHIKAWA <ichikawa.ken@jp.fujitsu.com>
|
||||
Ken Reese <krrgithub@gmail.com>
|
||||
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com>
|
||||
Kenjiro Nakayama <nakayamakenjiro@gmail.com>
|
||||
Kent Johnson <kentoj@gmail.com>
|
||||
|
@ -1035,9 +1073,10 @@ Krasimir Georgiev <support@vip-consult.co.uk>
|
|||
Kris-Mikael Krister <krismikael@protonmail.com>
|
||||
Kristian Haugene <kristian.haugene@capgemini.com>
|
||||
Kristina Zabunova <triara.xiii@gmail.com>
|
||||
krrg <krrgithub@gmail.com>
|
||||
Krystian Wojcicki <kwojcicki@sympatico.ca>
|
||||
Kun Zhang <zkazure@gmail.com>
|
||||
Kunal Kushwaha <kushwaha_kunal_v7@lab.ntt.co.jp>
|
||||
Kunal Tyagi <tyagi.kunal@live.com>
|
||||
Kyle Conroy <kyle.j.conroy@gmail.com>
|
||||
Kyle Linden <linden.kyle@gmail.com>
|
||||
kyu <leehk1227@gmail.com>
|
||||
|
@ -1060,6 +1099,7 @@ Leandro Siqueira <leandro.siqueira@gmail.com>
|
|||
Lee Chao <932819864@qq.com>
|
||||
Lee, Meng-Han <sunrisedm4@gmail.com>
|
||||
leeplay <hyeongkyu.lee@navercorp.com>
|
||||
Lei Gong <lgong@alauda.io>
|
||||
Lei Jitang <leijitang@huawei.com>
|
||||
Len Weincier <len@cloudafrica.net>
|
||||
Lennie <github@consolejunkie.net>
|
||||
|
@ -1076,6 +1116,8 @@ Liana Lo <liana.lixia@gmail.com>
|
|||
Liang Mingqiang <mqliang.zju@gmail.com>
|
||||
Liang-Chi Hsieh <viirya@gmail.com>
|
||||
Liao Qingwei <liaoqingwei@huawei.com>
|
||||
Lifubang <lifubang@acmcoder.com>
|
||||
Lihua Tang <lhtang@alauda.io>
|
||||
Lily Guo <lily.guo@docker.com>
|
||||
limsy <seongyeol37@gmail.com>
|
||||
Lin Lu <doraalin@163.com>
|
||||
|
@ -1094,7 +1136,8 @@ Lloyd Dewolf <foolswisdom@gmail.com>
|
|||
Lokesh Mandvekar <lsm5@fedoraproject.org>
|
||||
longliqiang88 <394564827@qq.com>
|
||||
Lorenz Leutgeb <lorenz.leutgeb@gmail.com>
|
||||
Lorenzo Fontana <lo@linux.com>
|
||||
Lorenzo Fontana <fontanalorenz@gmail.com>
|
||||
Lotus Fenn <fenn.lotus@gmail.com>
|
||||
Louis Opter <kalessin@kalessin.fr>
|
||||
Luca Favatella <luca.favatella@erlang-solutions.com>
|
||||
Luca Marturana <lucamarturana@gmail.com>
|
||||
|
@ -1151,6 +1194,7 @@ Marius Gundersen <me@mariusgundersen.net>
|
|||
Marius Sturm <marius@graylog.com>
|
||||
Marius Voila <marius.voila@gmail.com>
|
||||
Mark Allen <mrallen1@yahoo.com>
|
||||
Mark Jeromin <mark.jeromin@sysfrog.net>
|
||||
Mark McGranaghan <mmcgrana@gmail.com>
|
||||
Mark McKinstry <mmckinst@umich.edu>
|
||||
Mark Milstein <mark@epiloque.com>
|
||||
|
@ -1167,6 +1211,7 @@ Martijn van Oosterhout <kleptog@svana.org>
|
|||
Martin Honermeyer <maze@strahlungsfrei.de>
|
||||
Martin Kelly <martin@surround.io>
|
||||
Martin Mosegaard Amdisen <martin.amdisen@praqma.com>
|
||||
Martin Muzatko <martin@happy-css.com>
|
||||
Martin Redmond <redmond.martin@gmail.com>
|
||||
Mary Anthony <mary.anthony@docker.com>
|
||||
Masahito Zembutsu <zembutsu@users.noreply.github.com>
|
||||
|
@ -1200,6 +1245,7 @@ Matthias Klumpp <matthias@tenstral.net>
|
|||
Matthias Kühnle <git.nivoc@neverbox.com>
|
||||
Matthias Rampke <mr@soundcloud.com>
|
||||
Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
|
||||
Mattias Jernberg <nostrad@gmail.com>
|
||||
Mauricio Garavaglia <mauricio@medallia.com>
|
||||
mauriyouth <mauriyouth@gmail.com>
|
||||
Max Shytikov <mshytikov@gmail.com>
|
||||
|
@ -1208,6 +1254,7 @@ Maxim Ivanov <ivanov.maxim@gmail.com>
|
|||
Maxim Kulkin <mkulkin@mirantis.com>
|
||||
Maxim Treskin <zerthurd@gmail.com>
|
||||
Maxime Petazzoni <max@signalfuse.com>
|
||||
Maximiliano Maccanti <maccanti@amazon.com>
|
||||
Meaglith Ma <genedna@gmail.com>
|
||||
meejah <meejah@meejah.ca>
|
||||
Megan Kostick <mkostick@us.ibm.com>
|
||||
|
@ -1248,8 +1295,9 @@ Michal Wieczorek <wieczorek-michal@wp.pl>
|
|||
Michaël Pailloncy <mpapo.dev@gmail.com>
|
||||
Michał Czeraszkiewicz <czerasz@gmail.com>
|
||||
Michał Gryko <github@odkurzacz.org>
|
||||
Michiel@unhosted <michiel@unhosted.org>
|
||||
Mickaël FORTUNATO <morsi.morsicus@gmail.com>
|
||||
Michiel de Jong <michiel@unhosted.org>
|
||||
Mickaël Fortunato <morsi.morsicus@gmail.com>
|
||||
Mickaël Remars <mickael@remars.com>
|
||||
Miguel Angel Fernández <elmendalerenda@gmail.com>
|
||||
Miguel Morales <mimoralea@gmail.com>
|
||||
Mihai Borobocea <MihaiBorob@gmail.com>
|
||||
|
@ -1280,6 +1328,7 @@ Mitch Capper <mitch.capper@gmail.com>
|
|||
Mizuki Urushida <z11111001011@gmail.com>
|
||||
mlarcher <github@ringabell.org>
|
||||
Mohammad Banikazemi <mb@us.ibm.com>
|
||||
Mohammad Nasirifar <farnasirim@gmail.com>
|
||||
Mohammed Aaqib Ansari <maaquib@gmail.com>
|
||||
Mohit Soni <mosoni@ebay.com>
|
||||
Moorthy RS <rsmoorthy@gmail.com>
|
||||
|
@ -1304,6 +1353,7 @@ Nan Monnand Deng <monnand@gmail.com>
|
|||
Naoki Orii <norii@cs.cmu.edu>
|
||||
Natalie Parker <nparker@omnifone.com>
|
||||
Natanael Copa <natanael.copa@docker.com>
|
||||
Natasha Jarus <linuxmercedes@gmail.com>
|
||||
Nate Brennand <nate.brennand@clever.com>
|
||||
Nate Eagleson <nate@nateeag.com>
|
||||
Nate Jones <nate@endot.org>
|
||||
|
@ -1337,6 +1387,7 @@ Nicolas Dudebout <nicolas.dudebout@gatech.edu>
|
|||
Nicolas Goy <kuon@goyman.com>
|
||||
Nicolas Kaiser <nikai@nikai.net>
|
||||
Nicolas Sterchele <sterchele.nicolas@gmail.com>
|
||||
Nicolas V Castet <nvcastet@us.ibm.com>
|
||||
Nicolás Hock Isaza <nhocki@gmail.com>
|
||||
Nigel Poulton <nigelpoulton@hotmail.com>
|
||||
Nik Nyby <nikolas@gnu.org>
|
||||
|
@ -1352,6 +1403,7 @@ Noah Treuhaft <noah.treuhaft@docker.com>
|
|||
NobodyOnSE <ich@sektor.selfip.com>
|
||||
noducks <onemannoducks@gmail.com>
|
||||
Nolan Darilek <nolan@thewordnerd.info>
|
||||
Noriki Nakamura <noriki.nakamura@miraclelinux.com>
|
||||
nponeccop <andy.melnikov@gmail.com>
|
||||
Nuutti Kotivuori <naked@iki.fi>
|
||||
nzwsch <hi@nzwsch.com>
|
||||
|
@ -1363,8 +1415,11 @@ Ohad Schneider <ohadschn@users.noreply.github.com>
|
|||
ohmystack <jun.jiang02@ele.me>
|
||||
Ole Reifschneider <mail@ole-reifschneider.de>
|
||||
Oliver Neal <ItsVeryWindy@users.noreply.github.com>
|
||||
Oliver Reason <oli@overrateddev.co>
|
||||
Olivier Gambier <dmp42@users.noreply.github.com>
|
||||
Olle Jonsson <olle.jonsson@gmail.com>
|
||||
Olli Janatuinen <olli.janatuinen@gmail.com>
|
||||
Omri Shiv <Omri.Shiv@teradata.com>
|
||||
Oriol Francès <oriolfa@gmail.com>
|
||||
Oskar Niburski <oskarniburski@gmail.com>
|
||||
Otto Kekäläinen <otto@seravo.fi>
|
||||
|
@ -1420,6 +1475,7 @@ Peter Edge <peter.edge@gmail.com>
|
|||
Peter Ericson <pdericson@gmail.com>
|
||||
Peter Esbensen <pkesbensen@gmail.com>
|
||||
Peter Jaffe <pjaffe@nevo.com>
|
||||
Peter Kang <peter@spell.run>
|
||||
Peter Malmgren <ptmalmgren@gmail.com>
|
||||
Peter Salvatore <peter@psftw.com>
|
||||
Peter Volpe <petervo@redhat.com>
|
||||
|
@ -1452,6 +1508,7 @@ Prasanna Gautam <prasannagautam@gmail.com>
|
|||
Pratik Karki <prertik@outlook.com>
|
||||
Prayag Verma <prayag.verma@gmail.com>
|
||||
Priya Wadhwa <priyawadhwa@google.com>
|
||||
Projjol Banerji <probaner23@gmail.com>
|
||||
Przemek Hejman <przemyslaw.hejman@gmail.com>
|
||||
Pure White <daniel48@126.com>
|
||||
pysqz <randomq@126.com>
|
||||
|
@ -1475,6 +1532,7 @@ Ralph Bean <rbean@redhat.com>
|
|||
Ramkumar Ramachandra <artagnon@gmail.com>
|
||||
Ramon Brooker <rbrooker@aetherealmind.com>
|
||||
Ramon van Alteren <ramon@vanalteren.nl>
|
||||
RaviTeja Pothana <ravi-teja@live.com>
|
||||
Ray Tsang <rayt@google.com>
|
||||
ReadmeCritic <frankensteinbot@gmail.com>
|
||||
Recursive Madman <recursive.madman@gmx.de>
|
||||
|
@ -1524,6 +1582,7 @@ Roel Van Nyen <roel.vannyen@gmail.com>
|
|||
Roger Peppe <rogpeppe@gmail.com>
|
||||
Rohit Jnagal <jnagal@google.com>
|
||||
Rohit Kadam <rohit.d.kadam@gmail.com>
|
||||
Rohit Kapur <rkapur@flatiron.com>
|
||||
Rojin George <rojingeorge@huawei.com>
|
||||
Roland Huß <roland@jolokia.org>
|
||||
Roland Kammerer <roland.kammerer@linbit.com>
|
||||
|
@ -1533,6 +1592,9 @@ Roman Dudin <katrmr@gmail.com>
|
|||
Roman Strashkin <roman.strashkin@gmail.com>
|
||||
Ron Smits <ron.smits@gmail.com>
|
||||
Ron Williams <ron.a.williams@gmail.com>
|
||||
Rong Gao <gaoronggood@163.com>
|
||||
Rong Zhang <rongzhang@alauda.io>
|
||||
Rongxiang Song <tinysong1226@gmail.com>
|
||||
root <docker-dummy@example.com>
|
||||
root <root@lxdebmas.marist.edu>
|
||||
root <root@ubuntu-14.04-amd64-vbox>
|
||||
|
@ -1544,8 +1606,10 @@ Rovanion Luckey <rovanion.luckey@gmail.com>
|
|||
Royce Remer <royceremer@gmail.com>
|
||||
Rozhnov Alexandr <nox73@ya.ru>
|
||||
Rudolph Gottesheim <r.gottesheim@loot.at>
|
||||
Rui Cao <ruicao@alauda.io>
|
||||
Rui Lopes <rgl@ruilopes.com>
|
||||
Runshen Zhu <runshen.zhu@gmail.com>
|
||||
Russ Magee <rmagee@gmail.com>
|
||||
Ryan Abrams <rdabrams@gmail.com>
|
||||
Ryan Anderson <anderson.ryanc@gmail.com>
|
||||
Ryan Aslett <github@mixologic.com>
|
||||
|
@ -1564,6 +1628,7 @@ Ryan Wallner <ryan.wallner@clusterhq.com>
|
|||
Ryan Zhang <ryan.zhang@docker.com>
|
||||
ryancooper7 <ryan.cooper7@gmail.com>
|
||||
RyanDeng <sheldon.d1018@gmail.com>
|
||||
Ryo Nakao <nakabonne@gmail.com>
|
||||
Rémy Greinhofer <remy.greinhofer@livelovely.com>
|
||||
s. rannou <mxs@sbrk.org>
|
||||
s00318865 <sunyuan3@huawei.com>
|
||||
|
@ -1572,6 +1637,7 @@ Sachin Joshi <sachin_jayant_joshi@hotmail.com>
|
|||
Sagar Hani <sagarhani33@gmail.com>
|
||||
Sainath Grandhi <sainath.grandhi@intel.com>
|
||||
Sakeven Jiang <jc5930@sina.cn>
|
||||
Salahuddin Khan <salah@docker.com>
|
||||
Sally O'Malley <somalley@redhat.com>
|
||||
Sam Abed <sam.abed@gmail.com>
|
||||
Sam Alba <sam.alba@gmail.com>
|
||||
|
@ -1593,6 +1659,7 @@ Santhosh Manohar <santhosh@docker.com>
|
|||
sapphiredev <se.imas.kr@gmail.com>
|
||||
Sargun Dhillon <sargun@netflix.com>
|
||||
Sascha Andres <sascha.andres@outlook.com>
|
||||
Sascha Grunert <sgrunert@suse.com>
|
||||
Satnam Singh <satnam@raintown.org>
|
||||
Satoshi Amemiya <satoshi_amemiya@voyagegroup.com>
|
||||
Satoshi Tagomori <tagomoris@gmail.com>
|
||||
|
@ -1619,7 +1686,9 @@ Serge Hallyn <serge.hallyn@ubuntu.com>
|
|||
Sergey Alekseev <sergey.alekseev.minsk@gmail.com>
|
||||
Sergey Evstifeev <sergey.evstifeev@gmail.com>
|
||||
Sergii Kabashniuk <skabashnyuk@codenvy.com>
|
||||
Sergio Lopez <slp@redhat.com>
|
||||
Serhat Gülçiçek <serhat25@gmail.com>
|
||||
SeungUkLee <lsy931106@gmail.com>
|
||||
Sevki Hasirci <s@sevki.org>
|
||||
Shane Canon <scanon@lbl.gov>
|
||||
Shane da Silva <shane@dasilva.io>
|
||||
|
@ -1647,6 +1716,7 @@ Sidhartha Mani <sidharthamn@gmail.com>
|
|||
sidharthamani <sid@rancher.com>
|
||||
Silas Sewell <silas@sewell.org>
|
||||
Silvan Jegen <s.jegen@gmail.com>
|
||||
Simão Reis <smnrsti@gmail.com>
|
||||
Simei He <hesimei@zju.edu.cn>
|
||||
Simon Eskildsen <sirup@sirupsen.com>
|
||||
Simon Ferquel <simon.ferquel@docker.com>
|
||||
|
@ -1714,10 +1784,11 @@ tang0th <tang0th@gmx.com>
|
|||
Tangi Colin <tangicolin@gmail.com>
|
||||
Tatsuki Sugiura <sugi@nemui.org>
|
||||
Tatsushi Inagaki <e29253@jp.ibm.com>
|
||||
Taylan Isikdemir <taylani@google.com>
|
||||
Taylor Jones <monitorjbl@gmail.com>
|
||||
tbonza <tylers.pile@gmail.com>
|
||||
Ted M. Young <tedyoung@gmail.com>
|
||||
Tehmasp Chaudhri <tehmasp@gmail.com>
|
||||
Tejaswini Duggaraju <naduggar@microsoft.com>
|
||||
Tejesh Mehta <tejesh.mehta@gmail.com>
|
||||
terryding77 <550147740@qq.com>
|
||||
tgic <farmer1992@gmail.com>
|
||||
|
@ -1811,6 +1882,7 @@ Tristan Carel <tristan@cogniteev.com>
|
|||
Troy Denton <trdenton@gmail.com>
|
||||
Tycho Andersen <tycho@docker.com>
|
||||
Tyler Brock <tyler.brock@gmail.com>
|
||||
Tyler Brown <tylers.pile@gmail.com>
|
||||
Tzu-Jung Lee <roylee17@gmail.com>
|
||||
uhayate <uhayate.gong@daocloud.io>
|
||||
Ulysse Carion <ulyssecarion@gmail.com>
|
||||
|
@ -1871,6 +1943,7 @@ Wassim Dhif <wassimdhif@gmail.com>
|
|||
Wayne Chang <wayne@neverfear.org>
|
||||
Wayne Song <wsong@docker.com>
|
||||
Weerasak Chongnguluam <singpor@gmail.com>
|
||||
Wei Fu <fuweid89@gmail.com>
|
||||
Wei Wu <wuwei4455@gmail.com>
|
||||
Wei-Ting Kuo <waitingkuo0527@gmail.com>
|
||||
weipeng <weipeng@tuscloud.io>
|
||||
|
@ -1900,17 +1973,23 @@ WiseTrem <shepelyov.g@gmail.com>
|
|||
Wolfgang Powisch <powo@powo.priv.at>
|
||||
Wonjun Kim <wonjun.kim@navercorp.com>
|
||||
xamyzhao <x.amy.zhao@gmail.com>
|
||||
Xian Chaobo <xianchaobo@huawei.com>
|
||||
Xianglin Gao <xlgao@zju.edu.cn>
|
||||
Xianlu Bird <xianlubird@gmail.com>
|
||||
XiaoBing Jiang <s7v7nislands@gmail.com>
|
||||
Xiaodong Zhang <a4012017@sina.com>
|
||||
Xiaoxi He <xxhe@alauda.io>
|
||||
Xiaoxu Chen <chenxiaoxu14@otcaix.iscas.ac.cn>
|
||||
Xiaoyu Zhang <zhang.xiaoyu33@zte.com.cn>
|
||||
xichengliudui <1693291525@qq.com>
|
||||
xiekeyang <xiekeyang@huawei.com>
|
||||
Ximo Guanter Gonzálbez <joaquin.guantergonzalbez@telefonica.com>
|
||||
Xinbo Weng <xihuanbo_0521@zju.edu.cn>
|
||||
Xinzi Zhou <imdreamrunner@gmail.com>
|
||||
Xiuming Chen <cc@cxm.cc>
|
||||
Xuecong Liao <satorulogic@gmail.com>
|
||||
xuzhaokui <cynicholas@gmail.com>
|
||||
Yadnyawalkya Tale <ytale@redhat.com>
|
||||
Yahya <ya7yaz@gmail.com>
|
||||
YAMADA Tsuyoshi <tyamada@minimum2scp.org>
|
||||
Yamasaki Masahide <masahide.y@gmail.com>
|
||||
|
@ -1930,6 +2009,7 @@ Yihang Ho <hoyihang5@gmail.com>
|
|||
Ying Li <ying.li@docker.com>
|
||||
Yohei Ueda <yohei@jp.ibm.com>
|
||||
Yong Tang <yong.tang.github@outlook.com>
|
||||
Yongxin Li <yxli@alauda.io>
|
||||
Yongzhi Pan <panyongzhi@gmail.com>
|
||||
Yosef Fertel <yfertel@gmail.com>
|
||||
You-Sheng Yang (楊有勝) <vicamo@gmail.com>
|
||||
|
@ -1940,9 +2020,12 @@ Yu Peng <yu.peng36@zte.com.cn>
|
|||
Yu-Ju Hong <yjhong@google.com>
|
||||
Yuan Sun <sunyuan3@huawei.com>
|
||||
Yuanhong Peng <pengyuanhong@huawei.com>
|
||||
Yue Zhang <zy675793960@yeah.net>
|
||||
Yuhao Fang <fangyuhao@gmail.com>
|
||||
Yuichiro Kaneko <spiketeika@gmail.com>
|
||||
Yunxiang Huang <hyxqshk@vip.qq.com>
|
||||
Yurii Rashkovskii <yrashk@gmail.com>
|
||||
Yusuf Tarık Günaydın <yusuf_tarik@hotmail.com>
|
||||
Yves Junqueira <yves.junqueira@gmail.com>
|
||||
Zac Dover <zdover@redhat.com>
|
||||
Zach Borboa <zachborboa@gmail.com>
|
||||
|
@ -1959,8 +2042,10 @@ ZhangHang <stevezhang2014@gmail.com>
|
|||
zhangxianwei <xianwei.zw@alibaba-inc.com>
|
||||
Zhenan Ye <21551168@zju.edu.cn>
|
||||
zhenghenghuo <zhenghenghuo@zju.edu.cn>
|
||||
Zhenhai Gao <gaozh1988@live.com>
|
||||
Zhenkun Bi <bi.zhenkun@zte.com.cn>
|
||||
Zhou Hao <zhouhao@cn.fujitsu.com>
|
||||
Zhoulin Xie <zhoulin.xie@daocloud.io>
|
||||
Zhu Guihua <zhugh.fnst@cn.fujitsu.com>
|
||||
Zhu Kunjia <zhu.kunjia@zte.com.cn>
|
||||
Zhuoyun Wei <wzyboy@wzyboy.org>
|
||||
|
|
|
@ -99,7 +99,7 @@ be found.
|
|||
* Add `--format` option to `docker node ls` [#30424](https://github.com/docker/docker/pull/30424)
|
||||
* Add `--prune` option to `docker stack deploy` to remove services that are no longer defined in the docker-compose file [#31302](https://github.com/docker/docker/pull/31302)
|
||||
* Add `PORTS` column for `docker service ls` when using `ingress` mode [#30813](https://github.com/docker/docker/pull/30813)
|
||||
- Fix unnescessary re-deploying of tasks when environment-variables are used [#32364](https://github.com/docker/docker/pull/32364)
|
||||
- Fix unnecessary re-deploying of tasks when environment-variables are used [#32364](https://github.com/docker/docker/pull/32364)
|
||||
- Fix `docker stack deploy` not supporting `endpoint_mode` when deploying from a docker compose file [#32333](https://github.com/docker/docker/pull/32333)
|
||||
- Proceed with startup if cluster component cannot be created to allow recovering from a broken swarm setup [#31631](https://github.com/docker/docker/pull/31631)
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ process](docs/contributing/).
|
|||
|
||||
This page contains information about reporting issues as well as some tips and
|
||||
guidelines useful to experienced open source contributors. Finally, make sure
|
||||
you read our [community guidelines](#docker-community-guidelines) before you
|
||||
you read our [community guidelines](#moby-community-guidelines) before you
|
||||
start participating.
|
||||
|
||||
## Topics
|
||||
|
@ -17,7 +17,7 @@ start participating.
|
|||
* [Design and Cleanup Proposals](#design-and-cleanup-proposals)
|
||||
* [Reporting Issues](#reporting-other-issues)
|
||||
* [Quick Contribution Tips and Guidelines](#quick-contribution-tips-and-guidelines)
|
||||
* [Community Guidelines](#docker-community-guidelines)
|
||||
* [Community Guidelines](#moby-community-guidelines)
|
||||
|
||||
## Reporting security issues
|
||||
|
||||
|
|
|
@ -24,18 +24,15 @@
|
|||
# the case. Therefore, you don't have to disable it anymore.
|
||||
#
|
||||
|
||||
FROM golang:1.10.3 AS base
|
||||
# FIXME(vdemeester) this is kept for other script depending on it to not fail right away
|
||||
# Remove this once the other scripts uses something else to detect the version
|
||||
ENV GO_VERSION 1.10.3
|
||||
FROM golang:1.12.1 AS base
|
||||
# allow replacing httpredir or deb mirror
|
||||
ARG APT_MIRROR=deb.debian.org
|
||||
RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
|
||||
|
||||
FROM base AS criu
|
||||
# Install CRIU for checkpoint/restore support
|
||||
ENV CRIU_VERSION 3.6
|
||||
# Install dependancy packages specific to criu
|
||||
ENV CRIU_VERSION 3.11
|
||||
# Install dependency packages specific to criu
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libnet-dev \
|
||||
libprotobuf-c0-dev \
|
||||
|
@ -52,11 +49,6 @@ RUN apt-get update && apt-get install -y \
|
|||
&& make PREFIX=/build/ install-criu
|
||||
|
||||
FROM base AS registry
|
||||
# Install two versions of the registry. The first is an older version that
|
||||
# only supports schema1 manifests. The second is a newer version that supports
|
||||
# both. This allows integration-cli tests to cover push/pull with both schema1
|
||||
# and schema2 manifests.
|
||||
ENV REGISTRY_COMMIT_SCHEMA1 ec87e9b6971d831f0eff752ddb54fb64693e51cd
|
||||
ENV REGISTRY_COMMIT 47a064d4195a9b56133891bbb13620c3ac83a827
|
||||
RUN set -x \
|
||||
&& export GOPATH="$(mktemp -d)" \
|
||||
|
@ -64,20 +56,13 @@ RUN set -x \
|
|||
&& (cd "$GOPATH/src/github.com/docker/distribution" && git checkout -q "$REGISTRY_COMMIT") \
|
||||
&& GOPATH="$GOPATH/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH" \
|
||||
go build -buildmode=pie -o /build/registry-v2 github.com/docker/distribution/cmd/registry \
|
||||
&& case $(dpkg --print-architecture) in \
|
||||
amd64|ppc64*|s390x) \
|
||||
(cd "$GOPATH/src/github.com/docker/distribution" && git checkout -q "$REGISTRY_COMMIT_SCHEMA1"); \
|
||||
GOPATH="$GOPATH/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH"; \
|
||||
go build -buildmode=pie -o /build/registry-v2-schema1 github.com/docker/distribution/cmd/registry; \
|
||||
;; \
|
||||
esac \
|
||||
&& rm -rf "$GOPATH"
|
||||
|
||||
|
||||
|
||||
FROM base AS docker-py
|
||||
# Get the "docker-py" source so we can run their integration tests
|
||||
ENV DOCKER_PY_COMMIT 8b246db271a85d6541dc458838627e89c683e42f
|
||||
ENV DOCKER_PY_COMMIT ac922192959870774ad8428344d9faa0555f7ba6
|
||||
RUN git clone https://github.com/docker/docker-py.git /build \
|
||||
&& cd /build \
|
||||
&& git checkout -q $DOCKER_PY_COMMIT
|
||||
|
@ -118,58 +103,65 @@ FROM base AS tomlv
|
|||
ENV INSTALL_BINARY_NAME=tomlv
|
||||
COPY hack/dockerfile/install/install.sh ./install.sh
|
||||
COPY hack/dockerfile/install/$INSTALL_BINARY_NAME.installer ./
|
||||
RUN PREFIX=/build/ ./install.sh $INSTALL_BINARY_NAME
|
||||
RUN PREFIX=/build ./install.sh $INSTALL_BINARY_NAME
|
||||
|
||||
FROM base AS vndr
|
||||
ENV INSTALL_BINARY_NAME=vndr
|
||||
COPY hack/dockerfile/install/install.sh ./install.sh
|
||||
COPY hack/dockerfile/install/$INSTALL_BINARY_NAME.installer ./
|
||||
RUN PREFIX=/build/ ./install.sh $INSTALL_BINARY_NAME
|
||||
RUN PREFIX=/build ./install.sh $INSTALL_BINARY_NAME
|
||||
|
||||
FROM base AS containerd
|
||||
RUN apt-get update && apt-get install -y btrfs-tools
|
||||
ENV INSTALL_BINARY_NAME=containerd
|
||||
COPY hack/dockerfile/install/install.sh ./install.sh
|
||||
COPY hack/dockerfile/install/$INSTALL_BINARY_NAME.installer ./
|
||||
RUN PREFIX=/build/ ./install.sh $INSTALL_BINARY_NAME
|
||||
RUN PREFIX=/build ./install.sh $INSTALL_BINARY_NAME
|
||||
|
||||
FROM base AS proxy
|
||||
ENV INSTALL_BINARY_NAME=proxy
|
||||
COPY hack/dockerfile/install/install.sh ./install.sh
|
||||
COPY hack/dockerfile/install/$INSTALL_BINARY_NAME.installer ./
|
||||
RUN PREFIX=/build/ ./install.sh $INSTALL_BINARY_NAME
|
||||
RUN PREFIX=/build ./install.sh $INSTALL_BINARY_NAME
|
||||
|
||||
FROM base AS gometalinter
|
||||
ENV INSTALL_BINARY_NAME=gometalinter
|
||||
COPY hack/dockerfile/install/install.sh ./install.sh
|
||||
COPY hack/dockerfile/install/$INSTALL_BINARY_NAME.installer ./
|
||||
RUN PREFIX=/build/ ./install.sh $INSTALL_BINARY_NAME
|
||||
RUN PREFIX=/build ./install.sh $INSTALL_BINARY_NAME
|
||||
|
||||
FROM base AS dockercli
|
||||
ENV INSTALL_BINARY_NAME=dockercli
|
||||
COPY hack/dockerfile/install/install.sh ./install.sh
|
||||
COPY hack/dockerfile/install/$INSTALL_BINARY_NAME.installer ./
|
||||
RUN PREFIX=/build/ ./install.sh $INSTALL_BINARY_NAME
|
||||
RUN PREFIX=/build ./install.sh $INSTALL_BINARY_NAME
|
||||
|
||||
FROM runtime-dev AS runc
|
||||
ENV INSTALL_BINARY_NAME=runc
|
||||
COPY hack/dockerfile/install/install.sh ./install.sh
|
||||
COPY hack/dockerfile/install/$INSTALL_BINARY_NAME.installer ./
|
||||
RUN PREFIX=/build/ ./install.sh $INSTALL_BINARY_NAME
|
||||
RUN PREFIX=/build ./install.sh $INSTALL_BINARY_NAME
|
||||
|
||||
FROM base AS tini
|
||||
RUN apt-get update && apt-get install -y cmake vim-common
|
||||
COPY hack/dockerfile/install/install.sh ./install.sh
|
||||
ENV INSTALL_BINARY_NAME=tini
|
||||
COPY hack/dockerfile/install/$INSTALL_BINARY_NAME.installer ./
|
||||
RUN PREFIX=/build ./install.sh $INSTALL_BINARY_NAME
|
||||
|
||||
FROM base AS rootlesskit
|
||||
ENV INSTALL_BINARY_NAME=rootlesskit
|
||||
COPY hack/dockerfile/install/install.sh ./install.sh
|
||||
COPY hack/dockerfile/install/$INSTALL_BINARY_NAME.installer ./
|
||||
RUN PREFIX=/build/ ./install.sh $INSTALL_BINARY_NAME
|
||||
|
||||
|
||||
COPY ./contrib/dockerd-rootless.sh /build
|
||||
|
||||
# TODO: Some of this is only really needed for testing, it would be nice to split this up
|
||||
FROM runtime-dev AS dev
|
||||
RUN groupadd -r docker
|
||||
RUN useradd --create-home --gid docker unprivilegeduser
|
||||
# Let us use a .bashrc file
|
||||
RUN ln -sfv /go/src/github.com/docker/docker/.bashrc ~/.bashrc
|
||||
# Activate bash completion and include Docker's completion if mounted with DOCKER_BASH_COMPLETION_PATH
|
||||
RUN echo "source /usr/share/bash-completion/bash_completion" >> /etc/bash.bashrc
|
||||
RUN ln -s /usr/local/completion/bash/docker /etc/bash_completion.d/docker
|
||||
|
@ -183,7 +175,11 @@ RUN apt-get update && apt-get install -y \
|
|||
btrfs-tools \
|
||||
iptables \
|
||||
jq \
|
||||
libcap2-bin \
|
||||
libdevmapper-dev \
|
||||
# libffi-dev and libssl-dev appear to be required for compiling paramiko on s390x/ppc64le
|
||||
libffi-dev \
|
||||
libssl-dev \
|
||||
libudev-dev \
|
||||
libsystemd-dev \
|
||||
binutils-mingw-w64 \
|
||||
|
@ -192,6 +188,8 @@ RUN apt-get update && apt-get install -y \
|
|||
pigz \
|
||||
python-backports.ssl-match-hostname \
|
||||
python-dev \
|
||||
# python-cffi appears to be required for compiling paramiko on s390x/ppc64le
|
||||
python-cffi \
|
||||
python-mock \
|
||||
python-pip \
|
||||
python-requests \
|
||||
|
@ -205,6 +203,9 @@ RUN apt-get update && apt-get install -y \
|
|||
zip \
|
||||
bzip2 \
|
||||
xz-utils \
|
||||
libprotobuf-c1 \
|
||||
libnet1 \
|
||||
libnl-3-200 \
|
||||
--no-install-recommends
|
||||
COPY --from=swagger /build/swagger* /usr/local/bin/
|
||||
COPY --from=frozen-images /build/ /docker-frozen-images
|
||||
|
@ -224,9 +225,12 @@ COPY --from=docker-py /build/ /docker-py
|
|||
# split out into a separate image, including all the `python-*` deps installed
|
||||
# above.
|
||||
RUN cd /docker-py \
|
||||
&& pip install docker-pycreds==0.2.1 \
|
||||
&& pip install docker-pycreds==0.4.0 \
|
||||
&& pip install paramiko==2.4.2 \
|
||||
&& pip install yamllint==1.5.0 \
|
||||
&& pip install -r test-requirements.txt
|
||||
COPY --from=rootlesskit /build/ /usr/local/bin/
|
||||
COPY --from=djs55/vpnkit@sha256:e508a17cfacc8fd39261d5b4e397df2b953690da577e2c987a47630cd0c42f8e /vpnkit /usr/local/bin/vpnkit.x86_64
|
||||
|
||||
ENV PATH=/usr/local/cli:$PATH
|
||||
ENV DOCKER_BUILDTAGS apparmor seccomp selinux
|
||||
|
@ -236,5 +240,7 @@ WORKDIR /go/src/github.com/docker/docker
|
|||
VOLUME /var/lib/docker
|
||||
# Wrap all commands in the "docker-in-docker" script to allow nested containers
|
||||
ENTRYPOINT ["hack/dind"]
|
||||
|
||||
FROM dev AS final
|
||||
# Upload docker source
|
||||
COPY . /go/src/github.com/docker/docker
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
## Step 1: Build tests
|
||||
FROM golang:1.10.3-alpine3.7 as builder
|
||||
FROM golang:1.12.1-alpine3.9 as builder
|
||||
|
||||
RUN apk add --update \
|
||||
RUN apk --no-cache add \
|
||||
bash \
|
||||
btrfs-progs-dev \
|
||||
build-base \
|
||||
curl \
|
||||
lvm2-dev \
|
||||
jq \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
jq
|
||||
|
||||
RUN mkdir -p /go/src/github.com/docker/docker/
|
||||
WORKDIR /go/src/github.com/docker/docker/
|
||||
|
@ -40,10 +39,10 @@ RUN hack/make.sh build-integration-test-binary
|
|||
RUN mkdir -p /output/tests && find . -name test.main -exec cp --parents '{}' /output/tests \;
|
||||
|
||||
## Step 2: Generate testing image
|
||||
FROM alpine:3.7 as runner
|
||||
FROM alpine:3.8 as runner
|
||||
|
||||
# GNU tar is used for generating the emptyfs image
|
||||
RUN apk add --update \
|
||||
RUN apk --no-cache add \
|
||||
bash \
|
||||
ca-certificates \
|
||||
g++ \
|
||||
|
@ -51,8 +50,7 @@ RUN apk add --update \
|
|||
iptables \
|
||||
pigz \
|
||||
tar \
|
||||
xz \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
xz
|
||||
|
||||
# Add an unprivileged user to be used for tests which need it
|
||||
RUN addgroup docker && adduser -D -G docker unprivilegeduser -s /bin/ash
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
# This represents the bare minimum required to build and test Docker.
|
||||
|
||||
FROM debian:stretch
|
||||
FROM golang:1.12.1
|
||||
|
||||
# allow replacing httpredir or deb mirror
|
||||
ARG APT_MIRROR=deb.debian.org
|
||||
|
@ -37,18 +37,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
vim-common \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Go
|
||||
# IMPORTANT: If the version of Go is updated, the Windows to Linux CI machines
|
||||
# will need updating, to avoid errors. Ping #docker-maintainers on IRC
|
||||
# with a heads-up.
|
||||
# IMPORTANT: When updating this please note that stdlib archive/tar pkg is vendored
|
||||
ENV GO_VERSION 1.10.3
|
||||
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" \
|
||||
| tar -xzC /usr/local
|
||||
ENV PATH /go/bin:/usr/local/go/bin:$PATH
|
||||
ENV GOPATH /go
|
||||
ENV CGO_LDFLAGS -L/lib
|
||||
|
||||
# Install runc, containerd, tini and docker-proxy
|
||||
# Please edit hack/dockerfile/install/<name>.installer to update them.
|
||||
COPY hack/dockerfile/install hack/dockerfile/install
|
||||
|
|
|
@ -153,6 +153,13 @@
|
|||
|
||||
|
||||
# The number of build steps below are explicitly minimised to improve performance.
|
||||
|
||||
# Extremely important - do not change the following line to reference a "specific" image,
|
||||
# such as `mcr.microsoft.com/windows/servercore:ltsc2019`. If using this Dockerfile in process
|
||||
# isolated containers, the kernel of the host must match the container image, and hence
|
||||
# would fail between Windows Server 2016 (aka RS1) and Windows Server 2019 (aka RS5).
|
||||
# It is expected that the image `microsoft/windowsservercore:latest` is present, and matches
|
||||
# the hosts kernel version before doing a build.
|
||||
FROM microsoft/windowsservercore
|
||||
|
||||
# Use PowerShell as the default shell
|
||||
|
@ -161,7 +168,7 @@ SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPref
|
|||
# Environment variable notes:
|
||||
# - GO_VERSION must be consistent with 'Dockerfile' used by Linux.
|
||||
# - FROM_DOCKERFILE is used for detection of building within a container.
|
||||
ENV GO_VERSION=1.10.3 `
|
||||
ENV GO_VERSION=1.12.1 `
|
||||
GIT_VERSION=2.11.1 `
|
||||
GOPATH=C:\go `
|
||||
FROM_DOCKERFILE=1
|
||||
|
|
|
@ -0,0 +1,325 @@
|
|||
def withGithubStatus(String context, Closure cl) {
|
||||
def setGithubStatus = { String state ->
|
||||
try {
|
||||
def backref = "${BUILD_URL}flowGraphTable/"
|
||||
def reposSourceURL = scm.repositories[0].getURIs()[0].toString()
|
||||
step(
|
||||
$class: 'GitHubCommitStatusSetter',
|
||||
contextSource: [$class: "ManuallyEnteredCommitContextSource", context: context],
|
||||
errorHandlers: [[$class: 'ShallowAnyErrorHandler']],
|
||||
reposSource: [$class: 'ManuallyEnteredRepositorySource', url: reposSourceURL],
|
||||
statusBackrefSource: [$class: 'ManuallyEnteredBackrefSource', backref: backref],
|
||||
statusResultSource: [$class: 'ConditionalStatusResultSource', results: [[$class: 'AnyBuildResult', state: state]]],
|
||||
)
|
||||
} catch (err) {
|
||||
echo "Exception from GitHubCommitStatusSetter for $context: $err"
|
||||
}
|
||||
}
|
||||
|
||||
setGithubStatus 'PENDING'
|
||||
|
||||
try {
|
||||
cl()
|
||||
} catch (err) {
|
||||
// AbortException signals a "normal" build failure.
|
||||
if (!(err instanceof hudson.AbortException)) {
|
||||
echo "Exception in withGithubStatus for $context: $err"
|
||||
}
|
||||
setGithubStatus 'FAILURE'
|
||||
throw err
|
||||
}
|
||||
setGithubStatus 'SUCCESS'
|
||||
}
|
||||
|
||||
|
||||
pipeline {
|
||||
agent none
|
||||
options {
|
||||
buildDiscarder(logRotator(daysToKeepStr: '30'))
|
||||
timeout(time: 3, unit: 'HOURS')
|
||||
}
|
||||
parameters {
|
||||
booleanParam(name: 'janky', defaultValue: true, description: 'x86 Build/Test')
|
||||
booleanParam(name: 'experimental', defaultValue: true, description: 'x86 Experimental Build/Test ')
|
||||
booleanParam(name: 'z', defaultValue: true, description: 'IBM Z (s390x) Build/Test')
|
||||
booleanParam(name: 'powerpc', defaultValue: true, description: 'PowerPC (ppc64le) Build/Test')
|
||||
booleanParam(name: 'vendor', defaultValue: true, description: 'Vendor')
|
||||
booleanParam(name: 'windowsRS1', defaultValue: true, description: 'Windows 2016 (RS1) Build/Test')
|
||||
booleanParam(name: 'windowsRS5', defaultValue: true, description: 'Windows 2019 (RS5) Build/Test')
|
||||
}
|
||||
stages {
|
||||
stage('Build') {
|
||||
parallel {
|
||||
stage('janky') {
|
||||
when {
|
||||
beforeAgent true
|
||||
expression { params.janky }
|
||||
}
|
||||
agent {
|
||||
node {
|
||||
label 'ubuntu-1604-overlay2-stable'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
withCredentials([string(credentialsId: '52af932f-f13f-429e-8467-e7ff8b965cdb', variable: 'CODECOV_TOKEN')]) {
|
||||
withGithubStatus('janky') {
|
||||
sh '''
|
||||
# todo: include ip_vs in base image
|
||||
sudo modprobe ip_vs
|
||||
|
||||
GITCOMMIT=$(git rev-parse --short HEAD)
|
||||
docker build --rm --force-rm --build-arg APT_MIRROR=cdn-fastly.deb.debian.org -t docker:$GITCOMMIT .
|
||||
|
||||
docker run --rm -t --privileged \
|
||||
-v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
|
||||
-v "$WORKSPACE/.git:/go/src/github.com/docker/docker/.git" \
|
||||
--name docker-pr$BUILD_NUMBER \
|
||||
-e DOCKER_GITCOMMIT=${GITCOMMIT} \
|
||||
-e DOCKER_GRAPHDRIVER=vfs \
|
||||
-e DOCKER_EXECDRIVER=native \
|
||||
-e CODECOV_TOKEN \
|
||||
-e GIT_SHA1=${GIT_COMMIT} \
|
||||
docker:$GITCOMMIT \
|
||||
hack/ci/janky
|
||||
'''
|
||||
sh '''
|
||||
GITCOMMIT=$(git rev-parse --short HEAD)
|
||||
echo "Building e2e image"
|
||||
docker build --build-arg DOCKER_GITCOMMIT=$GITCOMMIT -t moby-e2e-test -f Dockerfile.e2e .
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
sh '''
|
||||
echo "Ensuring container killed."
|
||||
docker rm -vf docker-pr$BUILD_NUMBER || true
|
||||
|
||||
echo "Chowning /workspace to jenkins user"
|
||||
docker run --rm -v "$WORKSPACE:/workspace" busybox chown -R "$(id -u):$(id -g)" /workspace
|
||||
'''
|
||||
sh '''
|
||||
echo "Creating bundles.tar.gz"
|
||||
(find bundles -name '*.log' -o -name '*.prof' -o -name integration.test | xargs tar -czf bundles.tar.gz) || true
|
||||
'''
|
||||
archiveArtifacts artifacts: 'bundles.tar.gz'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('experimental') {
|
||||
when {
|
||||
beforeAgent true
|
||||
expression { params.experimental }
|
||||
}
|
||||
agent {
|
||||
node {
|
||||
label 'ubuntu-1604-aufs-stable'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
withGithubStatus('experimental') {
|
||||
sh '''
|
||||
GITCOMMIT=$(git rev-parse --short HEAD)
|
||||
docker build --rm --force-rm --build-arg APT_MIRROR=cdn-fastly.deb.debian.org -t docker:${GITCOMMIT}-exp .
|
||||
|
||||
docker run --rm -t --privileged \
|
||||
-v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
|
||||
-e DOCKER_EXPERIMENTAL=y \
|
||||
--name docker-pr-exp$BUILD_NUMBER \
|
||||
-e DOCKER_GITCOMMIT=${GITCOMMIT} \
|
||||
-e DOCKER_GRAPHDRIVER=vfs \
|
||||
-e DOCKER_EXECDRIVER=native \
|
||||
docker:${GITCOMMIT}-exp \
|
||||
hack/ci/experimental
|
||||
'''
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
sh '''
|
||||
echo "Ensuring container killed."
|
||||
docker rm -vf docker-pr-exp$BUILD_NUMBER || true
|
||||
|
||||
echo "Chowning /workspace to jenkins user"
|
||||
docker run --rm -v "$WORKSPACE:/workspace" busybox chown -R "$(id -u):$(id -g)" /workspace
|
||||
'''
|
||||
sh '''
|
||||
echo "Creating bundles.tar.gz"
|
||||
(find bundles -name '*.log' -o -name '*.prof' -o -name integration.test | xargs tar -czf bundles.tar.gz) || true
|
||||
'''
|
||||
archiveArtifacts artifacts: 'bundles.tar.gz'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('z') {
|
||||
when {
|
||||
beforeAgent true
|
||||
expression { params.z }
|
||||
}
|
||||
agent {
|
||||
node {
|
||||
label 's390x-ubuntu-1604'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
withGithubStatus('z') {
|
||||
sh '''
|
||||
GITCOMMIT=$(git rev-parse --short HEAD)
|
||||
|
||||
test -f Dockerfile.s390x && \
|
||||
docker build --rm --force-rm --build-arg APT_MIRROR=cdn-fastly.deb.debian.org -t docker-s390x:$GITCOMMIT -f Dockerfile.s390x . || \
|
||||
docker build --rm --force-rm --build-arg APT_MIRROR=cdn-fastly.deb.debian.org -t docker-s390x:$GITCOMMIT -f Dockerfile .
|
||||
|
||||
docker run --rm -t --privileged \
|
||||
-v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
|
||||
--name docker-pr-s390x$BUILD_NUMBER \
|
||||
-e DOCKER_GRAPHDRIVER=vfs \
|
||||
-e DOCKER_EXECDRIVER=native \
|
||||
-e TIMEOUT="300m" \
|
||||
-e DOCKER_GITCOMMIT=${GITCOMMIT} \
|
||||
docker-s390x:$GITCOMMIT \
|
||||
hack/ci/z
|
||||
'''
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
sh '''
|
||||
echo "Ensuring container killed."
|
||||
docker rm -vf docker-pr-s390x$BUILD_NUMBER || true
|
||||
|
||||
echo "Chowning /workspace to jenkins user"
|
||||
docker run --rm -v "$WORKSPACE:/workspace" s390x/busybox chown -R "$(id -u):$(id -g)" /workspace
|
||||
'''
|
||||
sh '''
|
||||
echo "Creating bundles.tar.gz"
|
||||
find bundles -name '*.log' | xargs tar -czf bundles.tar.gz
|
||||
'''
|
||||
archiveArtifacts artifacts: 'bundles.tar.gz'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('powerpc') {
|
||||
when {
|
||||
beforeAgent true
|
||||
expression { params.powerpc }
|
||||
}
|
||||
agent {
|
||||
node {
|
||||
label 'ppc64le-ubuntu-1604'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
withGithubStatus('powerpc') {
|
||||
sh '''
|
||||
GITCOMMIT=$(git rev-parse --short HEAD)
|
||||
|
||||
test -f Dockerfile.ppc64le && \
|
||||
docker build --rm --force-rm --build-arg APT_MIRROR=cdn-fastly.deb.debian.org -t docker-powerpc:$GITCOMMIT -f Dockerfile.ppc64le . || \
|
||||
docker build --rm --force-rm --build-arg APT_MIRROR=cdn-fastly.deb.debian.org -t docker-powerpc:$GITCOMMIT -f Dockerfile .
|
||||
|
||||
docker run --rm -t --privileged \
|
||||
-v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
|
||||
--name docker-pr-power$BUILD_NUMBER \
|
||||
-e DOCKER_GRAPHDRIVER=vfs \
|
||||
-e DOCKER_EXECDRIVER=native \
|
||||
-e DOCKER_GITCOMMIT=${GITCOMMIT} \
|
||||
-e TIMEOUT="180m" \
|
||||
docker-powerpc:$GITCOMMIT \
|
||||
hack/ci/powerpc
|
||||
'''
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
sh '''
|
||||
echo "Ensuring container killed."
|
||||
docker rm -vf docker-pr-power$BUILD_NUMBER || true
|
||||
|
||||
echo "Chowning /workspace to jenkins user"
|
||||
docker run --rm -v "$WORKSPACE:/workspace" ppc64le/busybox chown -R "$(id -u):$(id -g)" /workspace
|
||||
'''
|
||||
sh '''
|
||||
echo "Creating bundles.tar.gz"
|
||||
find bundles -name '*.log' | xargs tar -czf bundles.tar.gz
|
||||
'''
|
||||
archiveArtifacts artifacts: 'bundles.tar.gz'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('vendor') {
|
||||
when {
|
||||
beforeAgent true
|
||||
expression { params.vendor }
|
||||
}
|
||||
agent {
|
||||
node {
|
||||
label 'ubuntu-1604-aufs-stable'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
withGithubStatus('vendor') {
|
||||
sh '''
|
||||
GITCOMMIT=$(git rev-parse --short HEAD)
|
||||
|
||||
docker build --rm --force-rm --build-arg APT_MIRROR=cdn-fastly.deb.debian.org -t dockerven:$GITCOMMIT .
|
||||
|
||||
docker run --rm -t --privileged \
|
||||
--name dockerven-pr$BUILD_NUMBER \
|
||||
-e DOCKER_GRAPHDRIVER=vfs \
|
||||
-e DOCKER_EXECDRIVER=native \
|
||||
-v "$WORKSPACE/.git:/go/src/github.com/docker/docker/.git" \
|
||||
-e DOCKER_GITCOMMIT=${GITCOMMIT} \
|
||||
-e TIMEOUT=120m dockerven:$GITCOMMIT \
|
||||
hack/validate/vendor
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('windowsRS1') {
|
||||
when {
|
||||
beforeAgent true
|
||||
expression { params.windowsRS1 }
|
||||
}
|
||||
agent {
|
||||
node {
|
||||
label 'windows-rs1'
|
||||
customWorkspace 'c:\\gopath\\src\\github.com\\docker\\docker'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
withGithubStatus('windowsRS1') {
|
||||
powershell '''
|
||||
$ErrorActionPreference = 'Stop'
|
||||
.\\hack\\ci\\windows.ps1
|
||||
exit $LastExitCode
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('windowsRS5-process') {
|
||||
when {
|
||||
beforeAgent true
|
||||
expression { params.windowsRS5 }
|
||||
}
|
||||
agent {
|
||||
node {
|
||||
label 'windows-rs5'
|
||||
customWorkspace 'c:\\gopath\\src\\github.com\\docker\\docker'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
withGithubStatus('windowsRS5-process') {
|
||||
powershell '''
|
||||
$ErrorActionPreference = 'Stop'
|
||||
.\\hack\\ci\\windows.ps1
|
||||
exit $LastExitCode
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -176,7 +176,7 @@
|
|||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2013-2017 Docker, Inc.
|
||||
Copyright 2013-2018 Docker, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
"jhowardmsft",
|
||||
"johnstep",
|
||||
"justincormack",
|
||||
"kolyshkin",
|
||||
"mhbauer",
|
||||
"mlaventure",
|
||||
"runcom",
|
||||
|
@ -50,15 +51,6 @@
|
|||
"yongtang"
|
||||
]
|
||||
|
||||
[Org."Docs maintainers"]
|
||||
|
||||
# TODO Describe the docs maintainers role.
|
||||
|
||||
people = [
|
||||
"misty",
|
||||
"thajeztah"
|
||||
]
|
||||
|
||||
[Org.Curators]
|
||||
|
||||
# The curators help ensure that incoming issues and pull requests are properly triaged and
|
||||
|
@ -78,6 +70,7 @@
|
|||
"chanwit",
|
||||
"fntlnz",
|
||||
"gianarb",
|
||||
"olljanat",
|
||||
"programmerq",
|
||||
"rheinwein",
|
||||
"ripcurld",
|
||||
|
@ -162,7 +155,7 @@
|
|||
|
||||
# Alexander Morozov contributed many features to Docker, worked on the premise of
|
||||
# what later became containerd (and worked on that too), and made a "stupid" Go
|
||||
# vendor tool specificaly for docker/docker needs: vndr (https://github.com/LK4D4/vndr).
|
||||
# vendor tool specifically for docker/docker needs: vndr (https://github.com/LK4D4/vndr).
|
||||
# Not many know that Alexander is a master negotiator, being able to change course
|
||||
# of action with a single "Nope, we're not gonna do that".
|
||||
"lk4d4",
|
||||
|
@ -365,6 +358,11 @@
|
|||
Email = "justin.cormack@docker.com"
|
||||
GitHub = "justincormack"
|
||||
|
||||
[people.kolyshkin]
|
||||
Name = "Kir Kolyshkin"
|
||||
Email = "kolyshkin@gmail.com"
|
||||
GitHub = "kolyshkin"
|
||||
|
||||
[people.lk4d4]
|
||||
Name = "Alexander Morozov"
|
||||
Email = "lk4d4@docker.com"
|
||||
|
@ -380,11 +378,6 @@
|
|||
Email = "mbauer@us.ibm.com"
|
||||
GitHub = "mhbauer"
|
||||
|
||||
[people.misty]
|
||||
Name = "Misty Stanley-Jones"
|
||||
Email = "misty@docker.com"
|
||||
GitHub = "mistyhacks"
|
||||
|
||||
[people.mlaventure]
|
||||
Name = "Kenfe-Mickaël Laventure"
|
||||
Email = "mickael.laventure@gmail.com"
|
||||
|
@ -400,6 +393,11 @@
|
|||
Email = "mrjana@docker.com"
|
||||
GitHub = "mrjana"
|
||||
|
||||
[people.olljanat]
|
||||
Name = "Olli Janatuinen"
|
||||
Email = "olli.janatuinen@gmail.com"
|
||||
GitHub = "olljanat"
|
||||
|
||||
[people.programmerq]
|
||||
Name = "Jeff Anderson"
|
||||
Email = "jeff@docker.com"
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
.PHONY: all binary dynbinary build cross help init-go-pkg-cache install manpages run shell test test-docker-py test-integration test-unit validate win
|
||||
.PHONY: all binary dynbinary build cross help install manpages run shell test test-docker-py test-integration test-unit validate win
|
||||
|
||||
# set the graph driver as the current graphdriver if not set
|
||||
DOCKER_GRAPHDRIVER := $(if $(DOCKER_GRAPHDRIVER),$(DOCKER_GRAPHDRIVER),$(shell docker info 2>&1 | grep "Storage Driver" | sed 's/.*: //'))
|
||||
export DOCKER_GRAPHDRIVER
|
||||
DOCKER_INCREMENTAL_BINARY := $(if $(DOCKER_INCREMENTAL_BINARY),$(DOCKER_INCREMENTAL_BINARY),1)
|
||||
export DOCKER_INCREMENTAL_BINARY
|
||||
|
||||
# get OS/Arch of docker engine
|
||||
DOCKER_OSARCH := $(shell bash -c 'source hack/make/.detect-daemon-osarch && echo $${DOCKER_ENGINE_OSARCH}')
|
||||
|
@ -13,6 +11,12 @@ DOCKERFILE := $(shell bash -c 'source hack/make/.detect-daemon-osarch && echo $$
|
|||
DOCKER_GITCOMMIT := $(shell git rev-parse --short HEAD || echo unsupported)
|
||||
export DOCKER_GITCOMMIT
|
||||
|
||||
# allow overriding the repository and branch that validation scripts are running
|
||||
# against these are used in hack/validate/.validate to check what changed in the PR.
|
||||
export VALIDATE_REPO
|
||||
export VALIDATE_BRANCH
|
||||
export VALIDATE_ORIGIN_BRANCH
|
||||
|
||||
# env vars passed through directly to Docker's build scripts
|
||||
# to allow things like `make KEEPBUNDLE=1 binary` easily
|
||||
# `project/PACKAGERS.md` have some limited documentation of some of these
|
||||
|
@ -30,14 +34,15 @@ DOCKER_ENVS := \
|
|||
-e KEEPBUNDLE \
|
||||
-e DOCKER_BUILD_ARGS \
|
||||
-e DOCKER_BUILD_GOGC \
|
||||
-e DOCKER_BUILD_OPTS \
|
||||
-e DOCKER_BUILD_PKGS \
|
||||
-e DOCKER_BUILDKIT \
|
||||
-e DOCKER_BASH_COMPLETION_PATH \
|
||||
-e DOCKER_CLI_PATH \
|
||||
-e DOCKER_DEBUG \
|
||||
-e DOCKER_EXPERIMENTAL \
|
||||
-e DOCKER_GITCOMMIT \
|
||||
-e DOCKER_GRAPHDRIVER \
|
||||
-e DOCKER_INCREMENTAL_BINARY \
|
||||
-e DOCKER_LDFLAGS \
|
||||
-e DOCKER_PORT \
|
||||
-e DOCKER_REMAP_ROOT \
|
||||
|
@ -48,6 +53,9 @@ DOCKER_ENVS := \
|
|||
-e TESTDIRS \
|
||||
-e TESTFLAGS \
|
||||
-e TIMEOUT \
|
||||
-e VALIDATE_REPO \
|
||||
-e VALIDATE_BRANCH \
|
||||
-e VALIDATE_ORIGIN_BRANCH \
|
||||
-e HTTP_PROXY \
|
||||
-e HTTPS_PROXY \
|
||||
-e NO_PROXY \
|
||||
|
@ -55,13 +63,18 @@ DOCKER_ENVS := \
|
|||
-e https_proxy \
|
||||
-e no_proxy \
|
||||
-e VERSION \
|
||||
-e PLATFORM
|
||||
-e PLATFORM \
|
||||
-e DEFAULT_PRODUCT_LICENSE \
|
||||
-e PRODUCT
|
||||
# note: we _cannot_ add "-e DOCKER_BUILDTAGS" here because even if it's unset in the shell, that would shadow the "ENV DOCKER_BUILDTAGS" set in our Dockerfile, which is very important for our official builds
|
||||
|
||||
# to allow `make BIND_DIR=. shell` or `make BIND_DIR= test`
|
||||
# (default to no bind mount if DOCKER_HOST is set)
|
||||
# note: BINDDIR is supported for backwards-compatibility here
|
||||
BIND_DIR := $(if $(BINDDIR),$(BINDDIR),$(if $(DOCKER_HOST),,bundles))
|
||||
|
||||
# DOCKER_MOUNT can be overriden, but use at your own risk!
|
||||
ifndef DOCKER_MOUNT
|
||||
DOCKER_MOUNT := $(if $(BIND_DIR),-v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/docker/docker/$(BIND_DIR)")
|
||||
|
||||
# This allows the test suite to be able to run without worrying about the underlying fs used by the container running the daemon (e.g. aufs-on-aufs), so long as the host running the container is running a supported fs.
|
||||
|
@ -69,17 +82,14 @@ DOCKER_MOUNT := $(if $(BIND_DIR),-v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/do
|
|||
# Note that `BIND_DIR` will already be set to `bundles` if `DOCKER_HOST` is not set (see above BIND_DIR line), in such case this will do nothing since `DOCKER_MOUNT` will already be set.
|
||||
DOCKER_MOUNT := $(if $(DOCKER_MOUNT),$(DOCKER_MOUNT),-v /go/src/github.com/docker/docker/bundles) -v "$(CURDIR)/.git:/go/src/github.com/docker/docker/.git"
|
||||
|
||||
# This allows to set the docker-dev container name
|
||||
DOCKER_CONTAINER_NAME := $(if $(CONTAINER_NAME),--name $(CONTAINER_NAME),)
|
||||
|
||||
# enable package cache if DOCKER_INCREMENTAL_BINARY and DOCKER_MOUNT (i.e.DOCKER_HOST) are set
|
||||
PKGCACHE_MAP := gopath:/go/pkg goroot-linux_amd64:/usr/local/go/pkg/linux_amd64 goroot-linux_amd64_netgo:/usr/local/go/pkg/linux_amd64_netgo
|
||||
PKGCACHE_VOLROOT := dockerdev-go-pkg-cache
|
||||
PKGCACHE_VOL := $(if $(PKGCACHE_DIR),$(CURDIR)/$(PKGCACHE_DIR)/,$(PKGCACHE_VOLROOT)-)
|
||||
DOCKER_MOUNT_PKGCACHE := $(if $(DOCKER_INCREMENTAL_BINARY),$(shell echo $(PKGCACHE_MAP) | sed -E 's@([^ ]*)@-v "$(PKGCACHE_VOL)\1"@g'),)
|
||||
DOCKER_MOUNT_CACHE := -v docker-dev-cache:/root/.cache
|
||||
DOCKER_MOUNT_CLI := $(if $(DOCKER_CLI_PATH),-v $(shell dirname $(DOCKER_CLI_PATH)):/usr/local/cli,)
|
||||
DOCKER_MOUNT_BASH_COMPLETION := $(if $(DOCKER_BASH_COMPLETION_PATH),-v $(shell dirname $(DOCKER_BASH_COMPLETION_PATH)):/usr/local/completion/bash,)
|
||||
DOCKER_MOUNT := $(DOCKER_MOUNT) $(DOCKER_MOUNT_PKGCACHE) $(DOCKER_MOUNT_CLI) $(DOCKER_MOUNT_BASH_COMPLETION)
|
||||
DOCKER_MOUNT := $(DOCKER_MOUNT) $(DOCKER_MOUNT_CACHE) $(DOCKER_MOUNT_CLI) $(DOCKER_MOUNT_BASH_COMPLETION)
|
||||
endif # ifndef DOCKER_MOUNT
|
||||
|
||||
# This allows to set the docker-dev container name
|
||||
DOCKER_CONTAINER_NAME := $(if $(CONTAINER_NAME),--name $(CONTAINER_NAME),)
|
||||
|
||||
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
||||
GIT_BRANCH_CLEAN := $(shell echo $(GIT_BRANCH) | sed -e "s/[^[:alnum:]]/-/g")
|
||||
|
@ -107,6 +117,9 @@ INTERACTIVE := $(shell [ -t 0 ] && echo 1 || echo 0)
|
|||
ifeq ($(INTERACTIVE), 1)
|
||||
DOCKER_FLAGS += -t
|
||||
endif
|
||||
ifeq ($(BIND_DIR), .)
|
||||
DOCKER_BUILD_OPTS += --target=dev
|
||||
endif
|
||||
|
||||
DOCKER_RUN_DOCKER := $(DOCKER_FLAGS) "$(DOCKER_IMAGE)"
|
||||
|
||||
|
@ -121,28 +134,26 @@ binary: build ## build the linux binaries
|
|||
dynbinary: build ## build the linux dynbinaries
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary
|
||||
|
||||
build: bundles init-go-pkg-cache
|
||||
build: DOCKER_BUILDKIT ?= 1
|
||||
build: bundles
|
||||
$(warning The docker client CLI has moved to github.com/docker/cli. For a dev-test cycle involving the CLI, run:${\n} DOCKER_CLI_PATH=/host/path/to/cli/binary make shell ${\n} then change the cli and compile into a binary at the same location.${\n})
|
||||
docker build ${BUILD_APT_MIRROR} ${DOCKER_BUILD_ARGS} -t "$(DOCKER_IMAGE)" -f "$(DOCKERFILE)" .
|
||||
DOCKER_BUILDKIT="${DOCKER_BUILDKIT}" docker build ${BUILD_APT_MIRROR} ${DOCKER_BUILD_ARGS} ${DOCKER_BUILD_OPTS} -t "$(DOCKER_IMAGE)" -f "$(DOCKERFILE)" .
|
||||
|
||||
bundles:
|
||||
mkdir bundles
|
||||
|
||||
clean: clean-pkg-cache-vol ## clean up cached resources
|
||||
.PHONY: clean
|
||||
clean: clean-cache
|
||||
|
||||
clean-pkg-cache-vol:
|
||||
@- $(foreach mapping,$(PKGCACHE_MAP), \
|
||||
$(shell docker volume rm $(PKGCACHE_VOLROOT)-$(shell echo $(mapping) | awk -F':/' '{ print $$1 }') > /dev/null 2>&1) \
|
||||
)
|
||||
.PHONY: clean-cache
|
||||
clean-cache:
|
||||
docker volume rm -f docker-dev-cache
|
||||
|
||||
cross: build ## cross build the binaries for darwin, freebsd and\nwindows
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary binary cross
|
||||
|
||||
help: ## this help
|
||||
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
||||
|
||||
init-go-pkg-cache:
|
||||
$(if $(PKGCACHE_DIR), mkdir -p $(shell echo $(PKGCACHE_MAP) | sed -E 's@([^: ]*):[^ ]*@$(PKGCACHE_DIR)/\1@g'))
|
||||
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9_-]+:.*?## / {gsub("\\\\n",sprintf("\n%22c",""), $$2);printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
||||
|
||||
install: ## install the linux binaries
|
||||
KEEPBUNDLE=1 hack/make.sh install-binary
|
||||
|
@ -164,6 +175,9 @@ test-integration-cli: test-integration ## (DEPRECATED) use test-integration
|
|||
test-integration: build ## run the integration tests
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary test-integration
|
||||
|
||||
test-integration-flaky: build ## run the stress test for all new integration tests
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary test-integration-flaky
|
||||
|
||||
test-unit: build ## run the unit tests
|
||||
$(DOCKER_RUN_DOCKER) hack/test/unit
|
||||
|
||||
|
@ -171,7 +185,7 @@ validate: build ## validate DCO, Seccomp profile generation, gofmt,\n./pkg/ isol
|
|||
$(DOCKER_RUN_DOCKER) hack/validate/all
|
||||
|
||||
win: build ## cross build the binary for windows
|
||||
$(DOCKER_RUN_DOCKER) hack/make.sh win
|
||||
$(DOCKER_RUN_DOCKER) DOCKER_CROSSPLATFORMS=windows/amd64 hack/make.sh cross
|
||||
|
||||
.PHONY: swagger-gen
|
||||
swagger-gen:
|
||||
|
@ -194,12 +208,11 @@ build-integration-cli-on-swarm: build ## build images and binary for running int
|
|||
go build -buildmode=pie -o ./hack/integration-cli-on-swarm/integration-cli-on-swarm ./hack/integration-cli-on-swarm/host
|
||||
@echo "Building $(INTEGRATION_CLI_MASTER_IMAGE)"
|
||||
docker build -t $(INTEGRATION_CLI_MASTER_IMAGE) hack/integration-cli-on-swarm/agent
|
||||
# For worker, we don't use `docker build` so as to enable DOCKER_INCREMENTAL_BINARY and so on
|
||||
@echo "Building $(INTEGRATION_CLI_WORKER_IMAGE) from $(DOCKER_IMAGE)"
|
||||
$(eval tmp := integration-cli-worker-tmp)
|
||||
# We mount pkgcache, but not bundle (bundle needs to be baked into the image)
|
||||
# For avoiding bakings DOCKER_GRAPHDRIVER and so on to image, we cannot use $(DOCKER_ENVS) here
|
||||
docker run -t -d --name $(tmp) -e DOCKER_GITCOMMIT -e BUILDFLAGS -e DOCKER_INCREMENTAL_BINARY --privileged $(DOCKER_MOUNT_PKGCACHE) $(DOCKER_IMAGE) top
|
||||
docker run -t -d --name $(tmp) -e DOCKER_GITCOMMIT -e BUILDFLAGS --privileged $(DOCKER_IMAGE) top
|
||||
docker exec $(tmp) hack/make.sh build-integration-test-binary dynbinary
|
||||
docker exec $(tmp) go build -buildmode=pie -o /worker github.com/docker/docker/hack/integration-cli-on-swarm/agent/worker
|
||||
docker commit -c 'ENTRYPOINT ["/worker"]' $(tmp) $(INTEGRATION_CLI_WORKER_IMAGE)
|
||||
|
|
|
@ -35,34 +35,83 @@ issue, in the Slack channel, or in person at the Moby Summits that happen every
|
|||
|
||||
## 1.1 Runtime improvements
|
||||
|
||||
We introduced [`runC`](https://runc.io) as a standalone low-level tool for container
|
||||
execution in 2015, the first stage in spinning out parts of the Engine into standalone tools.
|
||||
Over time we have accumulated a lot of functionality in the container runtime
|
||||
aspect of Moby while also growing in other areas. Much of the container runtime
|
||||
pieces are now duplicated work available in other, lower level components such
|
||||
as [containerd](https://containerd.io).
|
||||
|
||||
As runC continued evolving, and the OCI specification along with it, we created
|
||||
[`containerd`](https://github.com/containerd/containerd), a daemon to control and monitor `runC`.
|
||||
In late 2016 this was relaunched as the `containerd` 1.0 track, aiming to provide a common runtime
|
||||
for the whole spectrum of container systems, including Kubernetes, with wide community support.
|
||||
This change meant that there was an increased scope for `containerd`, including image management
|
||||
and storage drivers.
|
||||
Moby currently only utilizes containerd for basic runtime state management, e.g. starting
|
||||
and stopping a container, which is what the pre-containerd 1.0 daemon provided.
|
||||
Now that containerd is a full-fledged container runtime which supports full
|
||||
container life-cycle management, we would like to start relying more on containerd
|
||||
and removing the bits in Moby which are now duplicated. This will necessitate
|
||||
a significant effort to refactor and even remove large parts of Moby's codebase.
|
||||
|
||||
Moby will rely on a long-running `containerd` companion daemon for all container execution
|
||||
related operations. This could open the door in the future for Engine restarts without interrupting
|
||||
running containers. The switch over to containerd 1.0 is an important goal for the project, and
|
||||
will result in a significant simplification of the functions implemented in this repository.
|
||||
Tracking issues:
|
||||
|
||||
## 1.2 Internal decoupling
|
||||
- [#38043](https://github.com/moby/moby/issues/38043) Proposal: containerd image integration
|
||||
|
||||
## 1.2 Image Builder
|
||||
|
||||
Work is ongoing to integrate [BuildKit](https://github.com/moby/buildkit) into
|
||||
Moby and replace the "v0" build implementation. Buildkit offers better cache
|
||||
management, parallelizable build steps, and better extensibility while also
|
||||
keeping builds portable, a chief tenent of Moby's builder.
|
||||
|
||||
Upon completion of this effort, users will have a builder that performs better
|
||||
while also being more extensible, enabling users to provide their own custom
|
||||
syntax which can be either Dockerfile-like or something completely different.
|
||||
|
||||
See [buildpacks on buildkit](https://github.com/tonistiigi/buildkit-pack) as an
|
||||
example of this extensibility.
|
||||
|
||||
New features for the builder and Dockerfile should be implemented first in the
|
||||
BuildKit backend using an external Dockerfile implementation from the container
|
||||
images. This allows everyone to test and evaluate the feature without upgrading
|
||||
their daemon. New features should go to the experimental channel first, and can be
|
||||
part of the `docker/dockerfile:experimental` image. From there they graduate to
|
||||
`docker/dockerfile:latest` and binary releases. The Dockerfile frontend source
|
||||
code is temporarily located at
|
||||
[https://github.com/moby/buildkit/tree/master/frontend/dockerfile](https://github.com/moby/buildkit/tree/master/frontend/dockerfile)
|
||||
with separate new features defined with go build tags.
|
||||
|
||||
Tracking issues:
|
||||
|
||||
- [#32925](https://github.com/moby/moby/issues/32925) discussion: builder future: buildkit
|
||||
|
||||
## 1.3 Rootless Mode
|
||||
|
||||
Running the daemon requires elevated privileges for many tasks. We would like to
|
||||
support running the daemon as a normal, unprivileged user without requiring `suid`
|
||||
binaries.
|
||||
|
||||
Tracking issues:
|
||||
|
||||
- [#37375](https://github.com/moby/moby/issues/37375) Proposal: allow running `dockerd` as an unprivileged user (aka rootless mode)
|
||||
|
||||
## 1.4 Testing
|
||||
|
||||
Moby has many tests, both unit and integration. Moby needs more tests which can
|
||||
cover the full spectrum functionality and edge cases out there.
|
||||
|
||||
Tests in the `integration-cli` folder should also be migrated into (both in
|
||||
location and style) the `integration` folder. These newer tests are simpler to
|
||||
run in isolation, simpler to read, simpler to write, and more fully exercise the
|
||||
API. Meanwhile tests of the docker CLI should generally live in docker/cli.
|
||||
|
||||
Tracking issues:
|
||||
|
||||
- [#32866](https://github.com/moby/moby/issues/32866) Replace integration-cli suite with API test suite
|
||||
|
||||
## 1.5 Internal decoupling
|
||||
|
||||
A lot of work has been done in trying to decouple Moby internals. This process of creating
|
||||
standalone projects with a well defined function that attract a dedicated community should continue.
|
||||
As well as integrating `containerd` we would like to integrate [BuildKit](https://github.com/moby/buildkit)
|
||||
as the next standalone component.
|
||||
|
||||
We see gRPC as the natural communication layer between decoupled components.
|
||||
|
||||
## 1.3 Custom assembly tooling
|
||||
|
||||
We have been prototyping the Moby [assembly tool](https://github.com/moby/tool) which was originally
|
||||
developed for LinuxKit and intend to turn it into a more generic packaging and assembly mechanism
|
||||
that can build not only the default version of Moby, as distribution packages or other useful forms,
|
||||
but can also build very different container systems, themselves built of cooperating daemons built in
|
||||
and running in containers. We intend to merge this functionality into this repo.
|
||||
In addition to pushing out large components into other projects, much of the
|
||||
internal code structure, and in particular the
|
||||
["Daemon"](https://godoc.org/github.com/docker/docker/daemon#Daemon) object,
|
||||
should be split into smaller, more manageable, and more testable components.
|
||||
|
|
|
@ -8,11 +8,11 @@ questions you may have as an aspiring Moby contributor.
|
|||
Moby has two test suites (and one legacy test suite):
|
||||
|
||||
* Unit tests - use standard `go test` and
|
||||
[gotestyourself/assert](https://godoc.org/github.com/gotestyourself/gotestyourself/assert) assertions. They are located in
|
||||
[gotest.tools/assert](https://godoc.org/gotest.tools/assert) assertions. They are located in
|
||||
the package they test. Unit tests should be fast and test only their own
|
||||
package.
|
||||
* API integration tests - use standard `go test` and
|
||||
[gotestyourself/assert](https://godoc.org/github.com/gotestyourself/gotestyourself/assert) assertions. They are located in
|
||||
[gotest.tools/assert](https://godoc.org/gotest.tools/assert) assertions. They are located in
|
||||
`./integration/<component>` directories, where `component` is: container,
|
||||
image, volume, etc. These tests perform HTTP requests to an API endpoint and
|
||||
check the HTTP response and daemon state after the call.
|
||||
|
@ -47,6 +47,24 @@ Bugs fixes should include a unit test case which exercises the bug.
|
|||
A bug fix may also include new assertions in an existing integration tests for the
|
||||
API endpoint.
|
||||
|
||||
### Integration tests environment considerations
|
||||
|
||||
When adding new tests or modifying existing test under `integration/`, testing
|
||||
environment should be properly considered. `skip.If` from
|
||||
[gotest.tools/skip](https://godoc.org/gotest.tools/skip) can be used to make the
|
||||
test run conditionally. Full testing environment conditions can be found at
|
||||
[environment.go](https://github.com/moby/moby/blob/cb37987ee11655ed6bbef663d245e55922354c68/internal/test/environment/environment.go)
|
||||
|
||||
Here is a quick example. If the test needs to interact with a docker daemon on
|
||||
the same host, the following condition should be checked within the test code
|
||||
|
||||
```go
|
||||
skip.If(t, testEnv.IsRemoteDaemon())
|
||||
// your integration test code
|
||||
```
|
||||
|
||||
If a remote daemon is detected, the test will be skipped.
|
||||
|
||||
## Running tests
|
||||
|
||||
To run the unit test suite:
|
||||
|
|
|
@ -3,7 +3,7 @@ package api // import "github.com/docker/docker/api"
|
|||
// Common constants for daemon and client.
|
||||
const (
|
||||
// DefaultVersion of Current REST API
|
||||
DefaultVersion = "1.38"
|
||||
DefaultVersion = "1.40"
|
||||
|
||||
// NoBaseImageSpecifier is the symbol used by the FROM
|
||||
// command to specify that no base image is to be used.
|
||||
|
|
|
@ -19,10 +19,10 @@ produces:
|
|||
consumes:
|
||||
- "application/json"
|
||||
- "text/plain"
|
||||
basePath: "/v1.38"
|
||||
basePath: "/v1.40"
|
||||
info:
|
||||
title: "Docker Engine API"
|
||||
version: "1.38"
|
||||
version: "1.40"
|
||||
x-logo:
|
||||
url: "https://docs.docker.com/images/logo-docker-main.png"
|
||||
description: |
|
||||
|
@ -49,8 +49,8 @@ info:
|
|||
the URL is not supported by the daemon, a HTTP `400 Bad Request` error message
|
||||
is returned.
|
||||
|
||||
If you omit the version-prefix, the current version of the API (v1.38) is used.
|
||||
For example, calling `/info` is the same as calling `/v1.38/info`. Using the
|
||||
If you omit the version-prefix, the current version of the API (v1.40) is used.
|
||||
For example, calling `/info` is the same as calling `/v1.40/info`. Using the
|
||||
API without a version-prefix is deprecated and will be removed in a future release.
|
||||
|
||||
Engine releases in the near future should support this version of the API,
|
||||
|
@ -210,6 +210,43 @@ definitions:
|
|||
PathInContainer: "/dev/deviceName"
|
||||
CgroupPermissions: "mrw"
|
||||
|
||||
DeviceRequest:
|
||||
type: "object"
|
||||
description: "A request for devices to be sent to device drivers"
|
||||
properties:
|
||||
Driver:
|
||||
type: "string"
|
||||
example: "nvidia"
|
||||
Count:
|
||||
type: "integer"
|
||||
example: -1
|
||||
DeviceIDs:
|
||||
type: "array"
|
||||
items:
|
||||
type: "string"
|
||||
example:
|
||||
- "0"
|
||||
- "1"
|
||||
- "GPU-fef8089b-4820-abfc-e83e-94318197576e"
|
||||
Capabilities:
|
||||
description: |
|
||||
A list of capabilities; an OR list of AND lists of capabilities.
|
||||
type: "array"
|
||||
items:
|
||||
type: "array"
|
||||
items:
|
||||
type: "string"
|
||||
example:
|
||||
# gpu AND nvidia AND compute
|
||||
- ["gpu", "nvidia", "compute"]
|
||||
Options:
|
||||
description: |
|
||||
Driver-specific options, specified as a key/value pairs. These options
|
||||
are passed directly to the driver.
|
||||
type: "object"
|
||||
additionalProperties:
|
||||
type: "string"
|
||||
|
||||
ThrottleDevice:
|
||||
type: "object"
|
||||
properties:
|
||||
|
@ -238,11 +275,13 @@ definitions:
|
|||
- `bind` Mounts a file or directory from the host into the container. Must exist prior to creating the container.
|
||||
- `volume` Creates a volume with the given name and options (or uses a pre-existing volume with the same name and options). These are **not** removed when the container is removed.
|
||||
- `tmpfs` Create a tmpfs with the given options. The mount source cannot be specified for tmpfs.
|
||||
- `npipe` Mounts a named pipe from the host into the container. Must exist prior to creating the container.
|
||||
type: "string"
|
||||
enum:
|
||||
- "bind"
|
||||
- "volume"
|
||||
- "tmpfs"
|
||||
- "npipe"
|
||||
ReadOnly:
|
||||
description: "Whether the mount should be read-only."
|
||||
type: "boolean"
|
||||
|
@ -263,6 +302,10 @@ definitions:
|
|||
- "rshared"
|
||||
- "slave"
|
||||
- "rslave"
|
||||
NonRecursive:
|
||||
description: "Disable recursive bind mount."
|
||||
type: "boolean"
|
||||
default: false
|
||||
VolumeOptions:
|
||||
description: "Optional configuration for the `volume` type."
|
||||
type: "object"
|
||||
|
@ -415,6 +458,11 @@ definitions:
|
|||
items:
|
||||
type: "string"
|
||||
example: "c 13:* rwm"
|
||||
DeviceRequests:
|
||||
description: "a list of requests for devices to be sent to device drivers"
|
||||
type: "array"
|
||||
items:
|
||||
$ref: "#/definitions/DeviceRequest"
|
||||
DiskQuota:
|
||||
description: "Disk limit (in bytes)."
|
||||
type: "integer"
|
||||
|
@ -423,6 +471,11 @@ definitions:
|
|||
description: "Kernel memory limit in bytes."
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
example: 209715200
|
||||
KernelMemoryTCP:
|
||||
description: "Hard limit for kernel TCP buffer memory (in bytes)."
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
MemoryReservation:
|
||||
description: "Memory soft limit in bytes."
|
||||
type: "integer"
|
||||
|
@ -449,9 +502,11 @@ definitions:
|
|||
type: "boolean"
|
||||
x-nullable: true
|
||||
PidsLimit:
|
||||
description: "Tune a container's pids limit. Set -1 for unlimited."
|
||||
description: |
|
||||
Tune a container's PIDs limit. Set `0` or `-1` for unlimited, or `null` to not change.
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
x-nullable: true
|
||||
Ulimits:
|
||||
description: |
|
||||
A list of resource limits to set in the container. For example: `{"Name": "nofile", "Soft": 1024, "Hard": 2048}`"
|
||||
|
@ -634,14 +689,22 @@ definitions:
|
|||
$ref: "#/definitions/Mount"
|
||||
|
||||
# Applicable to UNIX platforms
|
||||
Capabilities:
|
||||
type: "array"
|
||||
description: |
|
||||
A list of kernel capabilities to be available for container (this overrides the default set).
|
||||
|
||||
Conflicts with options 'CapAdd' and 'CapDrop'"
|
||||
items:
|
||||
type: "string"
|
||||
CapAdd:
|
||||
type: "array"
|
||||
description: "A list of kernel capabilities to add to the container."
|
||||
description: "A list of kernel capabilities to add to the container. Conflicts with option 'Capabilities'"
|
||||
items:
|
||||
type: "string"
|
||||
CapDrop:
|
||||
type: "array"
|
||||
description: "A list of kernel capabilities to drop from the container."
|
||||
description: "A list of kernel capabilities to drop from the container. Conflicts with option 'Capabilities'"
|
||||
items:
|
||||
type: "string"
|
||||
Dns:
|
||||
|
@ -1473,11 +1536,9 @@ definitions:
|
|||
type: "string"
|
||||
Options:
|
||||
description: "Driver-specific options, specified as a map."
|
||||
type: "array"
|
||||
items:
|
||||
type: "object"
|
||||
additionalProperties:
|
||||
type: "string"
|
||||
type: "object"
|
||||
additionalProperties:
|
||||
type: "string"
|
||||
|
||||
NetworkContainer:
|
||||
type: "object"
|
||||
|
@ -1513,6 +1574,31 @@ definitions:
|
|||
aux:
|
||||
$ref: "#/definitions/ImageID"
|
||||
|
||||
BuildCache:
|
||||
type: "object"
|
||||
properties:
|
||||
ID:
|
||||
type: "string"
|
||||
Parent:
|
||||
type: "string"
|
||||
Type:
|
||||
type: "string"
|
||||
Description:
|
||||
type: "string"
|
||||
InUse:
|
||||
type: "boolean"
|
||||
Shared:
|
||||
type: "boolean"
|
||||
Size:
|
||||
type: "integer"
|
||||
CreatedAt:
|
||||
type: "integer"
|
||||
LastUsedAt:
|
||||
type: "integer"
|
||||
x-nullable: true
|
||||
UsageCount:
|
||||
type: "integer"
|
||||
|
||||
ImageID:
|
||||
type: "object"
|
||||
description: "Image ID or Digest"
|
||||
|
@ -2434,6 +2520,31 @@ definitions:
|
|||
description: "Whether there is currently a root CA rotation in progress for the swarm"
|
||||
type: "boolean"
|
||||
example: false
|
||||
DataPathPort:
|
||||
description: |
|
||||
DataPathPort specifies the data path port number for data traffic.
|
||||
Acceptable port range is 1024 to 49151.
|
||||
If no port is set or is set to 0, the default port (4789) is used.
|
||||
type: "integer"
|
||||
format: "uint32"
|
||||
default: 4789
|
||||
example: 4789
|
||||
DefaultAddrPool:
|
||||
description: |
|
||||
Default Address Pool specifies default subnet pools for global scope networks.
|
||||
type: "array"
|
||||
items:
|
||||
type: "string"
|
||||
format: "CIDR"
|
||||
example: ["10.10.0.0/16", "20.20.0.0/16"]
|
||||
SubnetSize:
|
||||
description: |
|
||||
SubnetSize specifies the subnet size of the networks created from the default subnet pool
|
||||
type: "integer"
|
||||
format: "uint32"
|
||||
maximum: 29
|
||||
default: 24
|
||||
example: 24
|
||||
|
||||
JoinTokens:
|
||||
description: |
|
||||
|
@ -2556,8 +2667,20 @@ definitions:
|
|||
type: "object"
|
||||
description: "CredentialSpec for managed service account (Windows only)"
|
||||
properties:
|
||||
Config:
|
||||
type: "string"
|
||||
example: "0bt9dmxjvjiqermk6xrop3ekq"
|
||||
description: |
|
||||
Load credential spec from a Swarm Config with the given ID.
|
||||
The specified config must also be present in the Configs field with the Runtime property set.
|
||||
|
||||
<p><br /></p>
|
||||
|
||||
|
||||
> **Note**: `CredentialSpec.File`, `CredentialSpec.Registry`, and `CredentialSpec.Config` are mutually exclusive.
|
||||
File:
|
||||
type: "string"
|
||||
example: "spec.json"
|
||||
description: |
|
||||
Load credential spec from this file. The file is read by the daemon, and must be present in the
|
||||
`CredentialSpecs` subdirectory in the docker data directory, which defaults to
|
||||
|
@ -2567,7 +2690,7 @@ definitions:
|
|||
|
||||
<p><br /></p>
|
||||
|
||||
> **Note**: `CredentialSpec.File` and `CredentialSpec.Registry` are mutually exclusive.
|
||||
> **Note**: `CredentialSpec.File`, `CredentialSpec.Registry`, and `CredentialSpec.Config` are mutually exclusive.
|
||||
Registry:
|
||||
type: "string"
|
||||
description: |
|
||||
|
@ -2579,7 +2702,7 @@ definitions:
|
|||
<p><br /></p>
|
||||
|
||||
|
||||
> **Note**: `CredentialSpec.File` and `CredentialSpec.Registry` are mutually exclusive.
|
||||
> **Note**: `CredentialSpec.File`, `CredentialSpec.Registry`, and `CredentialSpec.Config` are mutually exclusive.
|
||||
SELinuxContext:
|
||||
type: "object"
|
||||
description: "SELinux labels of the container"
|
||||
|
@ -2690,7 +2813,12 @@ definitions:
|
|||
type: "object"
|
||||
properties:
|
||||
File:
|
||||
description: "File represents a specific target that is backed by a file."
|
||||
description: |
|
||||
File represents a specific target that is backed by a file.
|
||||
|
||||
<p><br /><p>
|
||||
|
||||
> **Note**: `Configs.File` and `Configs.Runtime` are mutually exclusive
|
||||
type: "object"
|
||||
properties:
|
||||
Name:
|
||||
|
@ -2706,6 +2834,14 @@ definitions:
|
|||
description: "Mode represents the FileMode of the file."
|
||||
type: "integer"
|
||||
format: "uint32"
|
||||
Runtime:
|
||||
description: |
|
||||
Runtime represents a target that is not mounted into the container but is used by the task
|
||||
|
||||
<p><br /><p>
|
||||
|
||||
> **Note**: `Configs.File` and `Configs.Runtime` are mutually exclusive
|
||||
type: "object"
|
||||
ConfigID:
|
||||
description: "ConfigID represents the ID of the specific config that we're referencing."
|
||||
type: "string"
|
||||
|
@ -2725,6 +2861,18 @@ definitions:
|
|||
description: "Run an init inside the container that forwards signals and reaps processes. This field is omitted if empty, and the default (as configured on the daemon) is used."
|
||||
type: "boolean"
|
||||
x-nullable: true
|
||||
Sysctls:
|
||||
description: |
|
||||
Set kernel namedspaced parameters (sysctls) in the container.
|
||||
The Sysctls option on services accepts the same sysctls as the
|
||||
are supported on containers. Note that while the same sysctls are
|
||||
supported, no guarantees or checks are made about their
|
||||
suitability for a clustered environment, and it's up to the user
|
||||
to determine whether a given sysctl will work properly in a
|
||||
Service.
|
||||
type: "object"
|
||||
additionalProperties:
|
||||
type: "string"
|
||||
NetworkAttachmentSpec:
|
||||
description: |
|
||||
Read-only spec type for non-swarm containers attached to swarm overlay
|
||||
|
@ -2805,6 +2953,11 @@ definitions:
|
|||
SpreadDescriptor: "node.labels.datacenter"
|
||||
- Spread:
|
||||
SpreadDescriptor: "node.labels.rack"
|
||||
MaxReplicas:
|
||||
description: "Maximum number of replicas for per node (default value is 0, which is unlimited)"
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
default: 0
|
||||
Platforms:
|
||||
description: |
|
||||
Platforms stores all the platforms that the service's image can
|
||||
|
@ -3605,6 +3758,10 @@ definitions:
|
|||
See [cpuset(7)](https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt)
|
||||
type: "boolean"
|
||||
example: true
|
||||
PidsLimit:
|
||||
description: "Indicates if the host kernel has PID limit support enabled."
|
||||
type: "boolean"
|
||||
example: true
|
||||
OomKillDisable:
|
||||
description: "Indicates if OOM killer disable is supported on the host."
|
||||
type: "boolean"
|
||||
|
@ -3722,18 +3879,22 @@ definitions:
|
|||
description: |
|
||||
HTTP-proxy configured for the daemon. This value is obtained from the
|
||||
[`HTTP_PROXY`](https://www.gnu.org/software/wget/manual/html_node/Proxies.html) environment variable.
|
||||
Credentials ([user info component](https://tools.ietf.org/html/rfc3986#section-3.2.1)) in the proxy URL
|
||||
are masked in the API response.
|
||||
|
||||
Containers do not automatically inherit this configuration.
|
||||
type: "string"
|
||||
example: "http://user:pass@proxy.corp.example.com:8080"
|
||||
example: "http://xxxxx:xxxxx@proxy.corp.example.com:8080"
|
||||
HttpsProxy:
|
||||
description: |
|
||||
HTTPS-proxy configured for the daemon. This value is obtained from the
|
||||
[`HTTPS_PROXY`](https://www.gnu.org/software/wget/manual/html_node/Proxies.html) environment variable.
|
||||
Credentials ([user info component](https://tools.ietf.org/html/rfc3986#section-3.2.1)) in the proxy URL
|
||||
are masked in the API response.
|
||||
|
||||
Containers do not automatically inherit this configuration.
|
||||
type: "string"
|
||||
example: "https://user:pass@proxy.corp.example.com:4443"
|
||||
example: "https://xxxxx:xxxxx@proxy.corp.example.com:4443"
|
||||
NoProxy:
|
||||
description: |
|
||||
Comma-separated list of domain extensions for which no proxy should be
|
||||
|
@ -3823,10 +3984,10 @@ definitions:
|
|||
$ref: "#/definitions/Runtime"
|
||||
default:
|
||||
runc:
|
||||
path: "docker-runc"
|
||||
path: "runc"
|
||||
example:
|
||||
runc:
|
||||
path: "docker-runc"
|
||||
path: "runc"
|
||||
runc-master:
|
||||
path: "/go/bin/runc"
|
||||
custom:
|
||||
|
@ -3896,6 +4057,27 @@ definitions:
|
|||
- "name=seccomp,profile=default"
|
||||
- "name=selinux"
|
||||
- "name=userns"
|
||||
ProductLicense:
|
||||
description: |
|
||||
Reports a summary of the product license on the daemon.
|
||||
|
||||
If a commercial license has been applied to the daemon, information
|
||||
such as number of nodes, and expiration are included.
|
||||
type: "string"
|
||||
example: "Community Engine"
|
||||
Warnings:
|
||||
description: |
|
||||
List of warnings / informational messages about missing features, or
|
||||
issues related to the daemon configuration.
|
||||
|
||||
These messages can be printed by the client as information to the user.
|
||||
type: "array"
|
||||
items:
|
||||
type: "string"
|
||||
example:
|
||||
- "WARNING: No memory limit support"
|
||||
- "WARNING: bridge-nf-call-iptables is disabled"
|
||||
- "WARNING: bridge-nf-call-ip6tables is disabled"
|
||||
|
||||
|
||||
# PluginsInfo is a temp struct holding Plugins name
|
||||
|
@ -4516,7 +4698,7 @@ paths:
|
|||
OomKillDisable: false
|
||||
OomScoreAdj: 500
|
||||
PidMode: ""
|
||||
PidsLimit: -1
|
||||
PidsLimit: 0
|
||||
PortBindings:
|
||||
22/tcp:
|
||||
- HostPort: "11022"
|
||||
|
@ -5922,7 +6104,7 @@ paths:
|
|||
headers:
|
||||
X-Docker-Container-Path-Stat:
|
||||
type: "string"
|
||||
description: "TODO"
|
||||
description: "A base64 - encoded JSON object with some filesystem header information about the path"
|
||||
400:
|
||||
description: "Bad parameter"
|
||||
schema:
|
||||
|
@ -6319,6 +6501,11 @@ paths:
|
|||
description: "Target build stage"
|
||||
type: "string"
|
||||
default: ""
|
||||
- name: "outputs"
|
||||
in: "query"
|
||||
description: "BuildKit output configuration"
|
||||
type: "string"
|
||||
default: ""
|
||||
responses:
|
||||
200:
|
||||
description: "no error"
|
||||
|
@ -6337,6 +6524,29 @@ paths:
|
|||
produces:
|
||||
- "application/json"
|
||||
operationId: "BuildPrune"
|
||||
parameters:
|
||||
- name: "keep-storage"
|
||||
in: "query"
|
||||
description: "Amount of disk space in bytes to keep for cache"
|
||||
type: "integer"
|
||||
format: "int64"
|
||||
- name: "all"
|
||||
in: "query"
|
||||
type: "boolean"
|
||||
description: "Remove all types of build cache"
|
||||
- name: "filters"
|
||||
in: "query"
|
||||
type: "string"
|
||||
description: |
|
||||
A JSON encoded value of the filters (a `map[string][]string`) to process on the list of build cache objects. Available filters:
|
||||
- `until=<duration>`: duration relative to daemon's time, during which build cache was not used, in Go's duration format (e.g., '24h')
|
||||
- `id=<id>`
|
||||
- `parent=<id>`
|
||||
- `type=<string>`
|
||||
- `description=<string>`
|
||||
- `inuse`
|
||||
- `shared`
|
||||
- `private`
|
||||
responses:
|
||||
200:
|
||||
description: "No error"
|
||||
|
@ -6344,6 +6554,11 @@ paths:
|
|||
type: "object"
|
||||
title: "BuildPruneResponse"
|
||||
properties:
|
||||
CachesDeleted:
|
||||
type: "array"
|
||||
items:
|
||||
description: "ID of build cache object"
|
||||
type: "string"
|
||||
SpaceReclaimed:
|
||||
description: "Disk space reclaimed in bytes"
|
||||
type: "integer"
|
||||
|
@ -6972,9 +7187,57 @@ paths:
|
|||
API-Version:
|
||||
type: "string"
|
||||
description: "Max API Version the server supports"
|
||||
BuildKit-Version:
|
||||
type: "string"
|
||||
description: "Default version of docker image builder"
|
||||
Docker-Experimental:
|
||||
type: "boolean"
|
||||
description: "If the server is running with experimental mode enabled"
|
||||
Cache-Control:
|
||||
type: "string"
|
||||
default: "no-cache, no-store, must-revalidate"
|
||||
Pragma:
|
||||
type: "string"
|
||||
default: "no-cache"
|
||||
500:
|
||||
description: "server error"
|
||||
schema:
|
||||
$ref: "#/definitions/ErrorResponse"
|
||||
headers:
|
||||
Cache-Control:
|
||||
type: "string"
|
||||
default: "no-cache, no-store, must-revalidate"
|
||||
Pragma:
|
||||
type: "string"
|
||||
default: "no-cache"
|
||||
tags: ["System"]
|
||||
head:
|
||||
summary: "Ping"
|
||||
description: "This is a dummy endpoint you can use to test if the server is accessible."
|
||||
operationId: "SystemPingHead"
|
||||
produces: ["text/plain"]
|
||||
responses:
|
||||
200:
|
||||
description: "no error"
|
||||
schema:
|
||||
type: "string"
|
||||
example: "(empty)"
|
||||
headers:
|
||||
API-Version:
|
||||
type: "string"
|
||||
description: "Max API Version the server supports"
|
||||
BuildKit-Version:
|
||||
type: "string"
|
||||
description: "Default version of docker image builder"
|
||||
Docker-Experimental:
|
||||
type: "boolean"
|
||||
description: "If the server is running with experimental mode enabled"
|
||||
Cache-Control:
|
||||
type: "string"
|
||||
default: "no-cache, no-store, must-revalidate"
|
||||
Pragma:
|
||||
type: "string"
|
||||
default: "no-cache"
|
||||
500:
|
||||
description: "server error"
|
||||
schema:
|
||||
|
@ -7175,6 +7438,10 @@ paths:
|
|||
type: "array"
|
||||
items:
|
||||
$ref: "#/definitions/Volume"
|
||||
BuildCache:
|
||||
type: "array"
|
||||
items:
|
||||
$ref: "#/definitions/BuildCache"
|
||||
example:
|
||||
LayersSize: 1092588
|
||||
Images:
|
||||
|
@ -7589,6 +7856,7 @@ paths:
|
|||
schema:
|
||||
type: "object"
|
||||
title: "VolumeListResponse"
|
||||
description: "Volume list response"
|
||||
required: [Volumes, Warnings]
|
||||
properties:
|
||||
Volumes:
|
||||
|
@ -7665,6 +7933,8 @@ paths:
|
|||
description: "Volume configuration"
|
||||
schema:
|
||||
type: "object"
|
||||
description: "Volume configuration"
|
||||
title: "VolumeConfig"
|
||||
properties:
|
||||
Name:
|
||||
description: "The new volume's name. If not specified, Docker generates a name."
|
||||
|
@ -7865,6 +8135,10 @@ paths:
|
|||
description: |
|
||||
JSON encoded value of the filters (a `map[string][]string`) to process on the networks list. Available filters:
|
||||
|
||||
- `dangling=<boolean>` When set to `true` (or `1`), returns all
|
||||
networks that are not in use by a container. When set to `false`
|
||||
(or `0`), only networks that are in use by one or more
|
||||
containers are returned.
|
||||
- `driver=<driver-name>` Matches a network's driver.
|
||||
- `id=<network-id>` Matches all or part of a network ID.
|
||||
- `label=<key>` or `label=<key>=<value>` of a network label.
|
||||
|
@ -8582,6 +8856,7 @@ paths:
|
|||
- `label=<engine label>`
|
||||
- `membership=`(`accepted`|`pending`)`
|
||||
- `name=<node name>`
|
||||
- `node.label=<node label>`
|
||||
- `role=`(`manager`|`worker`)`
|
||||
type: "string"
|
||||
tags: ["Node"]
|
||||
|
@ -8754,14 +9029,36 @@ paths:
|
|||
nodes in order to reach the containers running on this node. Using this parameter it is possible to
|
||||
separate the container data traffic from the management traffic of the cluster.
|
||||
type: "string"
|
||||
DataPathPort:
|
||||
description: |
|
||||
DataPathPort specifies the data path port number for data traffic.
|
||||
Acceptable port range is 1024 to 49151.
|
||||
if no port is set or is set to 0, default port 4789 will be used.
|
||||
type: "integer"
|
||||
format: "uint32"
|
||||
DefaultAddrPool:
|
||||
description: |
|
||||
Default Address Pool specifies default subnet pools for global scope networks.
|
||||
type: "array"
|
||||
items:
|
||||
type: "string"
|
||||
example: ["10.10.0.0/16", "20.20.0.0/16"]
|
||||
ForceNewCluster:
|
||||
description: "Force creation of a new swarm."
|
||||
type: "boolean"
|
||||
SubnetSize:
|
||||
description: |
|
||||
SubnetSize specifies the subnet size of the networks created from the default subnet pool
|
||||
type: "integer"
|
||||
format: "uint32"
|
||||
Spec:
|
||||
$ref: "#/definitions/SwarmSpec"
|
||||
example:
|
||||
ListenAddr: "0.0.0.0:2377"
|
||||
AdvertiseAddr: "192.168.1.1:2377"
|
||||
DataPathPort: 4789
|
||||
DefaultAddrPool: ["10.10.0.0/8", "20.20.0.0/8"]
|
||||
SubnetSize: 24
|
||||
ForceNewCluster: false
|
||||
Spec:
|
||||
Orchestration: {}
|
||||
|
@ -9243,7 +9540,10 @@ paths:
|
|||
|
||||
- name: "version"
|
||||
in: "query"
|
||||
description: "The version number of the service object being updated. This is required to avoid conflicting writes."
|
||||
description: "The version number of the service object being updated.
|
||||
This is required to avoid conflicting writes.
|
||||
This version number should be the value as currently set on the service *before* the update.
|
||||
You can find the current version by calling `GET /services/{id}`"
|
||||
required: true
|
||||
type: "integer"
|
||||
- name: "registryAuthFrom"
|
||||
|
@ -9602,6 +9902,7 @@ paths:
|
|||
description: "Only return this number of log lines from the end of the logs. Specify as an integer or `all` to output all log lines."
|
||||
type: "string"
|
||||
default: "all"
|
||||
tags: ["Task"]
|
||||
/secrets:
|
||||
get:
|
||||
summary: "List secrets"
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/go-units"
|
||||
units "github.com/docker/go-units"
|
||||
)
|
||||
|
||||
// CheckpointCreateOptions holds parameters to create a checkpoint from a container
|
||||
|
@ -181,8 +181,33 @@ type ImageBuildOptions struct {
|
|||
Target string
|
||||
SessionID string
|
||||
Platform string
|
||||
// Version specifies the version of the unerlying builder to use
|
||||
Version BuilderVersion
|
||||
// BuildID is an optional identifier that can be passed together with the
|
||||
// build request. The same identifier can be used to gracefully cancel the
|
||||
// build with the cancel request.
|
||||
BuildID string
|
||||
// Outputs defines configurations for exporting build results. Only supported
|
||||
// in BuildKit mode
|
||||
Outputs []ImageBuildOutput
|
||||
}
|
||||
|
||||
// ImageBuildOutput defines configuration for exporting a build result
|
||||
type ImageBuildOutput struct {
|
||||
Type string
|
||||
Attrs map[string]string
|
||||
}
|
||||
|
||||
// BuilderVersion sets the version of underlying builder to use
|
||||
type BuilderVersion string
|
||||
|
||||
const (
|
||||
// BuilderV1 is the first generation builder in docker daemon
|
||||
BuilderV1 BuilderVersion = "1"
|
||||
// BuilderBuildKit is builder based on moby/buildkit project
|
||||
BuilderBuildKit = "2"
|
||||
)
|
||||
|
||||
// ImageBuildResponse holds information
|
||||
// returned by a server after building
|
||||
// an image.
|
||||
|
|
|
@ -55,3 +55,10 @@ type PluginEnableConfig struct {
|
|||
type PluginDisableConfig struct {
|
||||
ForceDisable bool
|
||||
}
|
||||
|
||||
// NetworkListConfig stores the options available for listing networks
|
||||
type NetworkListConfig struct {
|
||||
// TODO(@cpuguy83): naming is hard, this is pulled from what was being used in the router before moving here
|
||||
Detailed bool
|
||||
Verbose bool
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ type Config struct {
|
|||
Env []string // List of environment variable to set in the container
|
||||
Cmd strslice.StrSlice // Command to run when starting the container
|
||||
Healthcheck *HealthConfig `json:",omitempty"` // Healthcheck describes how to check the container is healthy
|
||||
ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (Windows specific)
|
||||
ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (meaning treat as a command line) (Windows specific).
|
||||
Image string // Name of the image as it was passed by the operator (e.g. could be symbolic)
|
||||
Volumes map[string]struct{} // List of volumes (mounts) used for the container
|
||||
WorkingDir string // Current directory (PWD) in the command will be launched
|
||||
|
|
|
@ -244,6 +244,16 @@ func (n PidMode) Container() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// DeviceRequest represents a request for devices from a device driver.
|
||||
// Used by GPU device drivers.
|
||||
type DeviceRequest struct {
|
||||
Driver string // Name of device driver
|
||||
Count int // Number of devices to request (-1 = All)
|
||||
DeviceIDs []string // List of device IDs as recognizable by the device driver
|
||||
Capabilities [][]string // An OR list of AND lists of device capabilities (e.g. "gpu")
|
||||
Options map[string]string // Options to pass onto the device driver
|
||||
}
|
||||
|
||||
// DeviceMapping represents the device mapping between the host and the container.
|
||||
type DeviceMapping struct {
|
||||
PathOnHost string
|
||||
|
@ -327,13 +337,15 @@ type Resources struct {
|
|||
CpusetMems string // CpusetMems 0-2, 0,1
|
||||
Devices []DeviceMapping // List of devices to map inside the container
|
||||
DeviceCgroupRules []string // List of rule to be added to the device cgroup
|
||||
DeviceRequests []DeviceRequest // List of device requests for device drivers
|
||||
DiskQuota int64 // Disk limit (in bytes)
|
||||
KernelMemory int64 // Kernel memory limit (in bytes)
|
||||
KernelMemoryTCP int64 // Hard limit for kernel TCP buffer memory (in bytes)
|
||||
MemoryReservation int64 // Memory soft limit (in bytes)
|
||||
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap
|
||||
MemorySwappiness *int64 // Tuning container memory swappiness behaviour
|
||||
OomKillDisable *bool // Whether to disable OOM Killer or not
|
||||
PidsLimit int64 // Setting pids limit for a container
|
||||
PidsLimit *int64 // Setting PIDs limit for a container; Set `0` or `-1` for unlimited, or `null` to not change.
|
||||
Ulimits []*units.Ulimit // List of ulimits to be set in the container
|
||||
|
||||
// Applicable to Windows
|
||||
|
@ -369,9 +381,10 @@ type HostConfig struct {
|
|||
// Applicable to UNIX platforms
|
||||
CapAdd strslice.StrSlice // List of kernel capabilities to add to the container
|
||||
CapDrop strslice.StrSlice // List of kernel capabilities to remove from the container
|
||||
DNS []string `json:"Dns"` // List of DNS server to lookup
|
||||
DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for
|
||||
DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for
|
||||
Capabilities []string `json:"Capabilities"` // List of kernel capabilities to be available for container (this overrides the default set)
|
||||
DNS []string `json:"Dns"` // List of DNS server to lookup
|
||||
DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for
|
||||
DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for
|
||||
ExtraHosts []string // List of extra hosts
|
||||
GroupAdd []string // List of additional groups that the container process will run as
|
||||
IpcMode IpcMode // IPC namespace to use for the container
|
||||
|
|
|
@ -323,6 +323,22 @@ func (args Args) WalkValues(field string, op func(value string) error) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Clone returns a copy of args.
|
||||
func (args Args) Clone() (newArgs Args) {
|
||||
newArgs.fields = make(map[string]map[string]bool, len(args.fields))
|
||||
for k, m := range args.fields {
|
||||
var mm map[string]bool
|
||||
if m != nil {
|
||||
mm = make(map[string]bool, len(m))
|
||||
for kk, v := range m {
|
||||
mm[kk] = v
|
||||
}
|
||||
}
|
||||
newArgs.fields[k] = mm
|
||||
}
|
||||
return newArgs
|
||||
}
|
||||
|
||||
func deprecatedArgs(d map[string][]string) map[string]map[string]bool {
|
||||
m := map[string]map[string]bool{}
|
||||
for k, v := range d {
|
||||
|
|
|
@ -79,7 +79,8 @@ const (
|
|||
|
||||
// BindOptions defines options specific to mounts of type "bind".
|
||||
type BindOptions struct {
|
||||
Propagation Propagation `json:",omitempty"`
|
||||
Propagation Propagation `json:",omitempty"`
|
||||
NonRecursive bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
// VolumeOptions represents the options for a mount of type volume.
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
package network // import "github.com/docker/docker/api/types/network"
|
||||
import (
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/errdefs"
|
||||
)
|
||||
|
||||
// Address represents an IP address
|
||||
type Address struct {
|
||||
|
@ -106,3 +110,18 @@ type NetworkingConfig struct {
|
|||
type ConfigReference struct {
|
||||
Network string
|
||||
}
|
||||
|
||||
var acceptedFilters = map[string]bool{
|
||||
"dangling": true,
|
||||
"driver": true,
|
||||
"id": true,
|
||||
"label": true,
|
||||
"name": true,
|
||||
"scope": true,
|
||||
"type": true,
|
||||
}
|
||||
|
||||
// ValidateFilters validates the list of filter args with the available filters.
|
||||
func ValidateFilters(filter filters.Args) error {
|
||||
return errdefs.InvalidParameter(filter.Validate(acceptedFilters))
|
||||
}
|
||||
|
|
|
@ -77,8 +77,9 @@ type Arg struct {
|
|||
|
||||
// Filter is used to conditionally apply Seccomp rules
|
||||
type Filter struct {
|
||||
Caps []string `json:"caps,omitempty"`
|
||||
Arches []string `json:"arches,omitempty"`
|
||||
Caps []string `json:"caps,omitempty"`
|
||||
Arches []string `json:"arches,omitempty"`
|
||||
MinKernel string `json:"minKernel,omitempty"`
|
||||
}
|
||||
|
||||
// Syscall is used to match a group of syscalls in Seccomp
|
||||
|
|
|
@ -120,7 +120,7 @@ type NetworkStats struct {
|
|||
RxBytes uint64 `json:"rx_bytes"`
|
||||
// Packets received. Windows and Linux.
|
||||
RxPackets uint64 `json:"rx_packets"`
|
||||
// Received errors. Not used on Windows. Note that we dont `omitempty` this
|
||||
// Received errors. Not used on Windows. Note that we don't `omitempty` this
|
||||
// field as it is expected in the >=v1.21 API stats structure.
|
||||
RxErrors uint64 `json:"rx_errors"`
|
||||
// Incoming packets dropped. Windows and Linux.
|
||||
|
@ -129,7 +129,7 @@ type NetworkStats struct {
|
|||
TxBytes uint64 `json:"tx_bytes"`
|
||||
// Packets sent. Windows and Linux.
|
||||
TxPackets uint64 `json:"tx_packets"`
|
||||
// Sent errors. Not used on Windows. Note that we dont `omitempty` this
|
||||
// Sent errors. Not used on Windows. Note that we don't `omitempty` this
|
||||
// field as it is expected in the >=v1.21 API stats structure.
|
||||
TxErrors uint64 `json:"tx_errors"`
|
||||
// Outgoing packets dropped. Windows and Linux.
|
||||
|
|
|
@ -27,9 +27,14 @@ type ConfigReferenceFileTarget struct {
|
|||
Mode os.FileMode
|
||||
}
|
||||
|
||||
// ConfigReferenceRuntimeTarget is a target for a config specifying that it
|
||||
// isn't mounted into the container but instead has some other purpose.
|
||||
type ConfigReferenceRuntimeTarget struct{}
|
||||
|
||||
// ConfigReference is a reference to a config in swarm
|
||||
type ConfigReference struct {
|
||||
File *ConfigReferenceFileTarget
|
||||
File *ConfigReferenceFileTarget `json:",omitempty"`
|
||||
Runtime *ConfigReferenceRuntimeTarget `json:",omitempty"`
|
||||
ConfigID string
|
||||
ConfigName string
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ type SELinuxContext struct {
|
|||
|
||||
// CredentialSpec for managed service account (Windows only)
|
||||
type CredentialSpec struct {
|
||||
Config string
|
||||
File string
|
||||
Registry string
|
||||
}
|
||||
|
@ -71,4 +72,5 @@ type ContainerSpec struct {
|
|||
Secrets []*SecretReference `json:",omitempty"`
|
||||
Configs []*ConfigReference `json:",omitempty"`
|
||||
Isolation container.Isolation `json:",omitempty"`
|
||||
Sysctls map[string]string `json:",omitempty"`
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// ClusterInfo represents info about the cluster for outputting in "info"
|
||||
// it contains the same information as "Swarm", but without the JoinTokens
|
||||
|
@ -10,6 +12,9 @@ type ClusterInfo struct {
|
|||
Spec Spec
|
||||
TLSInfo TLSInfo
|
||||
RootRotationInProgress bool
|
||||
DefaultAddrPool []string
|
||||
SubnetSize uint32
|
||||
DataPathPort uint32
|
||||
}
|
||||
|
||||
// Swarm represents a swarm.
|
||||
|
@ -149,10 +154,13 @@ type InitRequest struct {
|
|||
ListenAddr string
|
||||
AdvertiseAddr string
|
||||
DataPathAddr string
|
||||
DataPathPort uint32
|
||||
ForceNewCluster bool
|
||||
Spec Spec
|
||||
AutoLockManagers bool
|
||||
Availability NodeAvailability
|
||||
DefaultAddrPool []string
|
||||
SubnetSize uint32
|
||||
}
|
||||
|
||||
// JoinRequest is the request used to join a swarm.
|
||||
|
@ -201,6 +209,8 @@ type Info struct {
|
|||
Managers int `json:",omitempty"`
|
||||
|
||||
Cluster *ClusterInfo `json:",omitempty"`
|
||||
|
||||
Warnings []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// Peer represents a peer.
|
||||
|
|
|
@ -127,6 +127,7 @@ type ResourceRequirements struct {
|
|||
type Placement struct {
|
||||
Constraints []string `json:",omitempty"`
|
||||
Preferences []PlacementPreference `json:",omitempty"`
|
||||
MaxReplicas uint64 `json:",omitempty"`
|
||||
|
||||
// Platforms stores all the platforms that the image can run on.
|
||||
// This field is used in the platform filter for scheduling. If empty,
|
||||
|
|
|
@ -102,9 +102,10 @@ type ContainerStats struct {
|
|||
// Ping contains response of Engine API:
|
||||
// GET "/_ping"
|
||||
type Ping struct {
|
||||
APIVersion string
|
||||
OSType string
|
||||
Experimental bool
|
||||
APIVersion string
|
||||
OSType string
|
||||
Experimental bool
|
||||
BuilderVersion BuilderVersion
|
||||
}
|
||||
|
||||
// ComponentVersion describes the version information for a specific component.
|
||||
|
@ -157,10 +158,12 @@ type Info struct {
|
|||
MemoryLimit bool
|
||||
SwapLimit bool
|
||||
KernelMemory bool
|
||||
KernelMemoryTCP bool
|
||||
CPUCfsPeriod bool `json:"CpuCfsPeriod"`
|
||||
CPUCfsQuota bool `json:"CpuCfsQuota"`
|
||||
CPUShares bool
|
||||
CPUSet bool
|
||||
PidsLimit bool
|
||||
IPv4Forwarding bool
|
||||
BridgeNfIptables bool
|
||||
BridgeNfIP6tables bool `json:"BridgeNfIp6tables"`
|
||||
|
@ -204,6 +207,8 @@ type Info struct {
|
|||
RuncCommit Commit
|
||||
InitCommit Commit
|
||||
SecurityOptions []string
|
||||
ProductLicense string `json:",omitempty"`
|
||||
Warnings []string
|
||||
}
|
||||
|
||||
// KeyValue holds a key/value pair
|
||||
|
@ -512,7 +517,8 @@ type DiskUsage struct {
|
|||
Images []*ImageSummary
|
||||
Containers []*Container
|
||||
Volumes []*Volume
|
||||
BuilderSize int64
|
||||
BuildCache []*BuildCache
|
||||
BuilderSize int64 // deprecated
|
||||
}
|
||||
|
||||
// ContainersPruneReport contains the response for Engine API:
|
||||
|
@ -539,6 +545,7 @@ type ImagesPruneReport struct {
|
|||
// BuildCachePruneReport contains the response for Engine API:
|
||||
// POST "/build/prune"
|
||||
type BuildCachePruneReport struct {
|
||||
CachesDeleted []string
|
||||
SpaceReclaimed uint64
|
||||
}
|
||||
|
||||
|
@ -585,3 +592,24 @@ type PushResult struct {
|
|||
type BuildResult struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
// BuildCache contains information about a build cache record
|
||||
type BuildCache struct {
|
||||
ID string
|
||||
Parent string
|
||||
Type string
|
||||
Description string
|
||||
InUse bool
|
||||
Shared bool
|
||||
Size int64
|
||||
CreatedAt time.Time
|
||||
LastUsedAt *time.Time
|
||||
UsageCount int
|
||||
}
|
||||
|
||||
// BuildCachePruneOptions hold parameters to prune the build cache
|
||||
type BuildCachePruneOptions struct {
|
||||
All bool
|
||||
KeepStorage int64
|
||||
Filters filters.Args
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ package volume
|
|||
// See hack/generate-swagger-api.sh
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// VolumeCreateBody
|
||||
// VolumeCreateBody Volume configuration
|
||||
// swagger:model VolumeCreateBody
|
||||
type VolumeCreateBody struct {
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ package volume
|
|||
|
||||
import "github.com/docker/docker/api/types"
|
||||
|
||||
// VolumeListOKBody
|
||||
// VolumeListOKBody Volume list response
|
||||
// swagger:model VolumeListOKBody
|
||||
type VolumeListOKBody struct {
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
cli, err := client.NewEnvClient()
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package client // import "github.com/docker/docker/client"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// BuildCancel requests the daemon to cancel ongoing build request
|
||||
func (cli *Client) BuildCancel(ctx context.Context, id string) error {
|
||||
query := url.Values{}
|
||||
query.Set("id", id)
|
||||
|
||||
serverResp, err := cli.post(ctx, "/build/cancel", query, nil, nil)
|
||||
ensureReaderClosed(serverResp)
|
||||
return err
|
||||
}
|
|
@ -4,23 +4,38 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// BuildCachePrune requests the daemon to delete unused cache data
|
||||
func (cli *Client) BuildCachePrune(ctx context.Context) (*types.BuildCachePruneReport, error) {
|
||||
func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) {
|
||||
if err := cli.NewVersionError("1.31", "build prune"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
report := types.BuildCachePruneReport{}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/build/prune", nil, nil, nil)
|
||||
query := url.Values{}
|
||||
if opts.All {
|
||||
query.Set("all", "1")
|
||||
}
|
||||
query.Set("keep-storage", fmt.Sprintf("%d", opts.KeepStorage))
|
||||
filters, err := filters.ToJSON(opts.Filters)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "prune could not marshal filters option")
|
||||
}
|
||||
query.Set("filters", filters)
|
||||
|
||||
serverResp, err := cli.post(ctx, "/build/prune", query, nil, nil)
|
||||
defer ensureReaderClosed(serverResp)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer ensureReaderClosed(serverResp)
|
||||
|
||||
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
||||
return nil, fmt.Errorf("Error retrieving disk usage: %v", err)
|
||||
|
|
|
@ -18,11 +18,11 @@ func (cli *Client) CheckpointList(ctx context.Context, container string, options
|
|||
}
|
||||
|
||||
resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", query, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return checkpoints, wrapResponseError(err, resp, "container", container)
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&checkpoints)
|
||||
ensureReaderClosed(resp)
|
||||
return checkpoints, err
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ For example, to list running containers (the equivalent of "docker ps"):
|
|||
)
|
||||
|
||||
func main() {
|
||||
cli, err := client.NewEnvClient()
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -47,16 +47,13 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/go-connections/sockets"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -90,7 +87,7 @@ type Client struct {
|
|||
// If the request is non-GET return `ErrRedirect`. Otherwise use the last response.
|
||||
//
|
||||
// Go 1.8 changes behavior for HTTP redirects (specifically 301, 307, and 308) in the client .
|
||||
// The Docker client (and by extension docker API client) can be made to to send a request
|
||||
// The Docker client (and by extension docker API client) can be made to send a request
|
||||
// like POST /containers//start where what would normally be in the name section of the URL is empty.
|
||||
// This triggers an HTTP 301 from the daemon.
|
||||
// In go 1.8 this 301 will be converted to a GET request, and ends up getting a 404 from the daemon.
|
||||
|
@ -103,130 +100,6 @@ func CheckRedirect(req *http.Request, via []*http.Request) error {
|
|||
return ErrRedirect
|
||||
}
|
||||
|
||||
// NewEnvClient initializes a new API client based on environment variables.
|
||||
// See FromEnv for a list of support environment variables.
|
||||
//
|
||||
// Deprecated: use NewClientWithOpts(FromEnv)
|
||||
func NewEnvClient() (*Client, error) {
|
||||
return NewClientWithOpts(FromEnv)
|
||||
}
|
||||
|
||||
// FromEnv configures the client with values from environment variables.
|
||||
//
|
||||
// Supported environment variables:
|
||||
// DOCKER_HOST to set the url to the docker server.
|
||||
// DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest.
|
||||
// DOCKER_CERT_PATH to load the TLS certificates from.
|
||||
// DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
|
||||
func FromEnv(c *Client) error {
|
||||
if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
|
||||
options := tlsconfig.Options{
|
||||
CAFile: filepath.Join(dockerCertPath, "ca.pem"),
|
||||
CertFile: filepath.Join(dockerCertPath, "cert.pem"),
|
||||
KeyFile: filepath.Join(dockerCertPath, "key.pem"),
|
||||
InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "",
|
||||
}
|
||||
tlsc, err := tlsconfig.Client(options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.client = &http.Client{
|
||||
Transport: &http.Transport{TLSClientConfig: tlsc},
|
||||
CheckRedirect: CheckRedirect,
|
||||
}
|
||||
}
|
||||
|
||||
if host := os.Getenv("DOCKER_HOST"); host != "" {
|
||||
if err := WithHost(host)(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if version := os.Getenv("DOCKER_API_VERSION"); version != "" {
|
||||
c.version = version
|
||||
c.manualOverride = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithTLSClientConfig applies a tls config to the client transport.
|
||||
func WithTLSClientConfig(cacertPath, certPath, keyPath string) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
opts := tlsconfig.Options{
|
||||
CAFile: cacertPath,
|
||||
CertFile: certPath,
|
||||
KeyFile: keyPath,
|
||||
ExclusiveRootPools: true,
|
||||
}
|
||||
config, err := tlsconfig.Client(opts)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create tls config")
|
||||
}
|
||||
if transport, ok := c.client.Transport.(*http.Transport); ok {
|
||||
transport.TLSClientConfig = config
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf("cannot apply tls config to transport: %T", c.client.Transport)
|
||||
}
|
||||
}
|
||||
|
||||
// WithDialer applies the dialer.DialContext to the client transport. This can be
|
||||
// used to set the Timeout and KeepAlive settings of the client.
|
||||
func WithDialer(dialer *net.Dialer) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
if transport, ok := c.client.Transport.(*http.Transport); ok {
|
||||
transport.DialContext = dialer.DialContext
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf("cannot apply dialer to transport: %T", c.client.Transport)
|
||||
}
|
||||
}
|
||||
|
||||
// WithVersion overrides the client version with the specified one
|
||||
func WithVersion(version string) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
c.version = version
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithHost overrides the client host with the specified one.
|
||||
func WithHost(host string) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
hostURL, err := ParseHostURL(host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.host = host
|
||||
c.proto = hostURL.Scheme
|
||||
c.addr = hostURL.Host
|
||||
c.basePath = hostURL.Path
|
||||
if transport, ok := c.client.Transport.(*http.Transport); ok {
|
||||
return sockets.ConfigureTransport(transport, c.proto, c.addr)
|
||||
}
|
||||
return errors.Errorf("cannot apply host to transport: %T", c.client.Transport)
|
||||
}
|
||||
}
|
||||
|
||||
// WithHTTPClient overrides the client http client with the specified one
|
||||
func WithHTTPClient(client *http.Client) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
if client != nil {
|
||||
c.client = client
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithHTTPHeaders overrides the client default http headers
|
||||
func WithHTTPHeaders(headers map[string]string) func(*Client) error {
|
||||
return func(c *Client) error {
|
||||
c.customHTTPHeaders = headers
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// NewClientWithOpts initializes a new API client with default values. It takes functors
|
||||
// to modify values when creating it, like `NewClientWithOpts(WithVersion(…))`
|
||||
// It also initializes the custom http headers to add to each request.
|
||||
|
@ -242,7 +115,6 @@ func NewClientWithOpts(ops ...func(*Client) error) (*Client, error) {
|
|||
c := &Client{
|
||||
host: DefaultDockerHost,
|
||||
version: api.DefaultVersion,
|
||||
scheme: "http",
|
||||
client: client,
|
||||
proto: defaultProto,
|
||||
addr: defaultAddr,
|
||||
|
@ -257,14 +129,18 @@ func NewClientWithOpts(ops ...func(*Client) error) (*Client, error) {
|
|||
if _, ok := c.client.Transport.(http.RoundTripper); !ok {
|
||||
return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", c.client.Transport)
|
||||
}
|
||||
tlsConfig := resolveTLSConfig(c.client.Transport)
|
||||
if tlsConfig != nil {
|
||||
// TODO(stevvooe): This isn't really the right way to write clients in Go.
|
||||
// `NewClient` should probably only take an `*http.Client` and work from there.
|
||||
// Unfortunately, the model of having a host-ish/url-thingy as the connection
|
||||
// string has us confusing protocol and transport layers. We continue doing
|
||||
// this to avoid breaking existing clients but this should be addressed.
|
||||
c.scheme = "https"
|
||||
if c.scheme == "" {
|
||||
c.scheme = "http"
|
||||
|
||||
tlsConfig := resolveTLSConfig(c.client.Transport)
|
||||
if tlsConfig != nil {
|
||||
// TODO(stevvooe): This isn't really the right way to write clients in Go.
|
||||
// `NewClient` should probably only take an `*http.Client` and work from there.
|
||||
// Unfortunately, the model of having a host-ish/url-thingy as the connection
|
||||
// string has us confusing protocol and transport layers. We continue doing
|
||||
// this to avoid breaking existing clients but this should be addressed.
|
||||
c.scheme = "https"
|
||||
}
|
||||
}
|
||||
|
||||
return c, nil
|
||||
|
@ -283,18 +159,6 @@ func defaultHTTPClient(host string) (*http.Client, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// NewClient initializes a new API client for the given host and API version.
|
||||
// It uses the given http client as transport.
|
||||
// It also initializes the custom http headers to add to each request.
|
||||
//
|
||||
// It won't send any version information if the version number is empty. It is
|
||||
// highly recommended that you set a version or your client may break if the
|
||||
// server is upgraded.
|
||||
// Deprecated: use NewClientWithOpts
|
||||
func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) {
|
||||
return NewClientWithOpts(WithHost(host), WithVersion(version), WithHTTPClient(client), WithHTTPHeaders(httpHeaders))
|
||||
}
|
||||
|
||||
// Close the transport used by the client
|
||||
func (cli *Client) Close() error {
|
||||
if t, ok := cli.client.Transport.(*http.Transport); ok {
|
||||
|
@ -400,3 +264,16 @@ func (cli *Client) CustomHTTPHeaders() map[string]string {
|
|||
func (cli *Client) SetCustomHTTPHeaders(headers map[string]string) {
|
||||
cli.customHTTPHeaders = headers
|
||||
}
|
||||
|
||||
// Dialer returns a dialer for a raw stream connection, with HTTP/1.1 header, that can be used for proxying the daemon connection.
|
||||
// Used by `docker dial-stdio` (docker/cli#889).
|
||||
func (cli *Client) Dialer() func(context.Context) (net.Conn, error) {
|
||||
return func(ctx context.Context) (net.Conn, error) {
|
||||
if transport, ok := cli.client.Transport.(*http.Transport); ok {
|
||||
if transport.DialContext != nil && transport.TLSClientConfig == nil {
|
||||
return transport.DialContext(ctx, cli.proto, cli.addr)
|
||||
}
|
||||
}
|
||||
return fallbackDial(cli.proto, cli.addr, resolveTLSConfig(cli.client.Transport))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package client
|
||||
|
||||
import "net/http"
|
||||
|
||||
// NewClient initializes a new API client for the given host and API version.
|
||||
// It uses the given http client as transport.
|
||||
// It also initializes the custom http headers to add to each request.
|
||||
//
|
||||
// It won't send any version information if the version number is empty. It is
|
||||
// highly recommended that you set a version or your client may break if the
|
||||
// server is upgraded.
|
||||
// Deprecated: use NewClientWithOpts
|
||||
func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) {
|
||||
return NewClientWithOpts(WithHost(host), WithVersion(version), WithHTTPClient(client), WithHTTPHeaders(httpHeaders))
|
||||
}
|
||||
|
||||
// NewEnvClient initializes a new API client based on environment variables.
|
||||
// See FromEnv for a list of support environment variables.
|
||||
//
|
||||
// Deprecated: use NewClientWithOpts(FromEnv)
|
||||
func NewEnvClient() (*Client, error) {
|
||||
return NewClientWithOpts(FromEnv)
|
||||
}
|
|
@ -15,11 +15,11 @@ func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (t
|
|||
return response, err
|
||||
}
|
||||
resp, err := cli.post(ctx, "/configs/create", nil, config, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&response)
|
||||
ensureReaderClosed(resp)
|
||||
return response, err
|
||||
}
|
||||
|
|
|
@ -18,10 +18,10 @@ func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.C
|
|||
return swarm.Config{}, nil, err
|
||||
}
|
||||
resp, err := cli.get(ctx, "/configs/"+id, nil, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return swarm.Config{}, nil, wrapResponseError(err, resp, "config", id)
|
||||
}
|
||||
defer ensureReaderClosed(resp)
|
||||
|
||||
body, err := ioutil.ReadAll(resp.body)
|
||||
if err != nil {
|
||||
|
|
|
@ -27,12 +27,12 @@ func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptio
|
|||
}
|
||||
|
||||
resp, err := cli.get(ctx, "/configs", query, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var configs []swarm.Config
|
||||
err = json.NewDecoder(resp.body).Decode(&configs)
|
||||
ensureReaderClosed(resp)
|
||||
return configs, err
|
||||
}
|
||||
|
|
|
@ -8,6 +8,6 @@ func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
|
|||
return err
|
||||
}
|
||||
resp, err := cli.delete(ctx, "/configs/"+id, nil, nil)
|
||||
ensureReaderClosed(resp)
|
||||
defer ensureReaderClosed(resp)
|
||||
return wrapResponseError(err, resp, "config", id)
|
||||
}
|
||||
|
|
|
@ -45,11 +45,11 @@ func (cli *Client) ContainerCommit(ctx context.Context, container string, option
|
|||
|
||||
var response types.IDResponse
|
||||
resp, err := cli.post(ctx, "/commit", query, options.Config, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&response)
|
||||
ensureReaderClosed(resp)
|
||||
return response, err
|
||||
}
|
||||
|
|
|
@ -21,10 +21,10 @@ func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path stri
|
|||
|
||||
urlStr := "/containers/" + containerID + "/archive"
|
||||
response, err := cli.head(ctx, urlStr, query, nil)
|
||||
defer ensureReaderClosed(response)
|
||||
if err != nil {
|
||||
return types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+path)
|
||||
}
|
||||
defer ensureReaderClosed(response)
|
||||
return getContainerPathStatFromHeader(response.header)
|
||||
}
|
||||
|
||||
|
@ -45,11 +45,12 @@ func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath str
|
|||
apiPath := "/containers/" + containerID + "/archive"
|
||||
|
||||
response, err := cli.putRaw(ctx, apiPath, query, content, nil)
|
||||
defer ensureReaderClosed(response)
|
||||
if err != nil {
|
||||
return wrapResponseError(err, response, "container:path", containerID+":"+dstPath)
|
||||
}
|
||||
defer ensureReaderClosed(response)
|
||||
|
||||
// TODO this code converts non-error status-codes (e.g., "204 No Content") into an error; verify if this is the desired behavior
|
||||
if response.statusCode != http.StatusOK {
|
||||
return fmt.Errorf("unexpected status code from daemon: %d", response.statusCode)
|
||||
}
|
||||
|
@ -69,6 +70,7 @@ func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath s
|
|||
return nil, types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+srcPath)
|
||||
}
|
||||
|
||||
// TODO this code converts non-error status-codes (e.g., "204 No Content") into an error; verify if this is the desired behavior
|
||||
if response.statusCode != http.StatusOK {
|
||||
return nil, types.ContainerPathStat{}, fmt.Errorf("unexpected status code from daemon: %d", response.statusCode)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
|
@ -43,14 +42,11 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
|
|||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/containers/create", query, body, nil)
|
||||
defer ensureReaderClosed(serverResp)
|
||||
if err != nil {
|
||||
if serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
|
||||
return response, objectNotFoundError{object: "image", id: config.Image}
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(serverResp.body).Decode(&response)
|
||||
ensureReaderClosed(serverResp)
|
||||
return response, err
|
||||
}
|
||||
|
|
|
@ -13,11 +13,11 @@ func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]con
|
|||
var changes []container.ContainerChangeResponseItem
|
||||
|
||||
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil)
|
||||
defer ensureReaderClosed(serverResp)
|
||||
if err != nil {
|
||||
return changes, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(serverResp.body).Decode(&changes)
|
||||
ensureReaderClosed(serverResp)
|
||||
return changes, err
|
||||
}
|
||||
|
|
|
@ -16,11 +16,11 @@ func (cli *Client) ContainerExecCreate(ctx context.Context, container string, co
|
|||
}
|
||||
|
||||
resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
err = json.NewDecoder(resp.body).Decode(&response)
|
||||
ensureReaderClosed(resp)
|
||||
return response, err
|
||||
}
|
||||
|
||||
|
|
|
@ -16,13 +16,13 @@ func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (ty
|
|||
return types.ContainerJSON{}, objectNotFoundError{object: "container", id: containerID}
|
||||
}
|
||||
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil)
|
||||
defer ensureReaderClosed(serverResp)
|
||||
if err != nil {
|
||||
return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID)
|
||||
}
|
||||
|
||||
var response types.ContainerJSON
|
||||
err = json.NewDecoder(serverResp.body).Decode(&response)
|
||||
ensureReaderClosed(serverResp)
|
||||
return response, err
|
||||
}
|
||||
|
||||
|
@ -36,10 +36,10 @@ func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID stri
|
|||
query.Set("size", "1")
|
||||
}
|
||||
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil)
|
||||
defer ensureReaderClosed(serverResp)
|
||||
if err != nil {
|
||||
return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID)
|
||||
}
|
||||
defer ensureReaderClosed(serverResp)
|
||||
|
||||
body, err := ioutil.ReadAll(serverResp.body)
|
||||
if err != nil {
|
||||
|
|
|
@ -45,12 +45,12 @@ func (cli *Client) ContainerList(ctx context.Context, options types.ContainerLis
|
|||
}
|
||||
|
||||
resp, err := cli.get(ctx, "/containers/json", query, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var containers []types.Container
|
||||
err = json.NewDecoder(resp.body).Decode(&containers)
|
||||
ensureReaderClosed(resp)
|
||||
return containers, err
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@ func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Arg
|
|||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/containers/prune", query, nil, nil)
|
||||
defer ensureReaderClosed(serverResp)
|
||||
if err != nil {
|
||||
return report, err
|
||||
}
|
||||
defer ensureReaderClosed(serverResp)
|
||||
|
||||
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
||||
return report, fmt.Errorf("Error retrieving disk usage: %v", err)
|
||||
|
|
|
@ -22,6 +22,6 @@ func (cli *Client) ContainerRemove(ctx context.Context, containerID string, opti
|
|||
}
|
||||
|
||||
resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil)
|
||||
ensureReaderClosed(resp)
|
||||
defer ensureReaderClosed(resp)
|
||||
return wrapResponseError(err, resp, "container", containerID)
|
||||
}
|
||||
|
|
|
@ -18,11 +18,11 @@ func (cli *Client) ContainerTop(ctx context.Context, containerID string, argumen
|
|||
}
|
||||
|
||||
resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&response)
|
||||
ensureReaderClosed(resp)
|
||||
return response, err
|
||||
}
|
||||
|
|
|
@ -11,12 +11,11 @@ import (
|
|||
func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error) {
|
||||
var response container.ContainerUpdateOKBody
|
||||
serverResp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil)
|
||||
defer ensureReaderClosed(serverResp)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(serverResp.body).Decode(&response)
|
||||
|
||||
ensureReaderClosed(serverResp)
|
||||
return response, err
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@ func (cli *Client) DiskUsage(ctx context.Context) (types.DiskUsage, error) {
|
|||
var du types.DiskUsage
|
||||
|
||||
serverResp, err := cli.get(ctx, "/system/df", nil, nil)
|
||||
defer ensureReaderClosed(serverResp)
|
||||
if err != nil {
|
||||
return du, err
|
||||
}
|
||||
defer ensureReaderClosed(serverResp)
|
||||
|
||||
if err := json.NewDecoder(serverResp.body).Decode(&du); err != nil {
|
||||
return du, fmt.Errorf("Error retrieving disk usage: %v", err)
|
||||
|
|
|
@ -28,11 +28,11 @@ func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegist
|
|||
}
|
||||
|
||||
resp, err := cli.get(ctx, "/distribution/"+image+"/json", url.Values{}, headers)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return distributionInspect, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&distributionInspect)
|
||||
ensureReaderClosed(resp)
|
||||
return distributionInspect, err
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -32,16 +33,19 @@ func ErrorConnectionFailed(host string) error {
|
|||
return errConnectionFailed{host: host}
|
||||
}
|
||||
|
||||
// Deprecated: use the errdefs.NotFound() interface instead. Kept for backward compatibility
|
||||
type notFound interface {
|
||||
error
|
||||
NotFound() bool // Is the error a NotFound error
|
||||
NotFound() bool
|
||||
}
|
||||
|
||||
// IsErrNotFound returns true if the error is a NotFound error, which is returned
|
||||
// by the API when some object is not found.
|
||||
func IsErrNotFound(err error) bool {
|
||||
te, ok := err.(notFound)
|
||||
return ok && te.NotFound()
|
||||
if _, ok := err.(notFound); ok {
|
||||
return ok
|
||||
}
|
||||
return errdefs.IsNotFound(err)
|
||||
}
|
||||
|
||||
type objectNotFoundError struct {
|
||||
|
@ -49,9 +53,7 @@ type objectNotFoundError struct {
|
|||
id string
|
||||
}
|
||||
|
||||
func (e objectNotFoundError) NotFound() bool {
|
||||
return true
|
||||
}
|
||||
func (e objectNotFoundError) NotFound() {}
|
||||
|
||||
func (e objectNotFoundError) Error() string {
|
||||
return fmt.Sprintf("Error: No such %s: %s", e.object, e.id)
|
||||
|
@ -64,7 +66,7 @@ func wrapResponseError(err error, resp serverResponse, object, id string) error
|
|||
case resp.statusCode == http.StatusNotFound:
|
||||
return objectNotFoundError{object: object, id: id}
|
||||
case resp.statusCode == http.StatusNotImplemented:
|
||||
return notImplementedError{message: err.Error()}
|
||||
return errdefs.NotImplemented(err)
|
||||
default:
|
||||
return err
|
||||
}
|
||||
|
@ -83,8 +85,10 @@ func (u unauthorizedError) Error() string {
|
|||
// IsErrUnauthorized returns true if the error is caused
|
||||
// when a remote registry authentication fails
|
||||
func IsErrUnauthorized(err error) bool {
|
||||
_, ok := err.(unauthorizedError)
|
||||
return ok
|
||||
if _, ok := err.(unauthorizedError); ok {
|
||||
return ok
|
||||
}
|
||||
return errdefs.IsUnauthorized(err)
|
||||
}
|
||||
|
||||
type pluginPermissionDenied struct {
|
||||
|
@ -118,8 +122,10 @@ func (e notImplementedError) NotImplemented() bool {
|
|||
// This is returned by the API when a requested feature has not been
|
||||
// implemented.
|
||||
func IsErrNotImplemented(err error) bool {
|
||||
te, ok := err.(notImplementedError)
|
||||
return ok && te.NotImplemented()
|
||||
if _, ok := err.(notImplementedError); ok {
|
||||
return ok
|
||||
}
|
||||
return errdefs.IsNotImplemented(err)
|
||||
}
|
||||
|
||||
// NewVersionError returns an error if the APIVersion required
|
||||
|
|
|
@ -30,7 +30,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
|
|||
}
|
||||
req = cli.addHeaders(req, headers)
|
||||
|
||||
conn, err := cli.setupHijackConn(req, "tcp")
|
||||
conn, err := cli.setupHijackConn(ctx, req, "tcp")
|
||||
if err != nil {
|
||||
return types.HijackedResponse{}, err
|
||||
}
|
||||
|
@ -38,7 +38,20 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
|
|||
return types.HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn)}, err
|
||||
}
|
||||
|
||||
func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
|
||||
// DialHijack returns a hijacked connection with negotiated protocol proto.
|
||||
func (cli *Client) DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error) {
|
||||
req, err := http.NewRequest("POST", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req = cli.addHeaders(req, meta)
|
||||
|
||||
return cli.setupHijackConn(ctx, req, proto)
|
||||
}
|
||||
|
||||
// fallbackDial is used when WithDialer() was not called.
|
||||
// See cli.Dialer().
|
||||
func fallbackDial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
|
||||
if tlsConfig != nil && proto != "unix" && proto != "npipe" {
|
||||
return tls.Dial(proto, addr, tlsConfig)
|
||||
}
|
||||
|
@ -48,12 +61,13 @@ func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
|
|||
return net.Dial(proto, addr)
|
||||
}
|
||||
|
||||
func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, error) {
|
||||
func (cli *Client) setupHijackConn(ctx context.Context, req *http.Request, proto string) (net.Conn, error) {
|
||||
req.Host = cli.addr
|
||||
req.Header.Set("Connection", "Upgrade")
|
||||
req.Header.Set("Upgrade", proto)
|
||||
|
||||
conn, err := dial(cli.proto, cli.addr, resolveTLSConfig(cli.client.Transport))
|
||||
dialer := cli.Dialer()
|
||||
conn, err := dialer(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot connect to the Docker daemon. Is 'docker daemon' running on this host?")
|
||||
}
|
||||
|
|
|
@ -30,12 +30,6 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio
|
|||
}
|
||||
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
|
||||
|
||||
if options.Platform != "" {
|
||||
if err := cli.NewVersionError("1.32", "platform"); err != nil {
|
||||
return types.ImageBuildResponse{}, err
|
||||
}
|
||||
query.Set("platform", options.Platform)
|
||||
}
|
||||
headers.Set("Content-Type", "application/x-tar")
|
||||
|
||||
serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
|
||||
|
@ -131,7 +125,22 @@ func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (ur
|
|||
query.Set("session", options.SessionID)
|
||||
}
|
||||
if options.Platform != "" {
|
||||
if err := cli.NewVersionError("1.32", "platform"); err != nil {
|
||||
return query, err
|
||||
}
|
||||
query.Set("platform", strings.ToLower(options.Platform))
|
||||
}
|
||||
if options.BuildID != "" {
|
||||
query.Set("buildid", options.BuildID)
|
||||
}
|
||||
query.Set("version", string(options.Version))
|
||||
|
||||
if options.Outputs != nil {
|
||||
outputsJSON, err := json.Marshal(options.Outputs)
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
query.Set("outputs", string(outputsJSON))
|
||||
}
|
||||
return query, nil
|
||||
}
|
||||
|
|
|
@ -12,11 +12,11 @@ import (
|
|||
func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]image.HistoryResponseItem, error) {
|
||||
var history []image.HistoryResponseItem
|
||||
serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", url.Values{}, nil)
|
||||
defer ensureReaderClosed(serverResp)
|
||||
if err != nil {
|
||||
return history, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(serverResp.body).Decode(&history)
|
||||
ensureReaderClosed(serverResp)
|
||||
return history, err
|
||||
}
|
||||
|
|
|
@ -15,10 +15,10 @@ func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (typ
|
|||
return types.ImageInspect{}, nil, objectNotFoundError{object: "image", id: imageID}
|
||||
}
|
||||
serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil)
|
||||
defer ensureReaderClosed(serverResp)
|
||||
if err != nil {
|
||||
return types.ImageInspect{}, nil, wrapResponseError(err, serverResp, "image", imageID)
|
||||
}
|
||||
defer ensureReaderClosed(serverResp)
|
||||
|
||||
body, err := ioutil.ReadAll(serverResp.body)
|
||||
if err != nil {
|
||||
|
|
|
@ -35,11 +35,11 @@ func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions
|
|||
}
|
||||
|
||||
serverResp, err := cli.get(ctx, "/images/json", query, nil)
|
||||
defer ensureReaderClosed(serverResp)
|
||||
if err != nil {
|
||||
return images, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(serverResp.body).Decode(&images)
|
||||
ensureReaderClosed(serverResp)
|
||||
return images, err
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@ func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (
|
|||
}
|
||||
|
||||
serverResp, err := cli.post(ctx, "/images/prune", query, nil, nil)
|
||||
defer ensureReaderClosed(serverResp)
|
||||
if err != nil {
|
||||
return report, err
|
||||
}
|
||||
defer ensureReaderClosed(serverResp)
|
||||
|
||||
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
|
||||
return report, fmt.Errorf("Error retrieving disk usage: %v", err)
|
||||
|
|
|
@ -3,12 +3,12 @@ package client // import "github.com/docker/docker/client"
|
|||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/errdefs"
|
||||
)
|
||||
|
||||
// ImagePull requests the docker host to pull an image from a remote registry.
|
||||
|
@ -35,7 +35,7 @@ func (cli *Client) ImagePull(ctx context.Context, refStr string, options types.I
|
|||
}
|
||||
|
||||
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
|
||||
if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
|
||||
if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil {
|
||||
newAuthHeader, privilegeErr := options.PrivilegeFunc()
|
||||
if privilegeErr != nil {
|
||||
return nil, privilegeErr
|
||||
|
|
|
@ -4,11 +4,11 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/errdefs"
|
||||
)
|
||||
|
||||
// ImagePush requests the docker host to push an image to a remote registry.
|
||||
|
@ -36,7 +36,7 @@ func (cli *Client) ImagePush(ctx context.Context, image string, options types.Im
|
|||
query.Set("tag", tag)
|
||||
|
||||
resp, err := cli.tryImagePush(ctx, name, query, options.RegistryAuth)
|
||||
if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
|
||||
if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil {
|
||||
newAuthHeader, privilegeErr := options.PrivilegeFunc()
|
||||
if privilegeErr != nil {
|
||||
return nil, privilegeErr
|
||||
|
|
|
@ -21,11 +21,11 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options type
|
|||
|
||||
var dels []types.ImageDeleteResponseItem
|
||||
resp, err := cli.delete(ctx, "/images/"+imageID, query, nil)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return dels, wrapResponseError(err, resp, "image", imageID)
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.body).Decode(&dels)
|
||||
ensureReaderClosed(resp)
|
||||
return dels, err
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue