Merge pull request #5756 from crosbymichael/move-units-to-pkg
Move duration and size to units pkg
This commit is contained in:
commit
bc22c9948c
11 changed files with 165 additions and 140 deletions
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/dotcloud/docker/nat"
|
||||
"github.com/dotcloud/docker/pkg/signal"
|
||||
"github.com/dotcloud/docker/pkg/term"
|
||||
"github.com/dotcloud/docker/pkg/units"
|
||||
"github.com/dotcloud/docker/registry"
|
||||
"github.com/dotcloud/docker/runconfig"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
|
@ -884,14 +885,14 @@ func (cli *DockerCli) CmdHistory(args ...string) error {
|
|||
fmt.Fprintf(w, "%s\t", utils.TruncateID(outID))
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%s ago\t", utils.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))))
|
||||
fmt.Fprintf(w, "%s ago\t", units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))))
|
||||
|
||||
if *noTrunc {
|
||||
fmt.Fprintf(w, "%s\t", out.Get("CreatedBy"))
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s\t", utils.Trunc(out.Get("CreatedBy"), 45))
|
||||
}
|
||||
fmt.Fprintf(w, "%s\n", utils.HumanSize(out.GetInt64("Size")))
|
||||
fmt.Fprintf(w, "%s\n", units.HumanSize(out.GetInt64("Size")))
|
||||
} else {
|
||||
if *noTrunc {
|
||||
fmt.Fprintln(w, outID)
|
||||
|
@ -1249,7 +1250,7 @@ func (cli *DockerCli) CmdImages(args ...string) error {
|
|||
}
|
||||
|
||||
if !*quiet {
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, outID, utils.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), utils.HumanSize(out.GetInt64("VirtualSize")))
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(out.GetInt64("VirtualSize")))
|
||||
} else {
|
||||
fmt.Fprintln(w, outID)
|
||||
}
|
||||
|
@ -1323,7 +1324,7 @@ func (cli *DockerCli) printTreeNode(noTrunc bool, image *engine.Env, prefix stri
|
|||
imageID = utils.TruncateID(image.Get("Id"))
|
||||
}
|
||||
|
||||
fmt.Fprintf(cli.out, "%s%s Virtual Size: %s", prefix, imageID, utils.HumanSize(image.GetInt64("VirtualSize")))
|
||||
fmt.Fprintf(cli.out, "%s%s Virtual Size: %s", prefix, imageID, units.HumanSize(image.GetInt64("VirtualSize")))
|
||||
if image.GetList("RepoTags")[0] != "<none>:<none>" {
|
||||
fmt.Fprintf(cli.out, " Tags: %s\n", strings.Join(image.GetList("RepoTags"), ", "))
|
||||
} else {
|
||||
|
@ -1408,12 +1409,12 @@ func (cli *DockerCli) CmdPs(args ...string) error {
|
|||
outCommand = utils.Trunc(outCommand, 20)
|
||||
}
|
||||
ports.ReadListFrom([]byte(out.Get("Ports")))
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", outID, out.Get("Image"), outCommand, utils.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), out.Get("Status"), api.DisplayablePorts(ports), strings.Join(outNames, ","))
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", outID, out.Get("Image"), outCommand, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), out.Get("Status"), api.DisplayablePorts(ports), strings.Join(outNames, ","))
|
||||
if *size {
|
||||
if out.GetInt("SizeRootFs") > 0 {
|
||||
fmt.Fprintf(w, "%s (virtual %s)\n", utils.HumanSize(out.GetInt64("SizeRw")), utils.HumanSize(out.GetInt64("SizeRootFs")))
|
||||
fmt.Fprintf(w, "%s (virtual %s)\n", units.HumanSize(out.GetInt64("SizeRw")), units.HumanSize(out.GetInt64("SizeRootFs")))
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s\n", utils.HumanSize(out.GetInt64("SizeRw")))
|
||||
fmt.Fprintf(w, "%s\n", units.HumanSize(out.GetInt64("SizeRw")))
|
||||
}
|
||||
} else {
|
||||
fmt.Fprint(w, "\n")
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/dotcloud/docker/pkg/libcontainer"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"github.com/dotcloud/docker/pkg/units"
|
||||
)
|
||||
|
||||
type Action func(*libcontainer.Container, interface{}, string) error
|
||||
|
@ -75,7 +75,7 @@ func memory(container *libcontainer.Container, context interface{}, value string
|
|||
return fmt.Errorf("cannot set cgroups when they are disabled")
|
||||
}
|
||||
|
||||
v, err := utils.RAMInBytes(value)
|
||||
v, err := units.RAMInBytes(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ func memoryReservation(container *libcontainer.Container, context interface{}, v
|
|||
return fmt.Errorf("cannot set cgroups when they are disabled")
|
||||
}
|
||||
|
||||
v, err := utils.RAMInBytes(value)
|
||||
v, err := units.RAMInBytes(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -2,9 +2,10 @@ package daemon
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/dotcloud/docker/pkg/units"
|
||||
)
|
||||
|
||||
type State struct {
|
||||
|
@ -22,12 +23,12 @@ func (s *State) String() string {
|
|||
defer s.RUnlock()
|
||||
|
||||
if s.Running {
|
||||
return fmt.Sprintf("Up %s", utils.HumanDuration(time.Now().UTC().Sub(s.StartedAt)))
|
||||
return fmt.Sprintf("Up %s", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt)))
|
||||
}
|
||||
if s.FinishedAt.IsZero() {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, utils.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
|
||||
return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
|
||||
}
|
||||
|
||||
func (s *State) IsRunning() bool {
|
||||
|
|
2
pkg/units/MAINTAINERS
Normal file
2
pkg/units/MAINTAINERS
Normal file
|
@ -0,0 +1,2 @@
|
|||
Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
|
||||
Victor Vieux <vieux@docker.com> (@vieux)
|
31
pkg/units/duration.go
Normal file
31
pkg/units/duration.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package units
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// HumanDuration returns a human-readable approximation of a duration
|
||||
// (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"
|
||||
} else if seconds < 60 {
|
||||
return fmt.Sprintf("%d seconds", seconds)
|
||||
} else if minutes := int(d.Minutes()); minutes == 1 {
|
||||
return "About a minute"
|
||||
} else if minutes < 60 {
|
||||
return fmt.Sprintf("%d minutes", minutes)
|
||||
} else if hours := int(d.Hours()); hours == 1 {
|
||||
return "About an hour"
|
||||
} else if hours < 48 {
|
||||
return fmt.Sprintf("%d hours", hours)
|
||||
} else if hours < 24*7*2 {
|
||||
return fmt.Sprintf("%d days", hours/24)
|
||||
} else if hours < 24*30*3 {
|
||||
return fmt.Sprintf("%d weeks", hours/24/7)
|
||||
} else if hours < 24*365*2 {
|
||||
return fmt.Sprintf("%d months", hours/24/30)
|
||||
}
|
||||
return fmt.Sprintf("%f years", d.Hours()/24/365)
|
||||
}
|
56
pkg/units/size.go
Normal file
56
pkg/units/size.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
package units
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// HumanSize returns a human-readable approximation of a size
|
||||
// using SI standard (eg. "44kB", "17MB")
|
||||
func HumanSize(size int64) string {
|
||||
i := 0
|
||||
var sizef float64
|
||||
sizef = float64(size)
|
||||
units := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
||||
for sizef >= 1000.0 {
|
||||
sizef = sizef / 1000.0
|
||||
i++
|
||||
}
|
||||
return fmt.Sprintf("%.4g %s", sizef, units[i])
|
||||
}
|
||||
|
||||
// Parses a human-readable string representing an amount of RAM
|
||||
// in bytes, kibibytes, mebibytes or gibibytes, and returns the
|
||||
// number of bytes, or -1 if the string is unparseable.
|
||||
// Units are case-insensitive, and the 'b' suffix is optional.
|
||||
func RAMInBytes(size string) (bytes int64, err error) {
|
||||
re, error := regexp.Compile("^(\\d+)([kKmMgG])?[bB]?$")
|
||||
if error != nil {
|
||||
return -1, error
|
||||
}
|
||||
|
||||
matches := re.FindStringSubmatch(size)
|
||||
|
||||
if len(matches) != 3 {
|
||||
return -1, fmt.Errorf("Invalid size: '%s'", size)
|
||||
}
|
||||
|
||||
memLimit, error := strconv.ParseInt(matches[1], 10, 0)
|
||||
if error != nil {
|
||||
return -1, error
|
||||
}
|
||||
|
||||
unit := strings.ToLower(matches[2])
|
||||
|
||||
if unit == "k" {
|
||||
memLimit *= 1024
|
||||
} else if unit == "m" {
|
||||
memLimit *= 1024 * 1024
|
||||
} else if unit == "g" {
|
||||
memLimit *= 1024 * 1024 * 1024
|
||||
}
|
||||
|
||||
return memLimit, nil
|
||||
}
|
54
pkg/units/size_test.go
Normal file
54
pkg/units/size_test.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
package units
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHumanSize(t *testing.T) {
|
||||
|
||||
size := strings.Trim(HumanSize(1000), " \t")
|
||||
expect := "1 kB"
|
||||
if size != expect {
|
||||
t.Errorf("1000 -> expected '%s', got '%s'", expect, size)
|
||||
}
|
||||
|
||||
size = strings.Trim(HumanSize(1024), " \t")
|
||||
expect = "1.024 kB"
|
||||
if size != expect {
|
||||
t.Errorf("1024 -> expected '%s', got '%s'", expect, size)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRAMInBytes(t *testing.T) {
|
||||
assertRAMInBytes(t, "32", false, 32)
|
||||
assertRAMInBytes(t, "32b", false, 32)
|
||||
assertRAMInBytes(t, "32B", false, 32)
|
||||
assertRAMInBytes(t, "32k", false, 32*1024)
|
||||
assertRAMInBytes(t, "32K", false, 32*1024)
|
||||
assertRAMInBytes(t, "32kb", false, 32*1024)
|
||||
assertRAMInBytes(t, "32Kb", false, 32*1024)
|
||||
assertRAMInBytes(t, "32Mb", false, 32*1024*1024)
|
||||
assertRAMInBytes(t, "32Gb", false, 32*1024*1024*1024)
|
||||
|
||||
assertRAMInBytes(t, "", true, -1)
|
||||
assertRAMInBytes(t, "hello", true, -1)
|
||||
assertRAMInBytes(t, "-32", true, -1)
|
||||
assertRAMInBytes(t, " 32 ", true, -1)
|
||||
assertRAMInBytes(t, "32 mb", true, -1)
|
||||
assertRAMInBytes(t, "32m b", true, -1)
|
||||
assertRAMInBytes(t, "32bm", true, -1)
|
||||
}
|
||||
|
||||
func assertRAMInBytes(t *testing.T, size string, expectError bool, expectedBytes int64) {
|
||||
actualBytes, err := RAMInBytes(size)
|
||||
if (err != nil) && !expectError {
|
||||
t.Errorf("Unexpected error parsing '%s': %s", size, err)
|
||||
}
|
||||
if (err == nil) && expectError {
|
||||
t.Errorf("Expected to get an error parsing '%s', but got none (bytes=%d)", size, actualBytes)
|
||||
}
|
||||
if actualBytes != expectedBytes {
|
||||
t.Errorf("Expected '%s' to parse as %d bytes, got %d", size, expectedBytes, actualBytes)
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/dotcloud/docker/opts"
|
||||
flag "github.com/dotcloud/docker/pkg/mflag"
|
||||
"github.com/dotcloud/docker/pkg/sysinfo"
|
||||
"github.com/dotcloud/docker/pkg/units"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
)
|
||||
|
||||
|
@ -120,7 +121,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
|
|||
|
||||
var flMemory int64
|
||||
if *flMemoryString != "" {
|
||||
parsedMemory, err := utils.RAMInBytes(*flMemoryString)
|
||||
parsedMemory, err := units.RAMInBytes(*flMemoryString)
|
||||
if err != nil {
|
||||
return nil, nil, cmd, err
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@ package utils
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/dotcloud/docker/pkg/term"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dotcloud/docker/pkg/term"
|
||||
"github.com/dotcloud/docker/pkg/units"
|
||||
)
|
||||
|
||||
type JSONError struct {
|
||||
|
@ -41,11 +43,11 @@ func (p *JSONProgress) String() string {
|
|||
if p.Current <= 0 && p.Total <= 0 {
|
||||
return ""
|
||||
}
|
||||
current := HumanSize(int64(p.Current))
|
||||
current := units.HumanSize(int64(p.Current))
|
||||
if p.Total <= 0 {
|
||||
return fmt.Sprintf("%8v", current)
|
||||
}
|
||||
total := HumanSize(int64(p.Total))
|
||||
total := units.HumanSize(int64(p.Total))
|
||||
percentage := int(float64(p.Current)/float64(p.Total)*100) / 2
|
||||
if width > 110 {
|
||||
pbBox = fmt.Sprintf("[%s>%s] ", strings.Repeat("=", percentage), strings.Repeat(" ", 50-percentage))
|
||||
|
|
|
@ -16,7 +16,6 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -84,79 +83,6 @@ func Errorf(format string, a ...interface{}) {
|
|||
logf("error", format, a...)
|
||||
}
|
||||
|
||||
// HumanDuration returns a human-readable approximation of a duration
|
||||
// (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"
|
||||
} else if seconds < 60 {
|
||||
return fmt.Sprintf("%d seconds", seconds)
|
||||
} else if minutes := int(d.Minutes()); minutes == 1 {
|
||||
return "About a minute"
|
||||
} else if minutes < 60 {
|
||||
return fmt.Sprintf("%d minutes", minutes)
|
||||
} else if hours := int(d.Hours()); hours == 1 {
|
||||
return "About an hour"
|
||||
} else if hours < 48 {
|
||||
return fmt.Sprintf("%d hours", hours)
|
||||
} else if hours < 24*7*2 {
|
||||
return fmt.Sprintf("%d days", hours/24)
|
||||
} else if hours < 24*30*3 {
|
||||
return fmt.Sprintf("%d weeks", hours/24/7)
|
||||
} else if hours < 24*365*2 {
|
||||
return fmt.Sprintf("%d months", hours/24/30)
|
||||
}
|
||||
return fmt.Sprintf("%f years", d.Hours()/24/365)
|
||||
}
|
||||
|
||||
// HumanSize returns a human-readable approximation of a size
|
||||
// using SI standard (eg. "44kB", "17MB")
|
||||
func HumanSize(size int64) string {
|
||||
i := 0
|
||||
var sizef float64
|
||||
sizef = float64(size)
|
||||
units := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
||||
for sizef >= 1000.0 {
|
||||
sizef = sizef / 1000.0
|
||||
i++
|
||||
}
|
||||
return fmt.Sprintf("%.4g %s", sizef, units[i])
|
||||
}
|
||||
|
||||
// Parses a human-readable string representing an amount of RAM
|
||||
// in bytes, kibibytes, mebibytes or gibibytes, and returns the
|
||||
// number of bytes, or -1 if the string is unparseable.
|
||||
// Units are case-insensitive, and the 'b' suffix is optional.
|
||||
func RAMInBytes(size string) (bytes int64, err error) {
|
||||
re, error := regexp.Compile("^(\\d+)([kKmMgG])?[bB]?$")
|
||||
if error != nil {
|
||||
return -1, error
|
||||
}
|
||||
|
||||
matches := re.FindStringSubmatch(size)
|
||||
|
||||
if len(matches) != 3 {
|
||||
return -1, fmt.Errorf("Invalid size: '%s'", size)
|
||||
}
|
||||
|
||||
memLimit, error := strconv.ParseInt(matches[1], 10, 0)
|
||||
if error != nil {
|
||||
return -1, error
|
||||
}
|
||||
|
||||
unit := strings.ToLower(matches[2])
|
||||
|
||||
if unit == "k" {
|
||||
memLimit *= 1024
|
||||
} else if unit == "m" {
|
||||
memLimit *= 1024 * 1024
|
||||
} else if unit == "g" {
|
||||
memLimit *= 1024 * 1024 * 1024
|
||||
}
|
||||
|
||||
return memLimit, nil
|
||||
}
|
||||
|
||||
func Trunc(s string, maxlen int) string {
|
||||
if len(s) <= maxlen {
|
||||
return s
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -271,54 +270,6 @@ func TestCompareKernelVersion(t *testing.T) {
|
|||
-1)
|
||||
}
|
||||
|
||||
func TestHumanSize(t *testing.T) {
|
||||
|
||||
size := strings.Trim(HumanSize(1000), " \t")
|
||||
expect := "1 kB"
|
||||
if size != expect {
|
||||
t.Errorf("1000 -> expected '%s', got '%s'", expect, size)
|
||||
}
|
||||
|
||||
size = strings.Trim(HumanSize(1024), " \t")
|
||||
expect = "1.024 kB"
|
||||
if size != expect {
|
||||
t.Errorf("1024 -> expected '%s', got '%s'", expect, size)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRAMInBytes(t *testing.T) {
|
||||
assertRAMInBytes(t, "32", false, 32)
|
||||
assertRAMInBytes(t, "32b", false, 32)
|
||||
assertRAMInBytes(t, "32B", false, 32)
|
||||
assertRAMInBytes(t, "32k", false, 32*1024)
|
||||
assertRAMInBytes(t, "32K", false, 32*1024)
|
||||
assertRAMInBytes(t, "32kb", false, 32*1024)
|
||||
assertRAMInBytes(t, "32Kb", false, 32*1024)
|
||||
assertRAMInBytes(t, "32Mb", false, 32*1024*1024)
|
||||
assertRAMInBytes(t, "32Gb", false, 32*1024*1024*1024)
|
||||
|
||||
assertRAMInBytes(t, "", true, -1)
|
||||
assertRAMInBytes(t, "hello", true, -1)
|
||||
assertRAMInBytes(t, "-32", true, -1)
|
||||
assertRAMInBytes(t, " 32 ", true, -1)
|
||||
assertRAMInBytes(t, "32 mb", true, -1)
|
||||
assertRAMInBytes(t, "32m b", true, -1)
|
||||
assertRAMInBytes(t, "32bm", true, -1)
|
||||
}
|
||||
|
||||
func assertRAMInBytes(t *testing.T, size string, expectError bool, expectedBytes int64) {
|
||||
actualBytes, err := RAMInBytes(size)
|
||||
if (err != nil) && !expectError {
|
||||
t.Errorf("Unexpected error parsing '%s': %s", size, err)
|
||||
}
|
||||
if (err == nil) && expectError {
|
||||
t.Errorf("Expected to get an error parsing '%s', but got none (bytes=%d)", size, actualBytes)
|
||||
}
|
||||
if actualBytes != expectedBytes {
|
||||
t.Errorf("Expected '%s' to parse as %d bytes, got %d", size, expectedBytes, actualBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseHost(t *testing.T) {
|
||||
var (
|
||||
defaultHttpHost = "127.0.0.1"
|
||||
|
|
Loading…
Reference in a new issue