diff --git a/parsers/filters/parse.go b/parsers/filters/parse.go index df5486d..6c394f1 100644 --- a/parsers/filters/parse.go +++ b/parsers/filters/parse.go @@ -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] diff --git a/parsers/filters/parse_test.go b/parsers/filters/parse_test.go index a141c33..eb9fcef 100644 --- a/parsers/filters/parse_test.go +++ b/parsers/filters/parse_test.go @@ -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) } } diff --git a/parsers/kernel/kernel.go b/parsers/kernel/kernel.go index 5f79306..a21ba13 100644 --- a/parsers/kernel/kernel.go +++ b/parsers/kernel/kernel.go @@ -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, diff --git a/parsers/kernel/kernel_test.go b/parsers/kernel/kernel_test.go index 7f40939..6a2c246 100644 --- a/parsers/kernel/kernel_test.go +++ b/parsers/kernel/kernel_test.go @@ -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) } diff --git a/parsers/kernel/kernel_windows.go b/parsers/kernel/kernel_windows.go index 399d63e..85ca250 100644 --- a/parsers/kernel/kernel_windows.go +++ b/parsers/kernel/kernel_windows.go @@ -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\\`), diff --git a/parsers/kernel/uname_linux.go b/parsers/kernel/uname_linux.go index 8ca814c..7d12fcb 100644 --- a/parsers/kernel/uname_linux.go +++ b/parsers/kernel/uname_linux.go @@ -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) { diff --git a/parsers/kernel/uname_unsupported.go b/parsers/kernel/uname_unsupported.go index 00c5422..79c66b3 100644 --- a/parsers/kernel/uname_unsupported.go +++ b/parsers/kernel/uname_unsupported.go @@ -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 } diff --git a/parsers/operatingsystem/operatingsystem_linux.go b/parsers/operatingsystem/operatingsystem_linux.go index af185f9..ca8ea8f 100644 --- a/parsers/operatingsystem/operatingsystem_linux.go +++ b/parsers/operatingsystem/operatingsystem_linux.go @@ -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 { diff --git a/parsers/operatingsystem/operatingsystem_windows.go b/parsers/operatingsystem/operatingsystem_windows.go index c843c6f..3c86b6a 100644 --- a/parsers/operatingsystem/operatingsystem_windows.go +++ b/parsers/operatingsystem/operatingsystem_windows.go @@ -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 } diff --git a/parsers/parsers.go b/parsers/parsers.go index ef7f942..e326a11 100644 --- a/parsers/parsers.go +++ b/parsers/parsers.go @@ -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") diff --git a/parsers/parsers_test.go b/parsers/parsers_test.go index a64e6b9..903c66a 100644 --- a/parsers/parsers_test.go +++ b/parsers/parsers_test.go @@ -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) } } diff --git a/pidfile/pidfile.go b/pidfile/pidfile.go index 3e57073..db3535b 100644 --- a/pidfile/pidfile.go +++ b/pidfile/pidfile.go @@ -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 } diff --git a/pidfile/pidfile_test.go b/pidfile/pidfile_test.go index 6ed9cfc..d5ef870 100644 --- a/pidfile/pidfile_test.go +++ b/pidfile/pidfile_test.go @@ -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") diff --git a/plugins/client.go b/plugins/client.go index f30f05e..791fb7f 100644 --- a/plugins/client.go +++ b/plugins/client.go @@ -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) } diff --git a/plugins/discovery.go b/plugins/discovery.go index 2128a92..7bd470d 100644 --- a/plugins/discovery.go +++ b/plugins/discovery.go @@ -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") diff --git a/plugins/plugins.go b/plugins/plugins.go index a624e79..87a8eba 100644 --- a/plugins/plugins.go +++ b/plugins/plugins.go @@ -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 } diff --git a/pools/pools.go b/pools/pools.go index c34ea92..76e84f9 100644 --- a/pools/pools.go +++ b/pools/pools.go @@ -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 } diff --git a/progressreader/progressreader.go b/progressreader/progressreader.go index 908e8ee..d55fadd 100644 --- a/progressreader/progressreader.go +++ b/progressreader/progressreader.go @@ -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 diff --git a/proxy/proxy.go b/proxy/proxy.go index 7a711f6..4e24e5f 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -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: diff --git a/proxy/stub_proxy.go b/proxy/stub_proxy.go index 7684427..571749e 100644 --- a/proxy/stub_proxy.go +++ b/proxy/stub_proxy.go @@ -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, diff --git a/proxy/tcp_proxy.go b/proxy/tcp_proxy.go index 9942e6d..3cd742a 100644 --- a/proxy/tcp_proxy.go +++ b/proxy/tcp_proxy.go @@ -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 } diff --git a/proxy/udp_proxy.go b/proxy/udp_proxy.go index 2a073df..b8375c3 100644 --- a/proxy/udp_proxy.go +++ b/proxy/udp_proxy.go @@ -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. diff --git a/signal/signal.go b/signal/signal.go index 6333754..db60bf2 100644 --- a/signal/signal.go +++ b/signal/signal.go @@ -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) diff --git a/signal/signal_darwin.go b/signal/signal_darwin.go index fcd3a8f..946de87 100644 --- a/signal/signal_darwin.go +++ b/signal/signal_darwin.go @@ -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, diff --git a/signal/signal_freebsd.go b/signal/signal_freebsd.go index 102e918..6b9569b 100644 --- a/signal/signal_freebsd.go +++ b/signal/signal_freebsd.go @@ -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, diff --git a/signal/signal_linux.go b/signal/signal_linux.go index a62f79d..1ecc329 100644 --- a/signal/signal_linux.go +++ b/signal/signal_linux.go @@ -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, diff --git a/signal/signal_unix.go b/signal/signal_unix.go index 613e30e..5c1ad5f 100644 --- a/signal/signal_unix.go +++ b/signal/signal_unix.go @@ -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 diff --git a/signal/signal_unsupported.go b/signal/signal_unsupported.go index 99f9465..cefb240 100644 --- a/signal/signal_unsupported.go +++ b/signal/signal_unsupported.go @@ -6,4 +6,5 @@ import ( "syscall" ) +// SignalMap is an empty map of signals for unsupported platform. var SignalMap = map[string]syscall.Signal{} diff --git a/signal/signal_windows.go b/signal/signal_windows.go index 9f00b99..1f1a6ed 100644 --- a/signal/signal_windows.go +++ b/signal/signal_windows.go @@ -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) +) diff --git a/signal/trap.go b/signal/trap.go index 3772db5..80b5e87 100644 --- a/signal/trap.go +++ b/signal/trap.go @@ -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)] diff --git a/sockets/tcp_socket.go b/sockets/tcp_socket.go index 746270c..9f8319d 100644 --- a/sockets/tcp_socket.go +++ b/sockets/tcp_socket.go @@ -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 diff --git a/sockets/unix_socket.go b/sockets/unix_socket.go index fde11f5..42e558e 100644 --- a/sockets/unix_socket.go +++ b/sockets/unix_socket.go @@ -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 diff --git a/streamformatter/streamformatter.go b/streamformatter/streamformatter.go index 792ce00..7b7ad12 100644 --- a/streamformatter/streamformatter.go +++ b/streamformatter/streamformatter.go @@ -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) { diff --git a/stringid/stringid.go b/stringid/stringid.go index 6a683b6..5a866f6 100644 --- a/stringid/stringid.go +++ b/stringid/stringid.go @@ -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) diff --git a/stringutils/stringutils.go b/stringutils/stringutils.go index aee2648..800da4e 100644 --- a/stringutils/stringutils.go +++ b/stringutils/stringutils.go @@ -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 { diff --git a/stringutils/stringutils_test.go b/stringutils/stringutils_test.go index 124b255..fec5945 100644 --- a/stringutils/stringutils_test.go +++ b/stringutils/stringutils_test.go @@ -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) } diff --git a/systemd/sd_notify.go b/systemd/sd_notify.go index 1993cab..bb864bb 100644 --- a/systemd/sd_notify.go +++ b/systemd/sd_notify.go @@ -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) diff --git a/tailfile/tailfile.go b/tailfile/tailfile.go index 92aea46..83b852c 100644 --- a/tailfile/tailfile.go +++ b/tailfile/tailfile.go @@ -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 diff --git a/tarsum/builder_context.go b/tarsum/builder_context.go index 06a4282..b42983e 100644 --- a/tarsum/builder_context.go +++ b/tarsum/builder_context.go @@ -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) diff --git a/tarsum/fileinfosums.go b/tarsum/fileinfosums.go index 32e5b37..7c2161c 100644 --- a/tarsum/fileinfosums.go +++ b/tarsum/fileinfosums.go @@ -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 { diff --git a/tarsum/tarsum.go b/tarsum/tarsum.go index a778bb0..d2df58c 100644 --- a/tarsum/tarsum.go +++ b/tarsum/tarsum.go @@ -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} } diff --git a/tarsum/versioning.go b/tarsum/versioning.go index 3cdc6dd..8988b9f 100644 --- a/tarsum/versioning.go +++ b/tarsum/versioning.go @@ -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, "+") { diff --git a/term/tc_linux_cgo.go b/term/tc_linux_cgo.go index d47cf59..1005084 100644 --- a/term/tc_linux_cgo.go +++ b/term/tc_linux_cgo.go @@ -10,6 +10,9 @@ import ( // #include 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 diff --git a/term/term.go b/term/term.go index b945a3d..7912ae4 100644 --- a/term/term.go +++ b/term/term.go @@ -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 { diff --git a/term/term_windows.go b/term/term_windows.go index f7fa1b3..7eb9da3 100644 --- a/term/term_windows.go +++ b/term/term_windows.go @@ -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 { diff --git a/term/termios_darwin.go b/term/termios_darwin.go index 11cd70d..480db90 100644 --- a/term/termios_darwin.go +++ b/term/termios_darwin.go @@ -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 diff --git a/term/termios_freebsd.go b/term/termios_freebsd.go index ed36595..ed843ad 100644 --- a/term/termios_freebsd.go +++ b/term/termios_freebsd.go @@ -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 diff --git a/term/termios_linux.go b/term/termios_linux.go index 024187f..22921b6 100644 --- a/term/termios_linux.go +++ b/term/termios_linux.go @@ -12,6 +12,7 @@ const ( setTermios = syscall.TCSETS ) +// Termios is the Unix API for terminal I/O. type Termios struct { Iflag uint32 Oflag uint32 diff --git a/timeoutconn/timeoutconn.go b/timeoutconn/timeoutconn.go index d9534b5..6487e3b 100644 --- a/timeoutconn/timeoutconn.go +++ b/timeoutconn/timeoutconn.go @@ -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 diff --git a/timeutils/json.go b/timeutils/json.go index 8043d69..ea19daa 100644 --- a/timeutils/json.go +++ b/timeutils/json.go @@ -1,3 +1,4 @@ +// Package timeutils provides helper functions to parse and print time (time.Time). package timeutils import ( diff --git a/truncindex/truncindex.go b/truncindex/truncindex.go index 8d8bee0..33ea2b5 100644 --- a/truncindex/truncindex.go +++ b/truncindex/truncindex.go @@ -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() diff --git a/ulimit/ulimit.go b/ulimit/ulimit.go index eb2ae4e..8fb0d80 100644 --- a/ulimit/ulimit.go +++ b/ulimit/ulimit.go @@ -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 { diff --git a/units/duration.go b/units/duration.go index 44012aa..c219a8a 100644 --- a/units/duration.go +++ b/units/duration.go @@ -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" diff --git a/units/size.go b/units/size.go index 9e84697..2fde3b4 100644 --- a/units/size.go +++ b/units/size.go @@ -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 { diff --git a/urlutil/urlutil.go b/urlutil/urlutil.go index 7250643..f7094b1 100644 --- a/urlutil/urlutil.go +++ b/urlutil/urlutil.go @@ -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 ( diff --git a/useragent/useragent.go b/useragent/useragent.go index 9e35d1c..a410974 100644 --- a/useragent/useragent.go +++ b/useragent/useragent.go @@ -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