mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Lint on pkg/* packages
- pkg/useragent - pkg/units - pkg/ulimit - pkg/truncindex - pkg/timeoutconn - pkg/term - pkg/tarsum - pkg/tailfile - pkg/systemd - pkg/stringutils - pkg/stringid - pkg/streamformatter - pkg/sockets - pkg/signal - pkg/proxy - pkg/progressreader - pkg/pools - pkg/plugins - pkg/pidfile - pkg/parsers - pkg/parsers/filters - pkg/parsers/kernel - pkg/parsers/operatingsystem Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
		
							parent
							
								
									0852170e8c
								
							
						
					
					
						commit
						18c7c67308
					
				
					 61 changed files with 483 additions and 200 deletions
				
			
		| 
						 | 
				
			
			@ -1555,7 +1555,7 @@ func (s *Server) initTcpSocket(addr string) (l net.Listener, err error) {
 | 
			
		|||
	if s.cfg.TLSConfig == nil || s.cfg.TLSConfig.ClientAuth != tls.RequireAndVerifyClientCert {
 | 
			
		||||
		logrus.Warn("/!\\ DON'T BIND ON ANY IP ADDRESS WITHOUT setting -tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
 | 
			
		||||
	}
 | 
			
		||||
	if l, err = sockets.NewTcpSocket(addr, s.cfg.TLSConfig, s.start); err != nil {
 | 
			
		||||
	if l, err = sockets.NewTCPSocket(addr, s.cfg.TLSConfig, s.start); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := allocateDaemonPort(addr); err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -182,11 +182,11 @@ func Build(d *daemon.Daemon, buildConfig *Config) error {
 | 
			
		|||
 | 
			
		||||
	builder := &builder{
 | 
			
		||||
		Daemon: d,
 | 
			
		||||
		OutStream: &streamformatter.StdoutFormater{
 | 
			
		||||
		OutStream: &streamformatter.StdoutFormatter{
 | 
			
		||||
			Writer:          buildConfig.Stdout,
 | 
			
		||||
			StreamFormatter: sf,
 | 
			
		||||
		},
 | 
			
		||||
		ErrStream: &streamformatter.StderrFormater{
 | 
			
		||||
		ErrStream: &streamformatter.StderrFormatter{
 | 
			
		||||
			Writer:          buildConfig.Stdout,
 | 
			
		||||
			StreamFormatter: sf,
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -108,7 +108,7 @@ func checkKernel() error {
 | 
			
		|||
	if k, err := kernel.GetKernelVersion(); err != nil {
 | 
			
		||||
		logrus.Warnf("%s", err)
 | 
			
		||||
	} else {
 | 
			
		||||
		if kernel.CompareKernelVersion(k, &kernel.KernelVersionInfo{Kernel: 3, Major: 10, Minor: 0}) < 0 {
 | 
			
		||||
		if kernel.CompareKernelVersion(*k, kernel.VersionInfo{Kernel: 3, Major: 10, Minor: 0}) < 0 {
 | 
			
		||||
			if os.Getenv("DOCKER_NOWARN_KERNEL_VERSION") == "" {
 | 
			
		||||
				logrus.Warnf("You are running linux kernel version %s, which might be unstable running docker. Please upgrade your kernel to 3.10.0.", k.String())
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -193,7 +193,7 @@ func (cli *DaemonCli) CmdDaemon(args ...string) error {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var pfile *pidfile.PidFile
 | 
			
		||||
	var pfile *pidfile.PIDFile
 | 
			
		||||
	if cli.Pidfile != "" {
 | 
			
		||||
		pf, err := pidfile.New(cli.Pidfile)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,14 +28,37 @@ packages=(
 | 
			
		|||
	pkg/mount
 | 
			
		||||
	pkg/namesgenerator
 | 
			
		||||
	pkg/nat
 | 
			
		||||
	pkg/parsers
 | 
			
		||||
	pkg/parsers/filters
 | 
			
		||||
	pkg/parsers/kernel
 | 
			
		||||
	pkg/parsers/operatingsystem
 | 
			
		||||
	pkg/pidfile
 | 
			
		||||
	pkg/plugins
 | 
			
		||||
	pkg/pools
 | 
			
		||||
	pkg/progressreader
 | 
			
		||||
	pkg/promise
 | 
			
		||||
	pkg/proxy
 | 
			
		||||
	pkg/pubsub
 | 
			
		||||
	pkg/random
 | 
			
		||||
	pkg/reexec
 | 
			
		||||
	pkg/signal
 | 
			
		||||
	pkg/sockets
 | 
			
		||||
	pkg/streamformatter
 | 
			
		||||
	pkg/stringid
 | 
			
		||||
	pkg/stringutils
 | 
			
		||||
	pkg/systemd
 | 
			
		||||
	pkg/symlink
 | 
			
		||||
	pkg/tailfile
 | 
			
		||||
	pkg/tarsum
 | 
			
		||||
	pkg/term
 | 
			
		||||
	pkg/timeoutconn
 | 
			
		||||
	pkg/timeutils
 | 
			
		||||
	pkg/tlsconfig
 | 
			
		||||
	pkg/truncindex
 | 
			
		||||
	pkg/urlutil
 | 
			
		||||
	pkg/ulimit
 | 
			
		||||
	pkg/units
 | 
			
		||||
	pkg/useragent
 | 
			
		||||
	pkg/version
 | 
			
		||||
	registry
 | 
			
		||||
	utils
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// Package filters provides helper function to parse and handle command line
 | 
			
		||||
// filter, used for example in docker ps or docker images commands.
 | 
			
		||||
package filters
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -7,16 +9,22 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Args stores filter arguments as map key:{array of values}.
 | 
			
		||||
// It contains a aggregation of the list of arguments (which are in the form
 | 
			
		||||
// of -f 'key=value') based on the key, and store values for the same key
 | 
			
		||||
// in an slice.
 | 
			
		||||
// e.g given -f 'label=label1=1' -f 'label=label2=2' -f 'image.name=ubuntu'
 | 
			
		||||
// the args will be {'label': {'label1=1','label2=2'}, 'image.name', {'ubuntu'}}
 | 
			
		||||
type Args map[string][]string
 | 
			
		||||
 | 
			
		||||
// Parse the argument to the filter flag. Like
 | 
			
		||||
// ParseFlag parses the argument to the filter flag. Like
 | 
			
		||||
//
 | 
			
		||||
//   `docker ps -f 'created=today' -f 'image.name=ubuntu*'`
 | 
			
		||||
//
 | 
			
		||||
// If prev map is provided, then it is appended to, and returned. By default a new
 | 
			
		||||
// map is created.
 | 
			
		||||
func ParseFlag(arg string, prev Args) (Args, error) {
 | 
			
		||||
	var filters Args = prev
 | 
			
		||||
	filters := prev
 | 
			
		||||
	if prev == nil {
 | 
			
		||||
		filters = Args{}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +33,7 @@ func ParseFlag(arg string, prev Args) (Args, error) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	if !strings.Contains(arg, "=") {
 | 
			
		||||
		return filters, ErrorBadFormat
 | 
			
		||||
		return filters, ErrBadFormat
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f := strings.SplitN(arg, "=", 2)
 | 
			
		||||
| 
						 | 
				
			
			@ -36,9 +44,10 @@ func ParseFlag(arg string, prev Args) (Args, error) {
 | 
			
		|||
	return filters, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var ErrorBadFormat = errors.New("bad format of filter (expected name=value)")
 | 
			
		||||
// ErrBadFormat is an error returned in case of bad format for a filter.
 | 
			
		||||
var ErrBadFormat = errors.New("bad format of filter (expected name=value)")
 | 
			
		||||
 | 
			
		||||
// packs the Args into an string for easy transport from client to server
 | 
			
		||||
// ToParam packs the Args into an string for easy transport from client to server.
 | 
			
		||||
func ToParam(a Args) (string, error) {
 | 
			
		||||
	// this way we don't URL encode {}, just empty space
 | 
			
		||||
	if len(a) == 0 {
 | 
			
		||||
| 
						 | 
				
			
			@ -52,7 +61,7 @@ func ToParam(a Args) (string, error) {
 | 
			
		|||
	return string(buf), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// unpacks the filter Args
 | 
			
		||||
// FromParam unpacks the filter Args.
 | 
			
		||||
func FromParam(p string) (Args, error) {
 | 
			
		||||
	args := Args{}
 | 
			
		||||
	if len(p) == 0 {
 | 
			
		||||
| 
						 | 
				
			
			@ -64,6 +73,11 @@ func FromParam(p string) (Args, error) {
 | 
			
		|||
	return args, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MatchKVList returns true if the values for the specified field maches the ones
 | 
			
		||||
// from the sources.
 | 
			
		||||
// e.g. given Args are {'label': {'label1=1','label2=1'}, 'image.name', {'ubuntu'}},
 | 
			
		||||
//      field is 'label' and sources are {'label':{'label1=1','label2=2','label3=3'}}
 | 
			
		||||
//      it returns true.
 | 
			
		||||
func (filters Args) MatchKVList(field string, sources map[string]string) bool {
 | 
			
		||||
	fieldValues := filters[field]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -96,6 +110,10 @@ outer:
 | 
			
		|||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Match returns true if the values for the specified field matches the source string
 | 
			
		||||
// e.g. given Args are {'label': {'label1=1','label2=1'}, 'image.name', {'ubuntu'}},
 | 
			
		||||
//      field is 'image.name' and source is 'ubuntu'
 | 
			
		||||
//      it returns true.
 | 
			
		||||
func (filters Args) Match(field, source string) bool {
 | 
			
		||||
	fieldValues := filters[field]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,8 +39,8 @@ func TestParseArgsEdgeCase(t *testing.T) {
 | 
			
		|||
	if args == nil || len(args) != 0 {
 | 
			
		||||
		t.Fatalf("Expected an empty Args (map), got %v", args)
 | 
			
		||||
	}
 | 
			
		||||
	if args, err = ParseFlag("anything", args); err == nil || err != ErrorBadFormat {
 | 
			
		||||
		t.Fatalf("Expected ErrorBadFormat, got %v", err)
 | 
			
		||||
	if args, err = ParseFlag("anything", args); err == nil || err != ErrBadFormat {
 | 
			
		||||
		t.Fatalf("Expected ErrBadFormat, got %v", err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
// +build !windows
 | 
			
		||||
 | 
			
		||||
// Package kernel provides helper function to get, parse and compare kernel
 | 
			
		||||
// versions for different platforms.
 | 
			
		||||
package kernel
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -8,20 +10,21 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type KernelVersionInfo struct {
 | 
			
		||||
	Kernel int
 | 
			
		||||
	Major  int
 | 
			
		||||
	Minor  int
 | 
			
		||||
	Flavor string
 | 
			
		||||
// VersionInfo holds information about the kernel.
 | 
			
		||||
type VersionInfo struct {
 | 
			
		||||
	Kernel int    // Version of the kernel (e.g. 4.1.2-generic -> 4)
 | 
			
		||||
	Major  int    // Major part of the kernel version (e.g. 4.1.2-generic -> 1)
 | 
			
		||||
	Minor  int    // Minor part of the kernel version (e.g. 4.1.2-generic -> 2)
 | 
			
		||||
	Flavor string // Flavor of the kernel version (e.g. 4.1.2-generic -> generic)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (k *KernelVersionInfo) String() string {
 | 
			
		||||
func (k *VersionInfo) String() string {
 | 
			
		||||
	return fmt.Sprintf("%d.%d.%d%s", k.Kernel, k.Major, k.Minor, k.Flavor)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compare two KernelVersionInfo struct.
 | 
			
		||||
// CompareKernelVersion compares two kernel.VersionInfo structs.
 | 
			
		||||
// Returns -1 if a < b, 0 if a == b, 1 it a > b
 | 
			
		||||
func CompareKernelVersion(a, b *KernelVersionInfo) int {
 | 
			
		||||
func CompareKernelVersion(a, b VersionInfo) int {
 | 
			
		||||
	if a.Kernel < b.Kernel {
 | 
			
		||||
		return -1
 | 
			
		||||
	} else if a.Kernel > b.Kernel {
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +46,8 @@ func CompareKernelVersion(a, b *KernelVersionInfo) int {
 | 
			
		|||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetKernelVersion() (*KernelVersionInfo, error) {
 | 
			
		||||
// GetKernelVersion gets the current kernel version.
 | 
			
		||||
func GetKernelVersion() (*VersionInfo, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		err error
 | 
			
		||||
	)
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +71,8 @@ func GetKernelVersion() (*KernelVersionInfo, error) {
 | 
			
		|||
	return ParseRelease(string(release))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ParseRelease(release string) (*KernelVersionInfo, error) {
 | 
			
		||||
// ParseRelease parses a string and creates a VersionInfo based on it.
 | 
			
		||||
func ParseRelease(release string) (*VersionInfo, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		kernel, major, minor, parsed int
 | 
			
		||||
		flavor, partial              string
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +91,7 @@ func ParseRelease(release string) (*KernelVersionInfo, error) {
 | 
			
		|||
		flavor = partial
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &KernelVersionInfo{
 | 
			
		||||
	return &VersionInfo{
 | 
			
		||||
		Kernel: kernel,
 | 
			
		||||
		Major:  major,
 | 
			
		||||
		Minor:  minor,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,13 +5,13 @@ import (
 | 
			
		|||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func assertParseRelease(t *testing.T, release string, b *KernelVersionInfo, result int) {
 | 
			
		||||
func assertParseRelease(t *testing.T, release string, b *VersionInfo, result int) {
 | 
			
		||||
	var (
 | 
			
		||||
		a *KernelVersionInfo
 | 
			
		||||
		a *VersionInfo
 | 
			
		||||
	)
 | 
			
		||||
	a, _ = ParseRelease(release)
 | 
			
		||||
 | 
			
		||||
	if r := CompareKernelVersion(a, b); r != result {
 | 
			
		||||
	if r := CompareKernelVersion(*a, *b); r != result {
 | 
			
		||||
		t.Fatalf("Unexpected kernel version comparison result for (%v,%v). Found %d, expected %d", release, b, r, result)
 | 
			
		||||
	}
 | 
			
		||||
	if a.Flavor != b.Flavor {
 | 
			
		||||
| 
						 | 
				
			
			@ -20,13 +20,13 @@ func assertParseRelease(t *testing.T, release string, b *KernelVersionInfo, resu
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func TestParseRelease(t *testing.T) {
 | 
			
		||||
	assertParseRelease(t, "3.8.0", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 0)
 | 
			
		||||
	assertParseRelease(t, "3.4.54.longterm-1", &KernelVersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0)
 | 
			
		||||
	assertParseRelease(t, "3.4.54.longterm-1", &KernelVersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0)
 | 
			
		||||
	assertParseRelease(t, "3.8.0-19-generic", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "-19-generic"}, 0)
 | 
			
		||||
	assertParseRelease(t, "3.12.8tag", &KernelVersionInfo{Kernel: 3, Major: 12, Minor: 8, Flavor: "tag"}, 0)
 | 
			
		||||
	assertParseRelease(t, "3.12-1-amd64", &KernelVersionInfo{Kernel: 3, Major: 12, Minor: 0, Flavor: "-1-amd64"}, 0)
 | 
			
		||||
	assertParseRelease(t, "3.8.0", &KernelVersionInfo{Kernel: 4, Major: 8, Minor: 0}, -1)
 | 
			
		||||
	assertParseRelease(t, "3.8.0", &VersionInfo{Kernel: 3, Major: 8, Minor: 0}, 0)
 | 
			
		||||
	assertParseRelease(t, "3.4.54.longterm-1", &VersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0)
 | 
			
		||||
	assertParseRelease(t, "3.4.54.longterm-1", &VersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0)
 | 
			
		||||
	assertParseRelease(t, "3.8.0-19-generic", &VersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "-19-generic"}, 0)
 | 
			
		||||
	assertParseRelease(t, "3.12.8tag", &VersionInfo{Kernel: 3, Major: 12, Minor: 8, Flavor: "tag"}, 0)
 | 
			
		||||
	assertParseRelease(t, "3.12-1-amd64", &VersionInfo{Kernel: 3, Major: 12, Minor: 0, Flavor: "-1-amd64"}, 0)
 | 
			
		||||
	assertParseRelease(t, "3.8.0", &VersionInfo{Kernel: 4, Major: 8, Minor: 0}, -1)
 | 
			
		||||
	// Errors
 | 
			
		||||
	invalids := []string{
 | 
			
		||||
		"3",
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ func TestParseRelease(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func assertKernelVersion(t *testing.T, a, b *KernelVersionInfo, result int) {
 | 
			
		||||
func assertKernelVersion(t *testing.T, a, b VersionInfo, result int) {
 | 
			
		||||
	if r := CompareKernelVersion(a, b); r != result {
 | 
			
		||||
		t.Fatalf("Unexpected kernel version comparison result. Found %d, expected %d", r, result)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -50,43 +50,43 @@ func assertKernelVersion(t *testing.T, a, b *KernelVersionInfo, result int) {
 | 
			
		|||
 | 
			
		||||
func TestCompareKernelVersion(t *testing.T) {
 | 
			
		||||
	assertKernelVersion(t,
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		0)
 | 
			
		||||
	assertKernelVersion(t,
 | 
			
		||||
		&KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0},
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 2, Major: 6, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		-1)
 | 
			
		||||
	assertKernelVersion(t,
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		&KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 2, Major: 6, Minor: 0},
 | 
			
		||||
		1)
 | 
			
		||||
	assertKernelVersion(t,
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		0)
 | 
			
		||||
	assertKernelVersion(t,
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 5},
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 5},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		1)
 | 
			
		||||
	assertKernelVersion(t,
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 0, Minor: 20},
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 0, Minor: 20},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		-1)
 | 
			
		||||
	assertKernelVersion(t,
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 7, Minor: 20},
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 7, Minor: 20},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		-1)
 | 
			
		||||
	assertKernelVersion(t,
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 20},
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 7, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 20},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 7, Minor: 0},
 | 
			
		||||
		1)
 | 
			
		||||
	assertKernelVersion(t,
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 20},
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 20},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		1)
 | 
			
		||||
	assertKernelVersion(t,
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 20},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 0},
 | 
			
		||||
		VersionInfo{Kernel: 3, Major: 8, Minor: 20},
 | 
			
		||||
		-1)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,18 +6,20 @@ import (
 | 
			
		|||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type KernelVersionInfo struct {
 | 
			
		||||
	kvi   string
 | 
			
		||||
	major int
 | 
			
		||||
	minor int
 | 
			
		||||
	build int
 | 
			
		||||
// VersionInfo holds information about the kernel.
 | 
			
		||||
type VersionInfo struct {
 | 
			
		||||
	kvi   string // Version of the kernel (e.g. 6.1.7601.17592 -> 6)
 | 
			
		||||
	major int    // Major part of the kernel version (e.g. 6.1.7601.17592 -> 1)
 | 
			
		||||
	minor int    // Minor part of the kernel version (e.g. 6.1.7601.17592 -> 7601)
 | 
			
		||||
	build int    // Build number of the kernel version (e.g. 6.1.7601.17592 -> 17592)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (k *KernelVersionInfo) String() string {
 | 
			
		||||
func (k *VersionInfo) String() string {
 | 
			
		||||
	return fmt.Sprintf("%d.%d %d (%s)", k.major, k.minor, k.build, k.kvi)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetKernelVersion() (*KernelVersionInfo, error) {
 | 
			
		||||
// GetKernelVersion gets the current kernel version.
 | 
			
		||||
func GetKernelVersion() (*VersionInfo, error) {
 | 
			
		||||
 | 
			
		||||
	var (
 | 
			
		||||
		h         syscall.Handle
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +27,7 @@ func GetKernelVersion() (*KernelVersionInfo, error) {
 | 
			
		|||
		err       error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	KVI := &KernelVersionInfo{"Unknown", 0, 0, 0}
 | 
			
		||||
	KVI := &VersionInfo{"Unknown", 0, 0, 0}
 | 
			
		||||
 | 
			
		||||
	if err = syscall.RegOpenKeyEx(syscall.HKEY_LOCAL_MACHINE,
 | 
			
		||||
		syscall.StringToUTF16Ptr(`SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\`),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,9 @@ import (
 | 
			
		|||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Utsname represents the system name structure.
 | 
			
		||||
// It is passthgrouh for syscall.Utsname in order to make it portable with
 | 
			
		||||
// other platforms where it is not available.
 | 
			
		||||
type Utsname syscall.Utsname
 | 
			
		||||
 | 
			
		||||
func uname() (*syscall.Utsname, error) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,9 @@ import (
 | 
			
		|||
	"errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Utsname represents the system name structure.
 | 
			
		||||
// It is defined here to make it portable as it is available on linux but not
 | 
			
		||||
// on windows.
 | 
			
		||||
type Utsname struct {
 | 
			
		||||
	Release [65]byte
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// Package operatingsystem provides helper function to get the operating system
 | 
			
		||||
// name for different platforms.
 | 
			
		||||
package operatingsystem
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +16,7 @@ var (
 | 
			
		|||
	etcOsRelease = "/etc/os-release"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetOperatingSystem gets the name of the current operating system.
 | 
			
		||||
func GetOperatingSystem() (string, error) {
 | 
			
		||||
	b, err := ioutil.ReadFile(etcOsRelease)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +29,7 @@ func GetOperatingSystem() (string, error) {
 | 
			
		|||
	return "", errors.New("PRETTY_NAME not found")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsContainerized returns true if we are running inside a container.
 | 
			
		||||
func IsContainerized() (bool, error) {
 | 
			
		||||
	b, err := ioutil.ReadFile(proc1Cgroup)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ import (
 | 
			
		|||
// See https://code.google.com/p/go/source/browse/src/pkg/mime/type_windows.go?r=d14520ac25bf6940785aabb71f5be453a286f58c
 | 
			
		||||
// for a similar sample
 | 
			
		||||
 | 
			
		||||
// GetOperatingSystem gets the name of the current operating system.
 | 
			
		||||
func GetOperatingSystem() (string, error) {
 | 
			
		||||
 | 
			
		||||
	var h syscall.Handle
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +42,8 @@ func GetOperatingSystem() (string, error) {
 | 
			
		|||
	return ret, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// No-op on Windows
 | 
			
		||||
// IsContainerized returns true if we are running inside a container.
 | 
			
		||||
// No-op on Windows, always returns false.
 | 
			
		||||
func IsContainerized() (bool, error) {
 | 
			
		||||
	return false, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,6 @@
 | 
			
		|||
// Package parsers provides helper functions to parse and validate different type
 | 
			
		||||
// of string. It can be hosts, unix addresses, tcp addresses, filters, kernel
 | 
			
		||||
// operating system versions.
 | 
			
		||||
package parsers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -9,6 +12,8 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ParseHost parses the specified address and returns an address that will be used as the host.
 | 
			
		||||
// Depending of the address specified, will use the defaultTCPAddr or defaultUnixAddr
 | 
			
		||||
// FIXME: Change this not to receive default value as parameter
 | 
			
		||||
func ParseHost(defaultTCPAddr, defaultUnixAddr, addr string) (string, error) {
 | 
			
		||||
	addr = strings.TrimSpace(addr)
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +22,7 @@ func ParseHost(defaultTCPAddr, defaultUnixAddr, addr string) (string, error) {
 | 
			
		|||
			addr = fmt.Sprintf("unix://%s", defaultUnixAddr)
 | 
			
		||||
		} else {
 | 
			
		||||
			// Note - defaultTCPAddr already includes tcp:// prefix
 | 
			
		||||
			addr = fmt.Sprintf("%s", defaultTCPAddr)
 | 
			
		||||
			addr = defaultTCPAddr
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	addrParts := strings.Split(addr, "://")
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +42,10 @@ func ParseHost(defaultTCPAddr, defaultUnixAddr, addr string) (string, error) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseUnixAddr parses and validates that the specified address is a valid UNIX
 | 
			
		||||
// socket address. It returns a formatted UNIX socket address, either using the
 | 
			
		||||
// address parsed from addr, or the contents of defaultAddr if addr is a blank
 | 
			
		||||
// string.
 | 
			
		||||
func ParseUnixAddr(addr string, defaultAddr string) (string, error) {
 | 
			
		||||
	addr = strings.TrimPrefix(addr, "unix://")
 | 
			
		||||
	if strings.Contains(addr, "://") {
 | 
			
		||||
| 
						 | 
				
			
			@ -48,6 +57,9 @@ func ParseUnixAddr(addr string, defaultAddr string) (string, error) {
 | 
			
		|||
	return fmt.Sprintf("unix://%s", addr), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseTCPAddr parses and validates that the specified address is a valid TCP
 | 
			
		||||
// address. It returns a formatted TCP address, either using the address parsed
 | 
			
		||||
// from addr, or the contents of defaultAddr if addr is a blank string.
 | 
			
		||||
func ParseTCPAddr(addr string, defaultAddr string) (string, error) {
 | 
			
		||||
	addr = strings.TrimPrefix(addr, "tcp://")
 | 
			
		||||
	if strings.Contains(addr, "://") || addr == "" {
 | 
			
		||||
| 
						 | 
				
			
			@ -74,7 +86,7 @@ func ParseTCPAddr(addr string, defaultAddr string) (string, error) {
 | 
			
		|||
	return fmt.Sprintf("tcp://%s:%d%s", host, p, u.Path), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get a repos name and returns the right reposName + tag|digest
 | 
			
		||||
// ParseRepositoryTag gets a repos name and returns the right reposName + tag|digest
 | 
			
		||||
// The tag can be confusing because of a port in a repository name.
 | 
			
		||||
//     Ex: localhost.localdomain:5000/samalba/hipache:latest
 | 
			
		||||
//     Digest ex: localhost:5000/foo/bar@sha256:bc8813ea7b3603864987522f02a76101c17ad122e1c46d790efc0fca78ca7bfb
 | 
			
		||||
| 
						 | 
				
			
			@ -94,6 +106,8 @@ func ParseRepositoryTag(repos string) (string, string) {
 | 
			
		|||
	return repos, ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PartParser parses and validates the specified string (data) using the specified template
 | 
			
		||||
// e.g. ip:public:private -> 192.168.0.1:80:8000
 | 
			
		||||
func PartParser(template, data string) (map[string]string, error) {
 | 
			
		||||
	// ip:public:private
 | 
			
		||||
	var (
 | 
			
		||||
| 
						 | 
				
			
			@ -115,6 +129,7 @@ func PartParser(template, data string) (map[string]string, error) {
 | 
			
		|||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseKeyValueOpt parses and validates the specified string as a key/value pair (key=value)
 | 
			
		||||
func ParseKeyValueOpt(opt string) (string, string, error) {
 | 
			
		||||
	parts := strings.SplitN(opt, "=", 2)
 | 
			
		||||
	if len(parts) != 2 {
 | 
			
		||||
| 
						 | 
				
			
			@ -123,6 +138,7 @@ func ParseKeyValueOpt(opt string) (string, string, error) {
 | 
			
		|||
	return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParsePortRange parses and validates the specified string as a port-range (8000-9000)
 | 
			
		||||
func ParsePortRange(ports string) (uint64, uint64, error) {
 | 
			
		||||
	if ports == "" {
 | 
			
		||||
		return 0, 0, fmt.Errorf("Empty string specified for ports.")
 | 
			
		||||
| 
						 | 
				
			
			@ -148,6 +164,7 @@ func ParsePortRange(ports string) (uint64, uint64, error) {
 | 
			
		|||
	return start, end, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseLink parses and validates the specified string as a link format (name:alias)
 | 
			
		||||
func ParseLink(val string) (string, string, error) {
 | 
			
		||||
	if val == "" {
 | 
			
		||||
		return "", "", fmt.Errorf("empty string specified for links")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ import (
 | 
			
		|||
 | 
			
		||||
func TestParseHost(t *testing.T) {
 | 
			
		||||
	var (
 | 
			
		||||
		defaultHttpHost = "127.0.0.1"
 | 
			
		||||
		defaultHTTPHost = "127.0.0.1"
 | 
			
		||||
		defaultUnix     = "/var/run/docker.sock"
 | 
			
		||||
	)
 | 
			
		||||
	invalids := map[string]string{
 | 
			
		||||
| 
						 | 
				
			
			@ -32,12 +32,12 @@ func TestParseHost(t *testing.T) {
 | 
			
		|||
		"fd://something":          "fd://something",
 | 
			
		||||
	}
 | 
			
		||||
	for invalidAddr, expectedError := range invalids {
 | 
			
		||||
		if addr, err := ParseHost(defaultHttpHost, defaultUnix, invalidAddr); err == nil || err.Error() != expectedError {
 | 
			
		||||
		if addr, err := ParseHost(defaultHTTPHost, defaultUnix, invalidAddr); err == nil || err.Error() != expectedError {
 | 
			
		||||
			t.Errorf("tcp %v address expected error %v return, got %s and addr %v", invalidAddr, expectedError, err, addr)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for validAddr, expectedAddr := range valids {
 | 
			
		||||
		if addr, err := ParseHost(defaultHttpHost, defaultUnix, validAddr); err != nil || addr != expectedAddr {
 | 
			
		||||
		if addr, err := ParseHost(defaultHTTPHost, defaultUnix, validAddr); err != nil || addr != expectedAddr {
 | 
			
		||||
			t.Errorf("%v -> expected %v, got %v", validAddr, expectedAddr, addr)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,6 @@
 | 
			
		|||
// Package pidfile provides structure and helper functions to create and remove
 | 
			
		||||
// PID file. A PID file is usually a file used to store the process ID of a
 | 
			
		||||
// running process.
 | 
			
		||||
package pidfile
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -8,11 +11,12 @@ import (
 | 
			
		|||
	"strconv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type PidFile struct {
 | 
			
		||||
// PIDFile is a file used to store the process ID of a running process.
 | 
			
		||||
type PIDFile struct {
 | 
			
		||||
	path string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func checkPidFileAlreadyExists(path string) error {
 | 
			
		||||
func checkPIDFileAlreadyExists(path string) error {
 | 
			
		||||
	if pidString, err := ioutil.ReadFile(path); err == nil {
 | 
			
		||||
		if pid, err := strconv.Atoi(string(pidString)); err == nil {
 | 
			
		||||
			if _, err := os.Stat(filepath.Join("/proc", string(pid))); err == nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -23,18 +27,20 @@ func checkPidFileAlreadyExists(path string) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func New(path string) (*PidFile, error) {
 | 
			
		||||
	if err := checkPidFileAlreadyExists(path); err != nil {
 | 
			
		||||
// New creates a PIDfile using the specified path.
 | 
			
		||||
func New(path string) (*PIDFile, error) {
 | 
			
		||||
	if err := checkPIDFileAlreadyExists(path); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := ioutil.WriteFile(path, []byte(fmt.Sprintf("%d", os.Getpid())), 0644); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &PidFile{path: path}, nil
 | 
			
		||||
	return &PIDFile{path: path}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (file PidFile) Remove() error {
 | 
			
		||||
// Remove removes the PIDFile.
 | 
			
		||||
func (file PIDFile) Remove() error {
 | 
			
		||||
	if err := os.Remove(file.path); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,7 +24,7 @@ func TestNewAndRemove(t *testing.T) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func TestRemoveInvalidPath(t *testing.T) {
 | 
			
		||||
	file := PidFile{path: filepath.Join("foo", "bar")}
 | 
			
		||||
	file := PIDFile{path: filepath.Join("foo", "bar")}
 | 
			
		||||
 | 
			
		||||
	if err := file.Remove(); err == nil {
 | 
			
		||||
		t.Fatal("Non-existing file doesn't give an error on delete")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ const (
 | 
			
		|||
	defaultTimeOut  = 30
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewClient creates a new plugin client (http).
 | 
			
		||||
func NewClient(addr string, tlsConfig tlsconfig.Options) (*Client, error) {
 | 
			
		||||
	tr := &http.Transport{}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -33,11 +34,14 @@ func NewClient(addr string, tlsConfig tlsconfig.Options) (*Client, error) {
 | 
			
		|||
	return &Client{&http.Client{Transport: tr}, protoAndAddr[1]}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Client represents a plugin client.
 | 
			
		||||
type Client struct {
 | 
			
		||||
	http *http.Client
 | 
			
		||||
	addr string
 | 
			
		||||
	http *http.Client // http client to use
 | 
			
		||||
	addr string       // http address of the plugin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Call calls the specified method with the specified arguments for the plugin.
 | 
			
		||||
// It will retry for 30 seconds if a failure occurs when calling.
 | 
			
		||||
func (c *Client) Call(serviceMethod string, args interface{}, ret interface{}) error {
 | 
			
		||||
	return c.callWithRetry(serviceMethod, args, ret, true)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,22 +12,28 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// ErrNotFound plugin not found
 | 
			
		||||
	ErrNotFound = errors.New("Plugin not found")
 | 
			
		||||
	socketsPath = "/run/docker/plugins"
 | 
			
		||||
	specsPaths  = []string{"/etc/docker/plugins", "/usr/lib/docker/plugins"}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Registry defines behavior of a registry of plugins.
 | 
			
		||||
type Registry interface {
 | 
			
		||||
	// Plugins lists all plugins.
 | 
			
		||||
	Plugins() ([]*Plugin, error)
 | 
			
		||||
	// Plugin returns the plugin registered with the given name (or returns an error).
 | 
			
		||||
	Plugin(name string) (*Plugin, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LocalRegistry defines a registry that is local (using unix socket).
 | 
			
		||||
type LocalRegistry struct{}
 | 
			
		||||
 | 
			
		||||
func newLocalRegistry() LocalRegistry {
 | 
			
		||||
	return LocalRegistry{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Plugin returns the plugin registered with the given name (or returns an error).
 | 
			
		||||
func (l *LocalRegistry) Plugin(name string) (*Plugin, error) {
 | 
			
		||||
	socketpaths := pluginPaths(socketsPath, name, ".sock")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,25 @@
 | 
			
		|||
// Package plugins provides structures and helper functions to manage Docker
 | 
			
		||||
// plugins.
 | 
			
		||||
//
 | 
			
		||||
// Docker discovers plugins by looking for them in the plugin directory whenever
 | 
			
		||||
// a user or container tries to use one by name. UNIX domain socket files must
 | 
			
		||||
// be located under /run/docker/plugins, whereas spec files can be located
 | 
			
		||||
// either under /etc/docker/plugins or /usr/lib/docker/plugins. This is handled
 | 
			
		||||
// by the Registry interface, which lets you list all plugins or get a plugin by
 | 
			
		||||
// its name if it exists.
 | 
			
		||||
//
 | 
			
		||||
// The plugins need to implement an HTTP server and bind this to the UNIX socket
 | 
			
		||||
// or the address specified in the spec files.
 | 
			
		||||
// A handshake is send at /Plugin.Activate, and plugins are expected to return
 | 
			
		||||
// a Manifest with a list of of Docker subsystems which this plugin implements.
 | 
			
		||||
//
 | 
			
		||||
// In order to use a plugins, you can use the ``Get`` with the name of the
 | 
			
		||||
// plugin and the subsystem it implements.
 | 
			
		||||
//
 | 
			
		||||
//	plugin, err := plugins.Get("example", "VolumeDriver")
 | 
			
		||||
//	if err != nil {
 | 
			
		||||
//		return fmt.Errorf("Error looking up volume plugin example: %v", err)
 | 
			
		||||
//	}
 | 
			
		||||
package plugins
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -9,6 +31,7 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// ErrNotImplements is returned if the plugin does not implement the requested driver.
 | 
			
		||||
	ErrNotImplements = errors.New("Plugin does not implement the requested driver")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -22,16 +45,24 @@ var (
 | 
			
		|||
	extpointHandlers = make(map[string]func(string, *Client))
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Manifest lists what a plugin implements.
 | 
			
		||||
type Manifest struct {
 | 
			
		||||
	// List of subsystem the plugin implements.
 | 
			
		||||
	Implements []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Plugin is the definition of a docker plugin.
 | 
			
		||||
type Plugin struct {
 | 
			
		||||
	Name      string `json:"-"`
 | 
			
		||||
	Addr      string
 | 
			
		||||
	// Name of the plugin
 | 
			
		||||
	Name string `json:"-"`
 | 
			
		||||
	// Address of the plugin
 | 
			
		||||
	Addr string
 | 
			
		||||
	// TLS configuration of the plugin
 | 
			
		||||
	TLSConfig tlsconfig.Options
 | 
			
		||||
	Client    *Client   `json:"-"`
 | 
			
		||||
	Manifest  *Manifest `json:"-"`
 | 
			
		||||
	// Client attached to the plugin
 | 
			
		||||
	Client *Client `json:"-"`
 | 
			
		||||
	// Manifest of the plugin (see above)
 | 
			
		||||
	Manifest *Manifest `json:"-"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newLocalPlugin(name, addr string) *Plugin {
 | 
			
		||||
| 
						 | 
				
			
			@ -96,6 +127,7 @@ func get(name string) (*Plugin, error) {
 | 
			
		|||
	return pl, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get returns the plugin given the specified name and requested implementation.
 | 
			
		||||
func Get(name, imp string) (*Plugin, error) {
 | 
			
		||||
	pl, err := get(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -110,6 +142,7 @@ func Get(name, imp string) (*Plugin, error) {
 | 
			
		|||
	return nil, ErrNotImplements
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Handle adds the specified function to the extpointHandlers.
 | 
			
		||||
func Handle(iface string, fn func(string, *Client)) {
 | 
			
		||||
	extpointHandlers[iface] = fn
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,14 +18,15 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// Pool which returns bufio.Reader with a 32K buffer
 | 
			
		||||
	// BufioReader32KPool is a pool which returns bufio.Reader with a 32K buffer.
 | 
			
		||||
	BufioReader32KPool *BufioReaderPool
 | 
			
		||||
	// Pool which returns bufio.Writer with a 32K buffer
 | 
			
		||||
	// BufioWriter32KPool is a pool which returns bufio.Writer with a 32K buffer.
 | 
			
		||||
	BufioWriter32KPool *BufioWriterPool
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const buffer32K = 32 * 1024
 | 
			
		||||
 | 
			
		||||
// BufioReaderPool is a bufio reader that uses sync.Pool.
 | 
			
		||||
type BufioReaderPool struct {
 | 
			
		||||
	pool sync.Pool
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +58,7 @@ func (bufPool *BufioReaderPool) Put(b *bufio.Reader) {
 | 
			
		|||
	bufPool.pool.Put(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Copy is a convenience wrapper which uses a buffer to avoid allocation in io.Copy
 | 
			
		||||
// Copy is a convenience wrapper which uses a buffer to avoid allocation in io.Copy.
 | 
			
		||||
func Copy(dst io.Writer, src io.Reader) (written int64, err error) {
 | 
			
		||||
	buf := BufioReader32KPool.Get(src)
 | 
			
		||||
	written, err = io.Copy(dst, buf)
 | 
			
		||||
| 
						 | 
				
			
			@ -77,6 +78,7 @@ func (bufPool *BufioReaderPool) NewReadCloserWrapper(buf *bufio.Reader, r io.Rea
 | 
			
		|||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BufioWriterPool is a bufio writer that uses sync.Pool.
 | 
			
		||||
type BufioWriterPool struct {
 | 
			
		||||
	pool sync.Pool
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// Package progressreader provides a Reader with a progress bar that can be
 | 
			
		||||
// printed out using the streamformatter package.
 | 
			
		||||
package progressreader
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -7,7 +9,7 @@ import (
 | 
			
		|||
	"github.com/docker/docker/pkg/streamformatter"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Reader with progress bar
 | 
			
		||||
// Config contains the configuration for a Reader with progress bar.
 | 
			
		||||
type Config struct {
 | 
			
		||||
	In         io.ReadCloser // Stream to read from
 | 
			
		||||
	Out        io.Writer     // Where to send progress bar to
 | 
			
		||||
| 
						 | 
				
			
			@ -20,6 +22,7 @@ type Config struct {
 | 
			
		|||
	Action     string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// New creates a new Config.
 | 
			
		||||
func New(newReader Config) *Config {
 | 
			
		||||
	return &newReader
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -48,6 +51,7 @@ func (config *Config) Read(p []byte) (n int, err error) {
 | 
			
		|||
	return read, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close closes the reader (Config).
 | 
			
		||||
func (config *Config) Close() error {
 | 
			
		||||
	if config.Current < config.Size {
 | 
			
		||||
		//print a full progress bar when closing prematurely
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// Package proxy provides a network Proxy interface and implementations for TCP
 | 
			
		||||
// and UDP.
 | 
			
		||||
package proxy
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -5,18 +7,24 @@ import (
 | 
			
		|||
	"net"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Proxy defines the behavior of a proxy. It forwards traffic back and forth
 | 
			
		||||
// between two endpoints : the frontend and the backend.
 | 
			
		||||
// It can be used to do software port-mapping between two addresses.
 | 
			
		||||
// e.g. forward all traffic between the frontend (host) 127.0.0.1:3000
 | 
			
		||||
// to the backend (container) at 172.17.42.108:4000.
 | 
			
		||||
type Proxy interface {
 | 
			
		||||
	// Start forwarding traffic back and forth the front and back-end
 | 
			
		||||
	// addresses.
 | 
			
		||||
	// Run starts forwarding traffic back and forth between the front
 | 
			
		||||
	// and back-end addresses.
 | 
			
		||||
	Run()
 | 
			
		||||
	// Stop forwarding traffic and close both ends of the Proxy.
 | 
			
		||||
	// Close stops forwarding traffic and close both ends of the Proxy.
 | 
			
		||||
	Close()
 | 
			
		||||
	// Return the address on which the proxy is listening.
 | 
			
		||||
	// FrontendAddr returns the address on which the proxy is listening.
 | 
			
		||||
	FrontendAddr() net.Addr
 | 
			
		||||
	// Return the proxied address.
 | 
			
		||||
	// BackendAddr returns the proxied address.
 | 
			
		||||
	BackendAddr() net.Addr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewProxy creates a Proxy according to the specified frontendAddr and backendAddr.
 | 
			
		||||
func NewProxy(frontendAddr, backendAddr net.Addr) (Proxy, error) {
 | 
			
		||||
	switch frontendAddr.(type) {
 | 
			
		||||
	case *net.UDPAddr:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,16 +4,25 @@ import (
 | 
			
		|||
	"net"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// StubProxy is a proxy that is a stub (does nothing).
 | 
			
		||||
type StubProxy struct {
 | 
			
		||||
	frontendAddr net.Addr
 | 
			
		||||
	backendAddr  net.Addr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *StubProxy) Run()                   {}
 | 
			
		||||
func (p *StubProxy) Close()                 {}
 | 
			
		||||
func (p *StubProxy) FrontendAddr() net.Addr { return p.frontendAddr }
 | 
			
		||||
func (p *StubProxy) BackendAddr() net.Addr  { return p.backendAddr }
 | 
			
		||||
// Run does nothing.
 | 
			
		||||
func (p *StubProxy) Run() {}
 | 
			
		||||
 | 
			
		||||
// Close does nothing.
 | 
			
		||||
func (p *StubProxy) Close() {}
 | 
			
		||||
 | 
			
		||||
// FrontendAddr returns the frontend address.
 | 
			
		||||
func (p *StubProxy) FrontendAddr() net.Addr { return p.frontendAddr }
 | 
			
		||||
 | 
			
		||||
// BackendAddr returns the backend address.
 | 
			
		||||
func (p *StubProxy) BackendAddr() net.Addr { return p.backendAddr }
 | 
			
		||||
 | 
			
		||||
// NewStubProxy creates a new StubProxy
 | 
			
		||||
func NewStubProxy(frontendAddr, backendAddr net.Addr) (Proxy, error) {
 | 
			
		||||
	return &StubProxy{
 | 
			
		||||
		frontendAddr: frontendAddr,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,12 +8,15 @@ import (
 | 
			
		|||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TCPProxy is a proxy for TCP connections. It implements the Proxy interface to
 | 
			
		||||
// handle TCP traffic forwarding between the frontend and backend addresses.
 | 
			
		||||
type TCPProxy struct {
 | 
			
		||||
	listener     *net.TCPListener
 | 
			
		||||
	frontendAddr *net.TCPAddr
 | 
			
		||||
	backendAddr  *net.TCPAddr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewTCPProxy creates a new TCPProxy.
 | 
			
		||||
func NewTCPProxy(frontendAddr, backendAddr *net.TCPAddr) (*TCPProxy, error) {
 | 
			
		||||
	listener, err := net.ListenTCP("tcp", frontendAddr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +56,7 @@ func (proxy *TCPProxy) clientLoop(client *net.TCPConn, quit chan bool) {
 | 
			
		|||
	go broker(client, backend)
 | 
			
		||||
	go broker(backend, client)
 | 
			
		||||
 | 
			
		||||
	var transferred int64 = 0
 | 
			
		||||
	var transferred int64
 | 
			
		||||
	for i := 0; i < 2; i++ {
 | 
			
		||||
		select {
 | 
			
		||||
		case written := <-event:
 | 
			
		||||
| 
						 | 
				
			
			@ -72,6 +75,7 @@ func (proxy *TCPProxy) clientLoop(client *net.TCPConn, quit chan bool) {
 | 
			
		|||
	backend.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Run starts forwarding the traffic using TCP.
 | 
			
		||||
func (proxy *TCPProxy) Run() {
 | 
			
		||||
	quit := make(chan bool)
 | 
			
		||||
	defer close(quit)
 | 
			
		||||
| 
						 | 
				
			
			@ -85,6 +89,11 @@ func (proxy *TCPProxy) Run() {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (proxy *TCPProxy) Close()                 { proxy.listener.Close() }
 | 
			
		||||
// Close stops forwarding the traffic.
 | 
			
		||||
func (proxy *TCPProxy) Close() { proxy.listener.Close() }
 | 
			
		||||
 | 
			
		||||
// FrontendAddr returns the TCP address on which the proxy is listening.
 | 
			
		||||
func (proxy *TCPProxy) FrontendAddr() net.Addr { return proxy.frontendAddr }
 | 
			
		||||
func (proxy *TCPProxy) BackendAddr() net.Addr  { return proxy.backendAddr }
 | 
			
		||||
 | 
			
		||||
// BackendAddr returns the TCP proxied address.
 | 
			
		||||
func (proxy *TCPProxy) BackendAddr() net.Addr { return proxy.backendAddr }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,8 +12,10 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// UDPConnTrackTimeout is the timeout used for UDP connection tracking
 | 
			
		||||
	UDPConnTrackTimeout = 90 * time.Second
 | 
			
		||||
	UDPBufSize          = 65507
 | 
			
		||||
	// UDPBufSize is the buffer size for the UDP proxy
 | 
			
		||||
	UDPBufSize = 65507
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// A net.Addr where the IP is split into two fields so you can use it as a key
 | 
			
		||||
| 
						 | 
				
			
			@ -41,6 +43,9 @@ func newConnTrackKey(addr *net.UDPAddr) *connTrackKey {
 | 
			
		|||
 | 
			
		||||
type connTrackMap map[connTrackKey]*net.UDPConn
 | 
			
		||||
 | 
			
		||||
// UDPProxy is proxy for which handles UDP datagrams. It implements the Proxy
 | 
			
		||||
// interface to handle UDP traffic forwarding between the frontend and backend
 | 
			
		||||
// addresses.
 | 
			
		||||
type UDPProxy struct {
 | 
			
		||||
	listener       *net.UDPConn
 | 
			
		||||
	frontendAddr   *net.UDPAddr
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +54,7 @@ type UDPProxy struct {
 | 
			
		|||
	connTrackLock  sync.Mutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewUDPProxy creates a new UDPProxy.
 | 
			
		||||
func NewUDPProxy(frontendAddr, backendAddr *net.UDPAddr) (*UDPProxy, error) {
 | 
			
		||||
	listener, err := net.ListenUDP("udp", frontendAddr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -96,6 +102,7 @@ func (proxy *UDPProxy) replyLoop(proxyConn *net.UDPConn, clientAddr *net.UDPAddr
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Run starts forwarding the traffic using UDP.
 | 
			
		||||
func (proxy *UDPProxy) Run() {
 | 
			
		||||
	readBuf := make([]byte, UDPBufSize)
 | 
			
		||||
	for {
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +142,7 @@ func (proxy *UDPProxy) Run() {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close stops forwarding the traffic.
 | 
			
		||||
func (proxy *UDPProxy) Close() {
 | 
			
		||||
	proxy.listener.Close()
 | 
			
		||||
	proxy.connTrackLock.Lock()
 | 
			
		||||
| 
						 | 
				
			
			@ -144,8 +152,11 @@ func (proxy *UDPProxy) Close() {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FrontendAddr returns the UDP address on which the proxy is listening.
 | 
			
		||||
func (proxy *UDPProxy) FrontendAddr() net.Addr { return proxy.frontendAddr }
 | 
			
		||||
func (proxy *UDPProxy) BackendAddr() net.Addr  { return proxy.backendAddr }
 | 
			
		||||
 | 
			
		||||
// BackendAddr returns the proxied UDP address.
 | 
			
		||||
func (proxy *UDPProxy) BackendAddr() net.Addr { return proxy.backendAddr }
 | 
			
		||||
 | 
			
		||||
func isClosedError(err error) bool {
 | 
			
		||||
	/* This comparison is ugly, but unfortunately, net.go doesn't export errClosing.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// Package signal provides helper functions for dealing with signals across
 | 
			
		||||
// various operating systems.
 | 
			
		||||
package signal
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -5,6 +7,7 @@ import (
 | 
			
		|||
	"os/signal"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CatchAll catches all signals and relays them to the specified channel.
 | 
			
		||||
func CatchAll(sigc chan os.Signal) {
 | 
			
		||||
	handledSigs := []os.Signal{}
 | 
			
		||||
	for _, s := range SignalMap {
 | 
			
		||||
| 
						 | 
				
			
			@ -13,6 +16,7 @@ func CatchAll(sigc chan os.Signal) {
 | 
			
		|||
	signal.Notify(sigc, handledSigs...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StopCatch stops catching the signals and closes the specified channel.
 | 
			
		||||
func StopCatch(sigc chan os.Signal) {
 | 
			
		||||
	signal.Stop(sigc)
 | 
			
		||||
	close(sigc)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@ import (
 | 
			
		|||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SignalMap is a map of Darwin signals.
 | 
			
		||||
var SignalMap = map[string]syscall.Signal{
 | 
			
		||||
	"ABRT":   syscall.SIGABRT,
 | 
			
		||||
	"ALRM":   syscall.SIGALRM,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@ import (
 | 
			
		|||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SignalMap is a map of FreeBSD signals.
 | 
			
		||||
var SignalMap = map[string]syscall.Signal{
 | 
			
		||||
	"ABRT":   syscall.SIGABRT,
 | 
			
		||||
	"ALRM":   syscall.SIGALRM,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@ import (
 | 
			
		|||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SignalMap is a map of Linux signals.
 | 
			
		||||
var SignalMap = map[string]syscall.Signal{
 | 
			
		||||
	"ABRT":   syscall.SIGABRT,
 | 
			
		||||
	"ALRM":   syscall.SIGALRM,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,5 +8,9 @@ import (
 | 
			
		|||
 | 
			
		||||
// Signals used in api/client (no windows equivalent, use
 | 
			
		||||
// invalid signals so they don't get handled)
 | 
			
		||||
 | 
			
		||||
// SIGCHLD is a signal sent to a process when a child process terminates, is interrupted, or resumes after being interrupted.
 | 
			
		||||
const SIGCHLD = syscall.SIGCHLD
 | 
			
		||||
 | 
			
		||||
// SIGWINCH is a signal sent to a process when its controlling terminal changes its size
 | 
			
		||||
const SIGWINCH = syscall.SIGWINCH
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,4 +6,5 @@ import (
 | 
			
		|||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SignalMap is an empty map of signals for unsupported platform.
 | 
			
		||||
var SignalMap = map[string]syscall.Signal{}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,5 +8,7 @@ import (
 | 
			
		|||
 | 
			
		||||
// Signals used in api/client (no windows equivalent, use
 | 
			
		||||
// invalid signals so they don't get handled)
 | 
			
		||||
const SIGCHLD = syscall.Signal(0xff)
 | 
			
		||||
const SIGWINCH = syscall.Signal(0xff)
 | 
			
		||||
const (
 | 
			
		||||
	SIGCHLD  = syscall.Signal(0xff)
 | 
			
		||||
	SIGWINCH = syscall.Signal(0xff)
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,6 +55,7 @@ func Trap(cleanup func()) {
 | 
			
		|||
	}()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DumpStacks dumps the runtime stack.
 | 
			
		||||
func DumpStacks() {
 | 
			
		||||
	buf := make([]byte, 16384)
 | 
			
		||||
	buf = buf[:runtime.Stack(buf, true)]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// Package sockets provides helper functions to create and configure Unix or TCP
 | 
			
		||||
// sockets.
 | 
			
		||||
package sockets
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +11,12 @@ import (
 | 
			
		|||
	"github.com/docker/docker/pkg/listenbuffer"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func NewTcpSocket(addr string, tlsConfig *tls.Config, activate <-chan struct{}) (net.Listener, error) {
 | 
			
		||||
// NewTCPSocket creates a TCP socket listener with the specified address and
 | 
			
		||||
// and the specified tls configuration. If TLSConfig is set, will encapsulate the
 | 
			
		||||
// TCP listener inside a TLS one.
 | 
			
		||||
// The channel passed is used to activate the listenbuffer when the caller is ready
 | 
			
		||||
// to accept connections.
 | 
			
		||||
func NewTCPSocket(addr string, tlsConfig *tls.Config, activate <-chan struct{}) (net.Listener, error) {
 | 
			
		||||
	l, err := listenbuffer.NewListenBuffer("tcp", addr, activate)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
| 
						 | 
				
			
			@ -21,6 +28,10 @@ func NewTcpSocket(addr string, tlsConfig *tls.Config, activate <-chan struct{})
 | 
			
		|||
	return l, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ConfigureTCPTransport configures the specified Transport according to the
 | 
			
		||||
// specified proto and addr.
 | 
			
		||||
// If the proto is unix (using a unix socket to communicate) the compression
 | 
			
		||||
// is disabled.
 | 
			
		||||
func ConfigureTCPTransport(tr *http.Transport, proto, addr string) {
 | 
			
		||||
	// Why 32? See https://github.com/docker/docker/pull/8035.
 | 
			
		||||
	timeout := 32 * time.Second
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,9 @@ import (
 | 
			
		|||
	"github.com/opencontainers/runc/libcontainer/user"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewUnixSocket creates a unix socket with the specified path and group.
 | 
			
		||||
// The channel passed is used to activate the listenbuffer when the caller is ready
 | 
			
		||||
// to accept connections.
 | 
			
		||||
func NewUnixSocket(path, group string, activate <-chan struct{}) (net.Listener, error) {
 | 
			
		||||
	if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) {
 | 
			
		||||
		return nil, err
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
// Package streamformatter provides helper functions to format a stream.
 | 
			
		||||
package streamformatter
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +9,7 @@ import (
 | 
			
		|||
	"github.com/docker/docker/pkg/jsonmessage"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// StreamFormatter formats a stream, optionally using JSON.
 | 
			
		||||
type StreamFormatter struct {
 | 
			
		||||
	json bool
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +28,7 @@ const streamNewline = "\r\n"
 | 
			
		|||
 | 
			
		||||
var streamNewlineBytes = []byte(streamNewline)
 | 
			
		||||
 | 
			
		||||
// FormatStream formats the specified stream.
 | 
			
		||||
func (sf *StreamFormatter) FormatStream(str string) []byte {
 | 
			
		||||
	if sf.json {
 | 
			
		||||
		b, err := json.Marshal(&jsonmessage.JSONMessage{Stream: str})
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +40,7 @@ func (sf *StreamFormatter) FormatStream(str string) []byte {
 | 
			
		|||
	return []byte(str + "\r")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FormatStatus formats the specified objects according to the specified format (and id).
 | 
			
		||||
func (sf *StreamFormatter) FormatStatus(id, format string, a ...interface{}) []byte {
 | 
			
		||||
	str := fmt.Sprintf(format, a...)
 | 
			
		||||
	if sf.json {
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +53,7 @@ func (sf *StreamFormatter) FormatStatus(id, format string, a ...interface{}) []b
 | 
			
		|||
	return []byte(str + streamNewline)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FormatError formats the specifed error.
 | 
			
		||||
func (sf *StreamFormatter) FormatError(err error) []byte {
 | 
			
		||||
	if sf.json {
 | 
			
		||||
		jsonError, ok := err.(*jsonmessage.JSONError)
 | 
			
		||||
| 
						 | 
				
			
			@ -63,6 +68,7 @@ func (sf *StreamFormatter) FormatError(err error) []byte {
 | 
			
		|||
	return []byte("Error: " + err.Error() + streamNewline)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FormatProgress formats the progress information for a specified action.
 | 
			
		||||
func (sf *StreamFormatter) FormatProgress(id, action string, progress *jsonmessage.JSONProgress) []byte {
 | 
			
		||||
	if progress == nil {
 | 
			
		||||
		progress = &jsonmessage.JSONProgress{}
 | 
			
		||||
| 
						 | 
				
			
			@ -86,12 +92,13 @@ func (sf *StreamFormatter) FormatProgress(id, action string, progress *jsonmessa
 | 
			
		|||
	return []byte(action + " " + progress.String() + endl)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type StdoutFormater struct {
 | 
			
		||||
// StdoutFormatter is a streamFormatter that writes to the standard output.
 | 
			
		||||
type StdoutFormatter struct {
 | 
			
		||||
	io.Writer
 | 
			
		||||
	*StreamFormatter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (sf *StdoutFormater) Write(buf []byte) (int, error) {
 | 
			
		||||
func (sf *StdoutFormatter) Write(buf []byte) (int, error) {
 | 
			
		||||
	formattedBuf := sf.StreamFormatter.FormatStream(string(buf))
 | 
			
		||||
	n, err := sf.Writer.Write(formattedBuf)
 | 
			
		||||
	if n != len(formattedBuf) {
 | 
			
		||||
| 
						 | 
				
			
			@ -100,12 +107,13 @@ func (sf *StdoutFormater) Write(buf []byte) (int, error) {
 | 
			
		|||
	return len(buf), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type StderrFormater struct {
 | 
			
		||||
// StderrFormatter is a streamFormatter that writes to the standard error.
 | 
			
		||||
type StderrFormatter struct {
 | 
			
		||||
	io.Writer
 | 
			
		||||
	*StreamFormatter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (sf *StderrFormater) Write(buf []byte) (int, error) {
 | 
			
		||||
func (sf *StderrFormatter) Write(buf []byte) (int, error) {
 | 
			
		||||
	formattedBuf := sf.StreamFormatter.FormatStream("\033[91m" + string(buf) + "\033[0m")
 | 
			
		||||
	n, err := sf.Writer.Write(formattedBuf)
 | 
			
		||||
	if n != len(formattedBuf) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
// Package stringid provides helper functions for dealing with string identifiers
 | 
			
		||||
package stringid
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +13,7 @@ const shortLen = 12
 | 
			
		|||
 | 
			
		||||
var validShortID = regexp.MustCompile("^[a-z0-9]{12}$")
 | 
			
		||||
 | 
			
		||||
// Determine if an arbitrary string *looks like* a short ID.
 | 
			
		||||
// IsShortID determines if an arbitrary string *looks like* a short ID.
 | 
			
		||||
func IsShortID(id string) bool {
 | 
			
		||||
	return validShortID.MatchString(id)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -29,7 +30,7 @@ func TruncateID(id string) string {
 | 
			
		|||
	return id[:trimTo]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GenerateRandomID returns an unique id
 | 
			
		||||
// GenerateRandomID returns an unique id.
 | 
			
		||||
func GenerateRandomID() string {
 | 
			
		||||
	for {
 | 
			
		||||
		id := make([]byte, 32)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
// Package stringutils provides helper functions for dealing with strings.
 | 
			
		||||
package stringutils
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -8,7 +9,7 @@ import (
 | 
			
		|||
	"github.com/docker/docker/pkg/random"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Generate alpha only random stirng with length n
 | 
			
		||||
// GenerateRandomAlphaOnlyString generates an alphabetical random string with length n.
 | 
			
		||||
func GenerateRandomAlphaOnlyString(n int) string {
 | 
			
		||||
	// make a really long string
 | 
			
		||||
	letters := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
 | 
			
		||||
| 
						 | 
				
			
			@ -20,8 +21,8 @@ func GenerateRandomAlphaOnlyString(n int) string {
 | 
			
		|||
	return string(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Generate Ascii random stirng with length n
 | 
			
		||||
func GenerateRandomAsciiString(n int) string {
 | 
			
		||||
// GenerateRandomASCIIString generates an ASCII random stirng with length n.
 | 
			
		||||
func GenerateRandomASCIIString(n int) string {
 | 
			
		||||
	chars := "abcdefghijklmnopqrstuvwxyz" +
 | 
			
		||||
		"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
 | 
			
		||||
		"~!@#$%^&*()-_+={}[]\\|<,>.?/\"';:` "
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +33,7 @@ func GenerateRandomAsciiString(n int) string {
 | 
			
		|||
	return string(res)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Truncate a string to maxlen
 | 
			
		||||
// Truncate truncates a string to maxlen.
 | 
			
		||||
func Truncate(s string, maxlen int) string {
 | 
			
		||||
	if len(s) <= maxlen {
 | 
			
		||||
		return s
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +41,7 @@ func Truncate(s string, maxlen int) string {
 | 
			
		|||
	return s[:maxlen]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test wheather a string is contained in a slice of strings or not.
 | 
			
		||||
// InSlice tests whether a string is contained in a slice of strings or not.
 | 
			
		||||
// Comparison is case insensitive
 | 
			
		||||
func InSlice(slice []string, s string) bool {
 | 
			
		||||
	for _, ss := range slice {
 | 
			
		||||
| 
						 | 
				
			
			@ -73,8 +74,8 @@ func quote(word string, buf *bytes.Buffer) {
 | 
			
		|||
	buf.WriteString("'")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Take a list of strings and escape them so they will be handled right
 | 
			
		||||
// when passed as arguments to an program via a shell
 | 
			
		||||
// ShellQuoteArguments takes a list of strings and escapes them so they will be
 | 
			
		||||
// handled right when passed as arguments to an program via a shell
 | 
			
		||||
func ShellQuoteArguments(args []string) string {
 | 
			
		||||
	var buf bytes.Buffer
 | 
			
		||||
	for i, arg := range args {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,15 +43,15 @@ func TestGenerateRandomAlphaOnlyStringUniqueness(t *testing.T) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func TestGenerateRandomAsciiStringLength(t *testing.T) {
 | 
			
		||||
	testLengthHelper(GenerateRandomAsciiString, t)
 | 
			
		||||
	testLengthHelper(GenerateRandomASCIIString, t)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGenerateRandomAsciiStringUniqueness(t *testing.T) {
 | 
			
		||||
	testUniquenessHelper(GenerateRandomAsciiString, t)
 | 
			
		||||
	testUniquenessHelper(GenerateRandomASCIIString, t)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGenerateRandomAsciiStringIsAscii(t *testing.T) {
 | 
			
		||||
	str := GenerateRandomAsciiString(64)
 | 
			
		||||
	str := GenerateRandomASCIIString(64)
 | 
			
		||||
	if !isASCII(str) {
 | 
			
		||||
		t.Fatalf("%s contained non-ascii characters", str)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,9 +6,10 @@ import (
 | 
			
		|||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var SdNotifyNoSocket = errors.New("No socket")
 | 
			
		||||
// ErrSdNotifyNoSocket is an error returned if no socket was specified.
 | 
			
		||||
var ErrSdNotifyNoSocket = errors.New("No socket")
 | 
			
		||||
 | 
			
		||||
// Send a message to the init daemon. It is common to ignore the error.
 | 
			
		||||
// SdNotify sends a message to the init daemon. It is common to ignore the return value.
 | 
			
		||||
func SdNotify(state string) error {
 | 
			
		||||
	socketAddr := &net.UnixAddr{
 | 
			
		||||
		Name: os.Getenv("NOTIFY_SOCKET"),
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +17,7 @@ func SdNotify(state string) error {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	if socketAddr.Name == "" {
 | 
			
		||||
		return SdNotifyNoSocket
 | 
			
		||||
		return ErrSdNotifyNoSocket
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	conn, err := net.DialUnix(socketAddr.Net, nil, socketAddr)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// Package tailfile provides helper functinos to read the nth lines of any
 | 
			
		||||
// ReadSeeker.
 | 
			
		||||
package tailfile
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -10,9 +12,11 @@ import (
 | 
			
		|||
const blockSize = 1024
 | 
			
		||||
 | 
			
		||||
var eol = []byte("\n")
 | 
			
		||||
var ErrNonPositiveLinesNumber = errors.New("Lines number must be positive")
 | 
			
		||||
 | 
			
		||||
//TailFile returns last n lines of file f
 | 
			
		||||
// ErrNonPositiveLinesNumber is an error returned if the lines number was negative.
 | 
			
		||||
var ErrNonPositiveLinesNumber = errors.New("The number of lines to extract from the file must be positive")
 | 
			
		||||
 | 
			
		||||
//TailFile returns last n lines of reader f (could be a fil).
 | 
			
		||||
func TailFile(f io.ReadSeeker, n int) ([][]byte, error) {
 | 
			
		||||
	if n <= 0 {
 | 
			
		||||
		return nil, ErrNonPositiveLinesNumber
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,10 @@
 | 
			
		|||
package tarsum
 | 
			
		||||
 | 
			
		||||
// This interface extends TarSum by adding the Remove method.  In general
 | 
			
		||||
// there was concern about adding this method to TarSum itself so instead
 | 
			
		||||
// it is being added just to "BuilderContext" which will then only be used
 | 
			
		||||
// during the .dockerignore file processing - see builder/evaluator.go
 | 
			
		||||
// BuilderContext is an interface extending TarSum by adding the Remove method.
 | 
			
		||||
// In general there was concern about adding this method to TarSum itself
 | 
			
		||||
// so instead it is being added just to "BuilderContext" which will then
 | 
			
		||||
// only be used during the .dockerignore file processing
 | 
			
		||||
// - see builder/evaluator.go
 | 
			
		||||
type BuilderContext interface {
 | 
			
		||||
	TarSum
 | 
			
		||||
	Remove(string)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,9 @@ package tarsum
 | 
			
		|||
 | 
			
		||||
import "sort"
 | 
			
		||||
 | 
			
		||||
// This info will be accessed through interface so the actual name and sum cannot be medled with
 | 
			
		||||
// FileInfoSumInterface provides an interface for accessing file checksum
 | 
			
		||||
// information within a tar file. This info is accessed through interface
 | 
			
		||||
// so the actual name and sum cannot be medled with.
 | 
			
		||||
type FileInfoSumInterface interface {
 | 
			
		||||
	// File name
 | 
			
		||||
	Name() string
 | 
			
		||||
| 
						 | 
				
			
			@ -28,9 +30,10 @@ func (fis fileInfoSum) Pos() int64 {
 | 
			
		|||
	return fis.pos
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FileInfoSums provides a list of FileInfoSumInterfaces.
 | 
			
		||||
type FileInfoSums []FileInfoSumInterface
 | 
			
		||||
 | 
			
		||||
// GetFile returns the first FileInfoSumInterface with a matching name
 | 
			
		||||
// GetFile returns the first FileInfoSumInterface with a matching name.
 | 
			
		||||
func (fis FileInfoSums) GetFile(name string) FileInfoSumInterface {
 | 
			
		||||
	for i := range fis {
 | 
			
		||||
		if fis[i].Name() == name {
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +43,7 @@ func (fis FileInfoSums) GetFile(name string) FileInfoSumInterface {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAllFile returns a FileInfoSums with all matching names
 | 
			
		||||
// GetAllFile returns a FileInfoSums with all matching names.
 | 
			
		||||
func (fis FileInfoSums) GetAllFile(name string) FileInfoSums {
 | 
			
		||||
	f := FileInfoSums{}
 | 
			
		||||
	for i := range fis {
 | 
			
		||||
| 
						 | 
				
			
			@ -51,6 +54,7 @@ func (fis FileInfoSums) GetAllFile(name string) FileInfoSums {
 | 
			
		|||
	return f
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetDuplicatePaths returns a FileInfoSums with all duplicated paths.
 | 
			
		||||
func (fis FileInfoSums) GetDuplicatePaths() (dups FileInfoSums) {
 | 
			
		||||
	seen := make(map[string]int, len(fis)) // allocate earl. no need to grow this map.
 | 
			
		||||
	for i := range fis {
 | 
			
		||||
| 
						 | 
				
			
			@ -64,17 +68,23 @@ func (fis FileInfoSums) GetDuplicatePaths() (dups FileInfoSums) {
 | 
			
		|||
	return dups
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fis FileInfoSums) Len() int      { return len(fis) }
 | 
			
		||||
// Len returns the size of the FileInfoSums.
 | 
			
		||||
func (fis FileInfoSums) Len() int { return len(fis) }
 | 
			
		||||
 | 
			
		||||
// Swap swaps two FileInfoSum values if a FileInfoSums list.
 | 
			
		||||
func (fis FileInfoSums) Swap(i, j int) { fis[i], fis[j] = fis[j], fis[i] }
 | 
			
		||||
 | 
			
		||||
// SortByPos sorts FileInfoSums content by position.
 | 
			
		||||
func (fis FileInfoSums) SortByPos() {
 | 
			
		||||
	sort.Sort(byPos{fis})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SortByNames sorts FileInfoSums content by name.
 | 
			
		||||
func (fis FileInfoSums) SortByNames() {
 | 
			
		||||
	sort.Sort(byName{fis})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SortBySums sorts FileInfoSums content by sums.
 | 
			
		||||
func (fis FileInfoSums) SortBySums() {
 | 
			
		||||
	dups := fis.GetDuplicatePaths()
 | 
			
		||||
	if len(dups) > 0 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,20 @@
 | 
			
		|||
// Package tarsum provides algorithms to perform checksum calculation on
 | 
			
		||||
// filesystem layers.
 | 
			
		||||
//
 | 
			
		||||
// The transportation of filesystems, regarding Docker, is done with tar(1)
 | 
			
		||||
// archives. There are a variety of tar serialization formats [2], and a key
 | 
			
		||||
// concern here is ensuring a repeatable checksum given a set of inputs from a
 | 
			
		||||
// generic tar archive. Types of transportation include distribution to and from a
 | 
			
		||||
// registry endpoint, saving and loading through commands or Docker daemon APIs,
 | 
			
		||||
// transferring the build context from client to Docker daemon, and committing the
 | 
			
		||||
// filesystem of a container to become an image.
 | 
			
		||||
//
 | 
			
		||||
// As tar archives are used for transit, but not preserved in many situations, the
 | 
			
		||||
// focus of the algorithm is to ensure the integrity of the preserved filesystem,
 | 
			
		||||
// while maintaining a deterministic accountability. This includes neither
 | 
			
		||||
// constraining the ordering or manipulation of the files during the creation or
 | 
			
		||||
// unpacking of the archive, nor include additional metadata state about the file
 | 
			
		||||
// system attributes.
 | 
			
		||||
package tarsum
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +47,8 @@ func NewTarSum(r io.Reader, dc bool, v Version) (TarSum, error) {
 | 
			
		|||
	return NewTarSumHash(r, dc, v, DefaultTHash)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create a new TarSum, providing a THash to use rather than the DefaultTHash
 | 
			
		||||
// NewTarSumHash creates a new TarSum, providing a THash to use rather than
 | 
			
		||||
// the DefaultTHash.
 | 
			
		||||
func NewTarSumHash(r io.Reader, dc bool, v Version, tHash THash) (TarSum, error) {
 | 
			
		||||
	headerSelector, err := getTarHeaderSelector(v)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +59,7 @@ func NewTarSumHash(r io.Reader, dc bool, v Version, tHash THash) (TarSum, error)
 | 
			
		|||
	return ts, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create a new TarSum using the provided TarSum version+hash label.
 | 
			
		||||
// NewTarSumForLabel creates a new TarSum using the provided TarSum version+hash label.
 | 
			
		||||
func NewTarSumForLabel(r io.Reader, disableCompression bool, label string) (TarSum, error) {
 | 
			
		||||
	parts := strings.SplitN(label, "+", 2)
 | 
			
		||||
	if len(parts) != 2 {
 | 
			
		||||
| 
						 | 
				
			
			@ -66,7 +84,7 @@ func NewTarSumForLabel(r io.Reader, disableCompression bool, label string) (TarS
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// TarSum is the generic interface for calculating fixed time
 | 
			
		||||
// checksums of a tar archive
 | 
			
		||||
// checksums of a tar archive.
 | 
			
		||||
type TarSum interface {
 | 
			
		||||
	io.Reader
 | 
			
		||||
	GetSums() FileInfoSums
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +93,7 @@ type TarSum interface {
 | 
			
		|||
	Hash() THash
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// tarSum struct is the structure for a Version0 checksum calculation
 | 
			
		||||
// tarSum struct is the structure for a Version0 checksum calculation.
 | 
			
		||||
type tarSum struct {
 | 
			
		||||
	io.Reader
 | 
			
		||||
	tarR               *tar.Reader
 | 
			
		||||
| 
						 | 
				
			
			@ -104,13 +122,13 @@ func (ts tarSum) Version() Version {
 | 
			
		|||
	return ts.tarSumVersion
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A hash.Hash type generator and its name
 | 
			
		||||
// THash provides a hash.Hash type generator and its name.
 | 
			
		||||
type THash interface {
 | 
			
		||||
	Hash() hash.Hash
 | 
			
		||||
	Name() string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convenience method for creating a THash
 | 
			
		||||
// NewTHash is a convenience method for creating a THash.
 | 
			
		||||
func NewTHash(name string, h func() hash.Hash) THash {
 | 
			
		||||
	return simpleTHash{n: name, h: h}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// versioning of the TarSum algorithm
 | 
			
		||||
// Version is used for versioning of the TarSum algorithm
 | 
			
		||||
// based on the prefix of the hash used
 | 
			
		||||
// i.e. "tarsum+sha256:e58fcf7418d4390dec8e8fb69d88c06ec07039d651fedd3aa72af9972e7d046b"
 | 
			
		||||
type Version int
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ type Version int
 | 
			
		|||
const (
 | 
			
		||||
	Version0 Version = iota
 | 
			
		||||
	Version1
 | 
			
		||||
	// NOTE: this variable will be either the latest or an unsettled next-version of the TarSum calculation
 | 
			
		||||
	// VersionDev this constant will be either the latest or an unsettled next-version of the TarSum calculation
 | 
			
		||||
	VersionDev
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +33,7 @@ func VersionLabelForChecksum(checksum string) string {
 | 
			
		|||
	return checksum[:sepIndex]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get a list of all known tarsum Version
 | 
			
		||||
// GetVersions gets a list of all known tarsum versions.
 | 
			
		||||
func GetVersions() []Version {
 | 
			
		||||
	v := []Version{}
 | 
			
		||||
	for k := range tarSumVersions {
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +59,7 @@ func (tsv Version) String() string {
 | 
			
		|||
	return tarSumVersions[tsv]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetVersionFromTarsum returns the Version from the provided string
 | 
			
		||||
// GetVersionFromTarsum returns the Version from the provided string.
 | 
			
		||||
func GetVersionFromTarsum(tarsum string) (Version, error) {
 | 
			
		||||
	tsv := tarsum
 | 
			
		||||
	if strings.Contains(tarsum, "+") {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,9 @@ import (
 | 
			
		|||
// #include <termios.h>
 | 
			
		||||
import "C"
 | 
			
		||||
 | 
			
		||||
// Termios is the Unix API for terminal I/O.
 | 
			
		||||
// It is passthgrouh for syscall.Termios in order to make it portable with
 | 
			
		||||
// other platforms where it is not available or handled differently.
 | 
			
		||||
type Termios syscall.Termios
 | 
			
		||||
 | 
			
		||||
// MakeRaw put the terminal connected to the given file descriptor into raw
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
// +build !windows
 | 
			
		||||
 | 
			
		||||
// Package term provides provides structures and helper functions to work with
 | 
			
		||||
// terminal (state, sizes).
 | 
			
		||||
package term
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -12,13 +14,16 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// ErrInvalidState is returned if the state of the terminal is invalid.
 | 
			
		||||
	ErrInvalidState = errors.New("Invalid terminal state")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// State represents the state of the terminal.
 | 
			
		||||
type State struct {
 | 
			
		||||
	termios Termios
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Winsize represents the size of the terminal window.
 | 
			
		||||
type Winsize struct {
 | 
			
		||||
	Height uint16
 | 
			
		||||
	Width  uint16
 | 
			
		||||
| 
						 | 
				
			
			@ -26,10 +31,12 @@ type Winsize struct {
 | 
			
		|||
	y      uint16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StdStreams returns the standard streams (stdin, stdout, stedrr).
 | 
			
		||||
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
 | 
			
		||||
	return os.Stdin, os.Stdout, os.Stderr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal.
 | 
			
		||||
func GetFdInfo(in interface{}) (uintptr, bool) {
 | 
			
		||||
	var inFd uintptr
 | 
			
		||||
	var isTerminalIn bool
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +47,7 @@ func GetFdInfo(in interface{}) (uintptr, bool) {
 | 
			
		|||
	return inFd, isTerminalIn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetWinsize returns the window size based on the specified file descriptor.
 | 
			
		||||
func GetWinsize(fd uintptr) (*Winsize, error) {
 | 
			
		||||
	ws := &Winsize{}
 | 
			
		||||
	_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(ws)))
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +58,7 @@ func GetWinsize(fd uintptr) (*Winsize, error) {
 | 
			
		|||
	return ws, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetWinsize tries to set the specified window size for the specified file descriptor.
 | 
			
		||||
func SetWinsize(fd uintptr, ws *Winsize) error {
 | 
			
		||||
	_, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws)))
 | 
			
		||||
	// Skipp errno = 0
 | 
			
		||||
| 
						 | 
				
			
			@ -65,8 +74,8 @@ func IsTerminal(fd uintptr) bool {
 | 
			
		|||
	return tcget(fd, &termios) == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Restore restores the terminal connected to the given file descriptor to a
 | 
			
		||||
// previous state.
 | 
			
		||||
// RestoreTerminal restores the terminal connected to the given file descriptor
 | 
			
		||||
// to a previous state.
 | 
			
		||||
func RestoreTerminal(fd uintptr, state *State) error {
 | 
			
		||||
	if state == nil {
 | 
			
		||||
		return ErrInvalidState
 | 
			
		||||
| 
						 | 
				
			
			@ -77,6 +86,7 @@ func RestoreTerminal(fd uintptr, state *State) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SaveState saves the state of the terminal connected to the given file descriptor.
 | 
			
		||||
func SaveState(fd uintptr) (*State, error) {
 | 
			
		||||
	var oldState State
 | 
			
		||||
	if err := tcget(fd, &oldState.termios); err != 0 {
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +96,8 @@ func SaveState(fd uintptr) (*State, error) {
 | 
			
		|||
	return &oldState, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DisableEcho applies the specified state to the terminal connected to the file
 | 
			
		||||
// descriptor, with echo disabled.
 | 
			
		||||
func DisableEcho(fd uintptr, state *State) error {
 | 
			
		||||
	newState := state.termios
 | 
			
		||||
	newState.Lflag &^= syscall.ECHO
 | 
			
		||||
| 
						 | 
				
			
			@ -97,6 +109,8 @@ func DisableEcho(fd uintptr, state *State) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetRawTerminal puts the terminal connected to the given file descriptor into
 | 
			
		||||
// raw mode and returns the previous state.
 | 
			
		||||
func SetRawTerminal(fd uintptr) (*State, error) {
 | 
			
		||||
	oldState, err := MakeRaw(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ type Winsize struct {
 | 
			
		|||
	y      uint16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StdStreams returns the standard streams (stdin, stdout, stedrr).
 | 
			
		||||
func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
 | 
			
		||||
	switch {
 | 
			
		||||
	case os.Getenv("ConEmuANSI") == "ON":
 | 
			
		||||
| 
						 | 
				
			
			@ -36,12 +37,12 @@ func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetFdInfo returns file descriptor and bool indicating whether the file is a terminal.
 | 
			
		||||
// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal.
 | 
			
		||||
func GetFdInfo(in interface{}) (uintptr, bool) {
 | 
			
		||||
	return winconsole.GetHandleInfo(in)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetWinsize retrieves the window size of the terminal connected to the passed file descriptor.
 | 
			
		||||
// GetWinsize returns the window size based on the specified file descriptor.
 | 
			
		||||
func GetWinsize(fd uintptr) (*Winsize, error) {
 | 
			
		||||
	info, err := winconsole.GetConsoleScreenBufferInfo(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +57,7 @@ func GetWinsize(fd uintptr) (*Winsize, error) {
 | 
			
		|||
		y:      0}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetWinsize sets the size of the given terminal connected to the passed file descriptor.
 | 
			
		||||
// SetWinsize tries to set the specified window size for the specified file descriptor.
 | 
			
		||||
func SetWinsize(fd uintptr, ws *Winsize) error {
 | 
			
		||||
	// TODO(azlinux): Implement SetWinsize
 | 
			
		||||
	logrus.Debugf("[windows] SetWinsize: WARNING -- Unsupported method invoked")
 | 
			
		||||
| 
						 | 
				
			
			@ -68,8 +69,8 @@ func IsTerminal(fd uintptr) bool {
 | 
			
		|||
	return winconsole.IsConsole(fd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RestoreTerminal restores the terminal connected to the given file descriptor to a
 | 
			
		||||
// previous state.
 | 
			
		||||
// RestoreTerminal restores the terminal connected to the given file descriptor
 | 
			
		||||
// to a previous state.
 | 
			
		||||
func RestoreTerminal(fd uintptr, state *State) error {
 | 
			
		||||
	return winconsole.SetConsoleMode(fd, state.mode)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -94,8 +95,7 @@ func DisableEcho(fd uintptr, state *State) error {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// SetRawTerminal puts the terminal connected to the given file descriptor into raw
 | 
			
		||||
// mode and returns the previous state of the terminal so that it can be
 | 
			
		||||
// restored.
 | 
			
		||||
// mode and returns the previous state.
 | 
			
		||||
func SetRawTerminal(fd uintptr) (*State, error) {
 | 
			
		||||
	state, err := MakeRaw(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,10 @@ import (
 | 
			
		|||
const (
 | 
			
		||||
	getTermios = syscall.TIOCGETA
 | 
			
		||||
	setTermios = syscall.TIOCSETA
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Termios magic numbers, passthrough to the ones defined in syscall.
 | 
			
		||||
const (
 | 
			
		||||
	IGNBRK = syscall.IGNBRK
 | 
			
		||||
	PARMRK = syscall.PARMRK
 | 
			
		||||
	INLCR  = syscall.INLCR
 | 
			
		||||
| 
						 | 
				
			
			@ -29,6 +32,7 @@ const (
 | 
			
		|||
	IEXTEN = syscall.IEXTEN
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Termios is the Unix API for terminal I/O.
 | 
			
		||||
type Termios struct {
 | 
			
		||||
	Iflag  uint64
 | 
			
		||||
	Oflag  uint64
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,10 @@ import (
 | 
			
		|||
const (
 | 
			
		||||
	getTermios = syscall.TIOCGETA
 | 
			
		||||
	setTermios = syscall.TIOCSETA
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Termios magic numbers, passthrough to the ones defined in syscall.
 | 
			
		||||
const (
 | 
			
		||||
	IGNBRK = syscall.IGNBRK
 | 
			
		||||
	PARMRK = syscall.PARMRK
 | 
			
		||||
	INLCR  = syscall.INLCR
 | 
			
		||||
| 
						 | 
				
			
			@ -29,6 +32,7 @@ const (
 | 
			
		|||
	IEXTEN = syscall.IEXTEN
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Termios is the Unix API for terminal I/O.
 | 
			
		||||
type Termios struct {
 | 
			
		||||
	Iflag  uint32
 | 
			
		||||
	Oflag  uint32
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ const (
 | 
			
		|||
	setTermios = syscall.TCSETS
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Termios is the Unix API for terminal I/O.
 | 
			
		||||
type Termios struct {
 | 
			
		||||
	Iflag  uint32
 | 
			
		||||
	Oflag  uint32
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
// Package timeoutconn provides overridden net.Conn that supports deadline (timeout).
 | 
			
		||||
package timeoutconn
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -5,11 +6,13 @@ import (
 | 
			
		|||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// New creates a net.Conn with a timeout for every Read operation.
 | 
			
		||||
func New(netConn net.Conn, timeout time.Duration) net.Conn {
 | 
			
		||||
	return &conn{netConn, timeout}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A net.Conn that sets a deadline for every Read or Write operation
 | 
			
		||||
// A net.Conn that sets a deadline for every Read operation.
 | 
			
		||||
// FIXME was documented the deadline was on Write operation too but not implement
 | 
			
		||||
type conn struct {
 | 
			
		||||
	net.Conn
 | 
			
		||||
	timeout time.Duration
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
// Package timeutils provides helper functions to parse and print time (time.Time).
 | 
			
		||||
package timeutils
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,6 @@
 | 
			
		|||
// Package truncindex package provides a general 'index tree', used by Docker
 | 
			
		||||
// in order to be able to reference containers by only a few unambiguous
 | 
			
		||||
// characters of their id.
 | 
			
		||||
package truncindex
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +13,9 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	ErrEmptyPrefix     = errors.New("Prefix can't be empty")
 | 
			
		||||
	// ErrEmptyPrefix is an error returned if the prefix was empty.
 | 
			
		||||
	ErrEmptyPrefix = errors.New("Prefix can't be empty")
 | 
			
		||||
	// ErrAmbiguousPrefix is an error returned if the prefix was ambiguous (multiple ids for the prefix).
 | 
			
		||||
	ErrAmbiguousPrefix = errors.New("Multiple IDs found with provided prefix")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +27,7 @@ type TruncIndex struct {
 | 
			
		|||
	ids  map[string]struct{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewTruncIndex creates a new TruncIndex and initializes with a list of IDs
 | 
			
		||||
// NewTruncIndex creates a new TruncIndex and initializes with a list of IDs.
 | 
			
		||||
func NewTruncIndex(ids []string) (idx *TruncIndex) {
 | 
			
		||||
	idx = &TruncIndex{
 | 
			
		||||
		ids: make(map[string]struct{}),
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +59,7 @@ func (idx *TruncIndex) addID(id string) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Add adds a new ID to the TruncIndex
 | 
			
		||||
// Add adds a new ID to the TruncIndex.
 | 
			
		||||
func (idx *TruncIndex) Add(id string) error {
 | 
			
		||||
	idx.Lock()
 | 
			
		||||
	defer idx.Unlock()
 | 
			
		||||
| 
						 | 
				
			
			@ -109,7 +114,7 @@ func (idx *TruncIndex) Get(s string) (string, error) {
 | 
			
		|||
	return "", fmt.Errorf("no such id: %s", s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Iterates over all stored IDs, and passes each of them to the given handler
 | 
			
		||||
// Iterate iterates over all stored IDs, and passes each of them to the given handler.
 | 
			
		||||
func (idx *TruncIndex) Iterate(handler func(id string)) {
 | 
			
		||||
	idx.RLock()
 | 
			
		||||
	defer idx.RUnlock()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// Package ulimit provides structure and helper function to parse and represent
 | 
			
		||||
// resource limits (Rlimit and Ulimit, its human friendly version).
 | 
			
		||||
package ulimit
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -6,13 +8,14 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Human friendly version of Rlimit
 | 
			
		||||
// Ulimit is a human friendly version of Rlimit.
 | 
			
		||||
type Ulimit struct {
 | 
			
		||||
	Name string
 | 
			
		||||
	Hard int64
 | 
			
		||||
	Soft int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Rlimit specifies the resource limits, such as max open files.
 | 
			
		||||
type Rlimit struct {
 | 
			
		||||
	Type int    `json:"type,omitempty"`
 | 
			
		||||
	Hard uint64 `json:"hard,omitempty"`
 | 
			
		||||
| 
						 | 
				
			
			@ -24,43 +27,44 @@ const (
 | 
			
		|||
	// some of these are defined in the syscall package, but not all.
 | 
			
		||||
	// Also since Windows client doesn't get access to the syscall package, need to
 | 
			
		||||
	//	define these here
 | 
			
		||||
	RLIMIT_AS         = 9
 | 
			
		||||
	RLIMIT_CORE       = 4
 | 
			
		||||
	RLIMIT_CPU        = 0
 | 
			
		||||
	RLIMIT_DATA       = 2
 | 
			
		||||
	RLIMIT_FSIZE      = 1
 | 
			
		||||
	RLIMIT_LOCKS      = 10
 | 
			
		||||
	RLIMIT_MEMLOCK    = 8
 | 
			
		||||
	RLIMIT_MSGQUEUE   = 12
 | 
			
		||||
	RLIMIT_NICE       = 13
 | 
			
		||||
	RLIMIT_NOFILE     = 7
 | 
			
		||||
	RLIMIT_NPROC      = 6
 | 
			
		||||
	RLIMIT_RSS        = 5
 | 
			
		||||
	RLIMIT_RTPRIO     = 14
 | 
			
		||||
	RLIMIT_RTTIME     = 15
 | 
			
		||||
	RLIMIT_SIGPENDING = 11
 | 
			
		||||
	RLIMIT_STACK      = 3
 | 
			
		||||
	rlimitAs         = 9
 | 
			
		||||
	rlimitCore       = 4
 | 
			
		||||
	rlimitCPU        = 0
 | 
			
		||||
	rlimitData       = 2
 | 
			
		||||
	rlimitFsize      = 1
 | 
			
		||||
	rlimitLocks      = 10
 | 
			
		||||
	rlimitMemlock    = 8
 | 
			
		||||
	rlimitMsgqueue   = 12
 | 
			
		||||
	rlimitNice       = 13
 | 
			
		||||
	rlimitNofile     = 7
 | 
			
		||||
	rlimitNproc      = 6
 | 
			
		||||
	rlimitRss        = 5
 | 
			
		||||
	rlimitRtprio     = 14
 | 
			
		||||
	rlimitRttime     = 15
 | 
			
		||||
	rlimitSigpending = 11
 | 
			
		||||
	rlimitStack      = 3
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var ulimitNameMapping = map[string]int{
 | 
			
		||||
	//"as":         RLIMIT_AS, // Disbaled since this doesn't seem usable with the way Docker inits a container.
 | 
			
		||||
	"core":       RLIMIT_CORE,
 | 
			
		||||
	"cpu":        RLIMIT_CPU,
 | 
			
		||||
	"data":       RLIMIT_DATA,
 | 
			
		||||
	"fsize":      RLIMIT_FSIZE,
 | 
			
		||||
	"locks":      RLIMIT_LOCKS,
 | 
			
		||||
	"memlock":    RLIMIT_MEMLOCK,
 | 
			
		||||
	"msgqueue":   RLIMIT_MSGQUEUE,
 | 
			
		||||
	"nice":       RLIMIT_NICE,
 | 
			
		||||
	"nofile":     RLIMIT_NOFILE,
 | 
			
		||||
	"nproc":      RLIMIT_NPROC,
 | 
			
		||||
	"rss":        RLIMIT_RSS,
 | 
			
		||||
	"rtprio":     RLIMIT_RTPRIO,
 | 
			
		||||
	"rttime":     RLIMIT_RTTIME,
 | 
			
		||||
	"sigpending": RLIMIT_SIGPENDING,
 | 
			
		||||
	"stack":      RLIMIT_STACK,
 | 
			
		||||
	//"as":         rlimitAs, // Disabled since this doesn't seem usable with the way Docker inits a container.
 | 
			
		||||
	"core":       rlimitCore,
 | 
			
		||||
	"cpu":        rlimitCPU,
 | 
			
		||||
	"data":       rlimitData,
 | 
			
		||||
	"fsize":      rlimitFsize,
 | 
			
		||||
	"locks":      rlimitLocks,
 | 
			
		||||
	"memlock":    rlimitMemlock,
 | 
			
		||||
	"msgqueue":   rlimitMsgqueue,
 | 
			
		||||
	"nice":       rlimitNice,
 | 
			
		||||
	"nofile":     rlimitNofile,
 | 
			
		||||
	"nproc":      rlimitNproc,
 | 
			
		||||
	"rss":        rlimitRss,
 | 
			
		||||
	"rtprio":     rlimitRtprio,
 | 
			
		||||
	"rttime":     rlimitRttime,
 | 
			
		||||
	"sigpending": rlimitSigpending,
 | 
			
		||||
	"stack":      rlimitStack,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parse parses and returns a Ulimit from the specified string.
 | 
			
		||||
func Parse(val string) (*Ulimit, error) {
 | 
			
		||||
	parts := strings.SplitN(val, "=", 2)
 | 
			
		||||
	if len(parts) != 2 {
 | 
			
		||||
| 
						 | 
				
			
			@ -92,6 +96,7 @@ func Parse(val string) (*Ulimit, error) {
 | 
			
		|||
	return &Ulimit{Name: parts[0], Soft: soft, Hard: hard}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRlimit returns the RLimit corresponding to Ulimit.
 | 
			
		||||
func (u *Ulimit) GetRlimit() (*Rlimit, error) {
 | 
			
		||||
	t, exists := ulimitNameMapping[u.Name]
 | 
			
		||||
	if !exists {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// Package units provides helper function to parse and print size and time units
 | 
			
		||||
// in human-readable format.
 | 
			
		||||
package units
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -6,7 +8,7 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
// HumanDuration returns a human-readable approximation of a duration
 | 
			
		||||
// (eg. "About a minute", "4 hours ago", etc.)
 | 
			
		||||
// (eg. "About a minute", "4 hours ago", etc.).
 | 
			
		||||
func HumanDuration(d time.Duration) string {
 | 
			
		||||
	if seconds := int(d.Seconds()); seconds < 1 {
 | 
			
		||||
		return "Less than a second"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ var decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
 | 
			
		|||
var binaryAbbrs = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
 | 
			
		||||
 | 
			
		||||
// CustomSize returns a human-readable approximation of a size
 | 
			
		||||
// using custom format
 | 
			
		||||
// using custom format.
 | 
			
		||||
func CustomSize(format string, size float64, base float64, _map []string) string {
 | 
			
		||||
	i := 0
 | 
			
		||||
	for size >= base {
 | 
			
		||||
| 
						 | 
				
			
			@ -49,17 +49,19 @@ func CustomSize(format string, size float64, base float64, _map []string) string
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// HumanSize returns a human-readable approximation of a size
 | 
			
		||||
// using SI standard (eg. "44kB", "17MB")
 | 
			
		||||
// using SI standard (eg. "44kB", "17MB").
 | 
			
		||||
func HumanSize(size float64) string {
 | 
			
		||||
	return CustomSize("%.4g %s", size, 1000.0, decimapAbbrs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BytesSize returns a human-readable size in bytes, kibibytes,
 | 
			
		||||
// mebibytes, gibibytes, or tebibytes (eg. "44kiB", "17MiB").
 | 
			
		||||
func BytesSize(size float64) string {
 | 
			
		||||
	return CustomSize("%.4g %s", size, 1024.0, binaryAbbrs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FromHumanSize returns an integer from a human-readable specification of a
 | 
			
		||||
// size using SI standard (eg. "44kB", "17MB")
 | 
			
		||||
// size using SI standard (eg. "44kB", "17MB").
 | 
			
		||||
func FromHumanSize(size string) (int64, error) {
 | 
			
		||||
	return parseSize(size, decimalMap)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -72,7 +74,7 @@ func RAMInBytes(size string) (int64, error) {
 | 
			
		|||
	return parseSize(size, binaryMap)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parses the human-readable size string into the amount it represents
 | 
			
		||||
// Parses the human-readable size string into the amount it represents.
 | 
			
		||||
func parseSize(sizeStr string, uMap unitMap) (int64, error) {
 | 
			
		||||
	matches := sizeRegex.FindStringSubmatch(sizeStr)
 | 
			
		||||
	if len(matches) != 3 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// Package urlutil provides helper function to check urls kind.
 | 
			
		||||
// It supports http urls, git urls and transport url (tcp://, …)
 | 
			
		||||
package urlutil
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,14 +3,9 @@
 | 
			
		|||
package useragent
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	ErrNilRequest = errors.New("request cannot be nil")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// VersionInfo is used to model UserAgent versions.
 | 
			
		||||
type VersionInfo struct {
 | 
			
		||||
	Name    string
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +25,7 @@ func (vi *VersionInfo) isValid() bool {
 | 
			
		|||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convert versions to a string and append the string to the string base.
 | 
			
		||||
// AppendVersions converts versions to a string and appends the string to the string base.
 | 
			
		||||
//
 | 
			
		||||
// Each VersionInfo will be converted to a string in the format of
 | 
			
		||||
// "product/version", where the "product" is get from the name field, while
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue