From acfe95887eb24422da34b0a903a1bceeb0ffca09 Mon Sep 17 00:00:00 2001 From: Preetha Appan Date: Wed, 25 Oct 2017 13:06:25 -0500 Subject: [PATCH] Add ModifyTime to Allocation and update it both on plan applies and client initiated updates --- api/allocations.go | 4 +++- nomad/node_endpoint.go | 4 ++++ nomad/node_endpoint_test.go | 10 ++++++++++ nomad/plan_apply.go | 2 ++ nomad/plan_apply_test.go | 4 ++++ nomad/state/state_store.go | 3 +++ nomad/structs/structs.go | 5 +++++ 7 files changed, 31 insertions(+), 1 deletion(-) diff --git a/api/allocations.go b/api/allocations.go index c01cbfc45..f23b83551 100644 --- a/api/allocations.go +++ b/api/allocations.go @@ -95,6 +95,7 @@ type Allocation struct { ModifyIndex uint64 AllocModifyIndex uint64 CreateTime int64 + ModifyTime int64 } // AllocationMetric is used to deserialize allocation metrics. @@ -132,11 +133,12 @@ type AllocationListStub struct { CreateIndex uint64 ModifyIndex uint64 CreateTime int64 + ModifyTime int64 } // AllocDeploymentStatus captures the status of the allocation as part of the // deployment. This can include things like if the allocation has been marked as -// heatlhy. +// healthy. type AllocDeploymentStatus struct { Healthy *bool ModifyIndex uint64 diff --git a/nomad/node_endpoint.go b/nomad/node_endpoint.go index c130e90af..9dbd7f871 100644 --- a/nomad/node_endpoint.go +++ b/nomad/node_endpoint.go @@ -822,6 +822,10 @@ func (n *Node) UpdateAlloc(args *structs.AllocUpdateRequest, reply *structs.Gene // Add this to the batch n.updatesLock.Lock() + now := time.Now().UTC().UnixNano() + for _, alloc := range args.Alloc { + alloc.ModifyTime = now + } n.updates = append(n.updates, args.Alloc...) // Start a new batch if none diff --git a/nomad/node_endpoint_test.go b/nomad/node_endpoint_test.go index e50e96826..22f919bb3 100644 --- a/nomad/node_endpoint_test.go +++ b/nomad/node_endpoint_test.go @@ -1323,8 +1323,10 @@ func TestClientEndpoint_GetClientAllocs_Blocking(t *testing.T) { node.ModifyIndex = resp.Index // Inject fake evaluations async + now := time.Now().UTC().UnixNano() alloc := mock.Alloc() alloc.NodeID = node.ID + alloc.ModifyTime = now state := s1.fsm.State() state.UpsertJobSummary(99, mock.JobSummary(alloc.JobID)) start := time.Now() @@ -1363,6 +1365,10 @@ func TestClientEndpoint_GetClientAllocs_Blocking(t *testing.T) { t.Fatalf("bad: %#v", resp2.Allocs) } + if resp2.Allocs[0].ModifyTime != now { + t.Fatalf("Invalid modify time %v", resp2.Allocs[0].ModifyTime) + } + // Alloc updates fire watches time.AfterFunc(100*time.Millisecond, func() { allocUpdate := mock.Alloc() @@ -1675,6 +1681,10 @@ func TestClientEndpoint_UpdateAlloc(t *testing.T) { if out.ClientStatus != structs.AllocClientStatusFailed { t.Fatalf("Bad: %#v", out) } + + if out.ModifyTime <= 0 { + t.Fatalf("must have valid modify time but was %v", out.ModifyTime) + } } func TestClientEndpoint_BatchUpdate(t *testing.T) { diff --git a/nomad/plan_apply.go b/nomad/plan_apply.go index 9e82c54f6..fe2ed2e5c 100644 --- a/nomad/plan_apply.go +++ b/nomad/plan_apply.go @@ -149,6 +149,8 @@ func (s *Server) applyPlan(plan *structs.Plan, result *structs.PlanResult, snap for _, alloc := range req.Alloc { if alloc.CreateTime == 0 { alloc.CreateTime = now + } else { + alloc.ModifyTime = now } } diff --git a/nomad/plan_apply_test.go b/nomad/plan_apply_test.go index f4341d49c..6bf7181b9 100644 --- a/nomad/plan_apply_test.go +++ b/nomad/plan_apply_test.go @@ -226,6 +226,10 @@ func TestPlanApply_applyPlan(t *testing.T) { t.Fatalf("missing job") } + if out.ModifyTime <= 0 { + t.Fatalf("must have valid modify time but was %v", out.ModifyTime) + } + // Lookup the allocation out, err = s1.fsm.State().AllocByID(ws, alloc2.ID) if err != nil { diff --git a/nomad/state/state_store.go b/nomad/state/state_store.go index 62bb49480..0091055b3 100644 --- a/nomad/state/state_store.go +++ b/nomad/state/state_store.go @@ -1718,6 +1718,9 @@ func (s *StateStore) nestedUpdateAllocFromClient(txn *memdb.Txn, index uint64, a // Update the modify index copyAlloc.ModifyIndex = index + // Update the modify time + copyAlloc.ModifyTime = alloc.ModifyTime + if err := s.updateDeploymentWithAlloc(index, copyAlloc, exist, txn); err != nil { return fmt.Errorf("error updating deployment: %v", err) } diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 42e7db18d..fbe93de85 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -4605,6 +4605,9 @@ type Allocation struct { // CreateTime is the time the allocation has finished scheduling and been // verified by the plan applier. CreateTime int64 + + // ModifyTime is the time the allocation was last updated. + ModifyTime int64 } // Index returns the index of the allocation. If the allocation is from a task @@ -4746,6 +4749,7 @@ func (a *Allocation) Stub() *AllocListStub { CreateIndex: a.CreateIndex, ModifyIndex: a.ModifyIndex, CreateTime: a.CreateTime, + ModifyTime: a.ModifyTime, } } @@ -4767,6 +4771,7 @@ type AllocListStub struct { CreateIndex uint64 ModifyIndex uint64 CreateTime int64 + ModifyTime int64 } // AllocMetric is used to track various metrics while attempting