From a89ba5b5ca6df768571d578238ad3e603f78dae4 Mon Sep 17 00:00:00 2001 From: Fabian Reinartz Date: Tue, 21 Jun 2016 11:47:49 +0200 Subject: [PATCH] provider/mesh: allow timestamp equality tolerance --- provider/mesh/state.go | 20 ++++++++++++++++++-- provider/mesh/state_test.go | 24 +++++++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/provider/mesh/state.go b/provider/mesh/state.go index d80017fe..d618a968 100644 --- a/provider/mesh/state.go +++ b/provider/mesh/state.go @@ -196,6 +196,8 @@ func (st *silenceState) Encode() [][]byte { return [][]byte{buf.Bytes()} } +const timestampTolerance = time.Second + // silenceModAllowed checks whether silence a may be changed to silence b. // Returns an error stating the reason if not. // The silences are guaranteed to be valid. Silence a may be nil if b is a new. @@ -211,7 +213,16 @@ func silenceModAllowed(a, b *types.Silence, now time.Time) error { if a.ID != b.ID { return fmt.Errorf("IDs do not match") } - if !b.StartsAt.Equal(a.StartsAt) { + + almostEqual := func(s, t time.Time) bool { + d := s.Sub(t) + return d <= timestampTolerance && d >= -timestampTolerance + } + if almostEqual(a.StartsAt, b.StartsAt) { + // Always pick original timestamp so we cannot drift the time + // by spamming edits. + b.StartsAt = a.StartsAt + } else { if a.StartsAt.Before(now) { return fmt.Errorf("start time of active silence must not be modified") } @@ -219,7 +230,11 @@ func silenceModAllowed(a, b *types.Silence, now time.Time) error { return fmt.Errorf("start time cannot be moved into the past") } } - if !b.EndsAt.Equal(a.EndsAt) { + if almostEqual(a.EndsAt, b.EndsAt) { + // Always pick original timestamp so we cannot drift the time + // by spamming edits. + b.EndsAt = a.EndsAt + } else { if a.EndsAt.Before(now) { return fmt.Errorf("end time must not be modified for elapsed silence") } @@ -227,6 +242,7 @@ func silenceModAllowed(a, b *types.Silence, now time.Time) error { return fmt.Errorf("end time must not be set into the past") } } + if !a.Matchers.Equal(b.Matchers) { return fmt.Errorf("matchers must not be modified") } diff --git a/provider/mesh/state_test.go b/provider/mesh/state_test.go index 28c4fc8d..2d5762b5 100644 --- a/provider/mesh/state_test.go +++ b/provider/mesh/state_test.go @@ -374,6 +374,8 @@ func TestSilenceModAllowed(t *testing.T) { }, }, { + // Modify silence comment and creator and set not-yet started + // end time into future. a: &types.Silence{ ID: id1, Matchers: matchers, @@ -413,7 +415,27 @@ func TestSilenceModAllowed(t *testing.T) { Comment: "y", }, }, - + { + a: &types.Silence{ + ID: id1, + Matchers: matchers, + StartsAt: now.Add(-10 * time.Minute), + EndsAt: now.Add(-5 * time.Minute), + UpdatedAt: now.Add(-10 * time.Minute), + CreatedBy: "x", + Comment: "x", + }, + // Timestamp tolerance must be respected. + b: &types.Silence{ + ID: id1, + Matchers: matchers, + StartsAt: now.Add(-10*time.Minute + timestampTolerance), + EndsAt: now.Add(-5*time.Minute - timestampTolerance), + UpdatedAt: now, + CreatedBy: "x", + Comment: "x", + }, + }, { a: nil, b: &types.Silence{