mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Move duration and size to units pkg
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
		
							parent
							
								
									0d78799db7
								
							
						
					
					
						commit
						d33b4655c4
					
				
					 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"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +120,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"
 | 
			
		||||
| 
						 | 
				
			
			@ -83,79 +82,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…
	
	Add table
		Add a link
		
	
		Reference in a new issue