Merge pull request #3484 from hashicorp/b-nomad-0.7.1

merge nomad 0.7.1 branch
This commit is contained in:
Preetha
2017-11-01 16:50:37 -05:00
committed by GitHub
38 changed files with 843 additions and 244 deletions

View File

@@ -115,7 +115,8 @@ func (s *HTTPServer) ClientGCRequest(resp http.ResponseWriter, req *http.Request
return nil, structs.ErrPermissionDenied
}
return nil, s.agent.Client().CollectAllAllocs()
s.agent.Client().CollectAllAllocs()
return nil, nil
}
func (s *HTTPServer) allocGC(allocID string, resp http.ResponseWriter, req *http.Request) (interface{}, error) {
@@ -131,7 +132,12 @@ func (s *HTTPServer) allocGC(allocID string, resp http.ResponseWriter, req *http
} else if aclObj != nil && !aclObj.AllowNsOp(namespace, acl.NamespaceCapabilitySubmitJob) {
return nil, structs.ErrPermissionDenied
}
return nil, s.agent.Client().CollectAllocation(allocID)
if !s.agent.Client().CollectAllocation(allocID) {
// Could not find alloc
return nil, fmt.Errorf("unable to collect allocation: not present")
}
return nil, nil
}
func (s *HTTPServer) allocSnapshot(allocID string, resp http.ResponseWriter, req *http.Request) (interface{}, error) {

View File

@@ -152,6 +152,7 @@ tls {
ca_file = "foo"
cert_file = "bar"
key_file = "pipe"
rpc_upgrade_mode = true
verify_https_client = true
}
sentinel {

View File

@@ -771,6 +771,7 @@ func parseTLSConfig(result **config.TLSConfig, list *ast.ObjectList) error {
"http",
"rpc",
"verify_server_hostname",
"rpc_upgrade_mode",
"ca_file",
"cert_file",
"key_file",

View File

@@ -172,6 +172,7 @@ func TestConfig_Parse(t *testing.T) {
CAFile: "foo",
CertFile: "bar",
KeyFile: "pipe",
RPCUpgradeMode: true,
VerifyHTTPSClient: true,
},
HTTPAPIResponseHeaders: map[string]string{

View File

@@ -214,6 +214,16 @@ func (c *AllocStatusCommand) Run(args []string) int {
}
func formatAllocBasicInfo(alloc *api.Allocation, client *api.Client, uuidLength int, verbose bool) (string, error) {
var formattedCreateTime, formattedModifyTime string
if verbose {
formattedCreateTime = formatUnixNanoTime(alloc.CreateTime)
formattedModifyTime = formatUnixNanoTime(alloc.ModifyTime)
} else {
formattedCreateTime = prettyTimeDiff(time.Unix(0, alloc.CreateTime), time.Now())
formattedModifyTime = prettyTimeDiff(time.Unix(0, alloc.ModifyTime), time.Now())
}
basic := []string{
fmt.Sprintf("ID|%s", limit(alloc.ID, uuidLength)),
fmt.Sprintf("Eval ID|%s", limit(alloc.EvalID, uuidLength)),
@@ -225,7 +235,8 @@ func formatAllocBasicInfo(alloc *api.Allocation, client *api.Client, uuidLength
fmt.Sprintf("Client Description|%s", alloc.ClientDescription),
fmt.Sprintf("Desired Status|%s", alloc.DesiredStatus),
fmt.Sprintf("Desired Description|%s", alloc.DesiredDescription),
fmt.Sprintf("Created At|%s", formatUnixNanoTime(alloc.CreateTime)),
fmt.Sprintf("Created|%s", formattedCreateTime),
fmt.Sprintf("Modified|%s", formattedModifyTime),
}
if alloc.DeploymentID != "" {

View File

@@ -128,9 +128,14 @@ func TestAllocStatusCommand_Run(t *testing.T) {
t.Fatalf("expected exit 0, got: %d", code)
}
out := ui.OutputWriter.String()
if !strings.Contains(out, "Created At") {
t.Fatalf("expected to have 'Created At' but saw: %s", out)
if !strings.Contains(out, "Created") {
t.Fatalf("expected to have 'Created' but saw: %s", out)
}
if !strings.Contains(out, "Modified") {
t.Fatalf("expected to have 'Modified' but saw: %s", out)
}
ui.OutputWriter.Reset()
if code := cmd.Run([]string{"-address=" + url, "-verbose", allocId1}); code != 0 {
@@ -140,8 +145,8 @@ func TestAllocStatusCommand_Run(t *testing.T) {
if !strings.Contains(out, allocId1) {
t.Fatal("expected to find alloc id in output")
}
if !strings.Contains(out, "Created At") {
t.Fatalf("expected to have 'Created At' but saw: %s", out)
if !strings.Contains(out, "Created") {
t.Fatalf("expected to have 'Created' but saw: %s", out)
}
ui.OutputWriter.Reset()
@@ -150,8 +155,8 @@ func TestAllocStatusCommand_Run(t *testing.T) {
t.Fatalf("expected exit 0, got: %d", code)
}
out = ui.OutputWriter.String()
if !strings.Contains(out, "Created At") {
t.Fatalf("expected to have 'Created At' but saw: %s", out)
if !strings.Contains(out, "Created") {
t.Fatalf("expected to have 'Created' but saw: %s", out)
}
ui.OutputWriter.Reset()

View File

@@ -75,6 +75,116 @@ func formatTimeDifference(first, second time.Time, d time.Duration) string {
return second.Truncate(d).Sub(first.Truncate(d)).String()
}
// fmtInt formats v into the tail of buf.
// It returns the index where the output begins.
func fmtInt(buf []byte, v uint64) int {
w := len(buf)
for v > 0 {
w--
buf[w] = byte(v%10) + '0'
v /= 10
}
return w
}
// prettyTimeDiff prints a human readable time difference.
// It uses abbreviated forms for each period - s for seconds, m for minutes, h for hours,
// d for days, mo for months, and y for years. Time difference is rounded to the nearest second,
// and the top two least granular periods are returned. For example, if the time difference
// is 10 months, 12 days, 3 hours and 2 seconds, the string "10mo12d" is returned. Zero values return the empty string
func prettyTimeDiff(first, second time.Time) string {
// handle zero values
if first.Second() == 0 {
return ""
}
// round to the nearest second
first = first.Round(time.Second)
second = second.Round(time.Second)
// calculate time difference in seconds
d := second.Sub(first)
u := uint64(d.Seconds())
var buf [32]byte
w := len(buf)
secs := u % 60
// track indexes of various periods
var indexes []int
if secs > 0 {
w--
buf[w] = 's'
// u is now seconds
w = fmtInt(buf[:w], secs)
indexes = append(indexes, w)
}
u /= 60
// u is now minutes
if u > 0 {
mins := u % 60
if mins > 0 {
w--
buf[w] = 'm'
w = fmtInt(buf[:w], mins)
indexes = append(indexes, w)
}
u /= 60
// u is now hours
if u > 0 {
hrs := u % 24
if hrs > 0 {
w--
buf[w] = 'h'
w = fmtInt(buf[:w], hrs)
indexes = append(indexes, w)
}
u /= 24
}
// u is now days
if u > 0 {
days := u % 30
if days > 0 {
w--
buf[w] = 'd'
w = fmtInt(buf[:w], days)
indexes = append(indexes, w)
}
u /= 30
}
// u is now months
if u > 0 {
months := u % 12
if months > 0 {
w--
buf[w] = 'o'
w--
buf[w] = 'm'
w = fmtInt(buf[:w], months)
indexes = append(indexes, w)
}
u /= 12
}
// u is now years
if u > 0 {
w--
buf[w] = 'y'
w = fmtInt(buf[:w], u)
indexes = append(indexes, w)
}
}
start := w
end := len(buf)
// truncate to the first two periods
num_periods := len(indexes)
if num_periods > 2 {
end = indexes[num_periods-3]
}
return string(buf[start:end]) + " ago"
}
// getLocalNodeID returns the node ID of the local Nomad Client and an error if
// it couldn't be determined or the Agent is not running in Client mode.
func getLocalNodeID(client *api.Client) (string, error) {

View File

@@ -294,3 +294,35 @@ func TestJobGetter_HTTPServer(t *testing.T) {
t.Fatalf("Unexpected file")
}
}
func TestPrettyTimeDiff(t *testing.T) {
test_cases := []struct {
d time.Duration
exp string
}{
{-740 * time.Second, "12m20s ago"},
{-12 * time.Minute, "12m ago"},
{-60 * time.Minute, "1h ago"},
{-80 * time.Minute, "1h20m ago"},
{-6 * time.Hour, "6h ago"},
{-22165 * time.Second, "6h9m ago"},
{-100 * time.Hour, "4d4h ago"},
{-438000 * time.Minute, "10mo4d ago"},
{-20460 * time.Hour, "2y4mo ago"},
}
for _, tc := range test_cases {
t2 := time.Now().Add(tc.d)
out := prettyTimeDiff(t2, time.Now())
if out != tc.exp {
t.Fatalf("expected :%v but got :%v", tc.exp, out)
}
}
var t1 time.Time
out := prettyTimeDiff(t1, time.Now())
if out != "" {
t.Fatalf("Expected empty output but got:%v", out)
}
}

View File

@@ -406,9 +406,9 @@ func formatAllocListStubs(stubs []*api.AllocationListStub, verbose bool, uuidLen
allocs := make([]string, len(stubs)+1)
if verbose {
allocs[0] = "ID|Eval ID|Node ID|Task Group|Version|Desired|Status|Created At"
allocs[0] = "ID|Eval ID|Node ID|Task Group|Version|Desired|Status|Created|Modified"
for i, alloc := range stubs {
allocs[i+1] = fmt.Sprintf("%s|%s|%s|%s|%d|%s|%s|%s",
allocs[i+1] = fmt.Sprintf("%s|%s|%s|%s|%d|%s|%s|%s|%s",
limit(alloc.ID, uuidLength),
limit(alloc.EvalID, uuidLength),
limit(alloc.NodeID, uuidLength),
@@ -416,19 +416,23 @@ func formatAllocListStubs(stubs []*api.AllocationListStub, verbose bool, uuidLen
alloc.JobVersion,
alloc.DesiredStatus,
alloc.ClientStatus,
formatUnixNanoTime(alloc.CreateTime))
formatUnixNanoTime(alloc.CreateTime),
formatUnixNanoTime(alloc.ModifyTime))
}
} else {
allocs[0] = "ID|Node ID|Task Group|Version|Desired|Status|Created At"
allocs[0] = "ID|Node ID|Task Group|Version|Desired|Status|Created|Modified"
for i, alloc := range stubs {
allocs[i+1] = fmt.Sprintf("%s|%s|%s|%d|%s|%s|%s",
createTimePretty := prettyTimeDiff(time.Unix(0, alloc.CreateTime), time.Now())
modTimePretty := prettyTimeDiff(time.Unix(0, alloc.ModifyTime), time.Now())
allocs[i+1] = fmt.Sprintf("%s|%s|%s|%d|%s|%s|%s|%s",
limit(alloc.ID, uuidLength),
limit(alloc.NodeID, uuidLength),
alloc.TaskGroup,
alloc.JobVersion,
alloc.DesiredStatus,
alloc.ClientStatus,
formatUnixNanoTime(alloc.CreateTime))
createTimePretty,
modTimePretty)
}
}

View File

@@ -113,9 +113,12 @@ func TestJobStatusCommand_Run(t *testing.T) {
if !strings.Contains(out, "Allocations") {
t.Fatalf("should dump allocations")
}
if !strings.Contains(out, "Created At") {
if !strings.Contains(out, "Created") {
t.Fatal("should have created header")
}
if !strings.Contains(out, "Modified") {
t.Fatal("should have modified header")
}
ui.ErrorWriter.Reset()
ui.OutputWriter.Reset()
@@ -138,6 +141,14 @@ func TestJobStatusCommand_Run(t *testing.T) {
if !strings.Contains(out, "job1_sfx") || strings.Contains(out, "job2_sfx") {
t.Fatalf("expected only job1_sfx, got: %s", out)
}
if !strings.Contains(out, "Created") {
t.Fatal("should have created header")
}
if !strings.Contains(out, "Modified") {
t.Fatal("should have modified header")
}
ui.OutputWriter.Reset()
// Query in short view mode