provider/mesh: extract silence deletion into state
This commit is contained in:
parent
9039a3cffa
commit
3d350a34b5
|
@ -2,7 +2,6 @@ package mesh
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/alertmanager/provider"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
|
@ -161,31 +160,16 @@ func (s *Silences) Set(sil *types.Silence) (uuid.UUID, error) {
|
|||
}
|
||||
|
||||
func (s *Silences) Del(id uuid.UUID) error {
|
||||
s.st.mtx.RLock()
|
||||
sil, ok := s.st.m[id]
|
||||
s.st.mtx.RUnlock()
|
||||
if !ok {
|
||||
return provider.ErrNotFound
|
||||
sil, err := s.st.del(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
now := time.Now()
|
||||
if sil.EndsAt.Before(now) {
|
||||
return fmt.Errorf("silence already ended")
|
||||
}
|
||||
// Silences are immutable by contract so we create a completely
|
||||
// new object instead.
|
||||
newSil := *sil
|
||||
newSil.UpdatedAt = now
|
||||
newSil.EndsAt = now
|
||||
|
||||
if err := newSil.Init(); err != nil {
|
||||
return fmt.Errorf("silence init: %s", err)
|
||||
}
|
||||
update := &silenceState{
|
||||
m: map[uuid.UUID]*types.Silence{
|
||||
newSil.ID: &newSil,
|
||||
sil.ID: sil,
|
||||
},
|
||||
}
|
||||
s.st.Merge(update)
|
||||
s.send.GossipBroadcast(update)
|
||||
|
||||
return nil
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/alertmanager/provider"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/satori/go.uuid"
|
||||
"github.com/weaveworks/mesh"
|
||||
|
@ -133,11 +134,10 @@ func (st *silenceState) Encode() [][]byte {
|
|||
|
||||
// silenceModAllowed checks whether silence a may be changed to silence b.
|
||||
// Returns an error stating the reason if not.
|
||||
func (st *silenceState) silenceModAllowed(a, b *types.Silence) error {
|
||||
func silenceModAllowed(a, b *types.Silence, now time.Time) error {
|
||||
if !b.StartsAt.Equal(a.StartsAt) {
|
||||
return fmt.Errorf("silence start time must not be modified")
|
||||
}
|
||||
now := st.now()
|
||||
if a.EndsAt.Before(now) {
|
||||
return fmt.Errorf("end time must not be modified for elapsed silence")
|
||||
}
|
||||
|
@ -154,7 +154,8 @@ func (st *silenceState) set(s *types.Silence) error {
|
|||
st.mtx.Lock()
|
||||
defer st.mtx.Unlock()
|
||||
|
||||
s.UpdatedAt = st.now()
|
||||
now := st.now()
|
||||
s.UpdatedAt = now
|
||||
|
||||
if err := s.Validate(); err != nil {
|
||||
return err
|
||||
|
@ -165,13 +166,39 @@ func (st *silenceState) set(s *types.Silence) error {
|
|||
st.m[s.ID] = s
|
||||
return nil
|
||||
}
|
||||
if err := st.silenceModAllowed(prev, s); err != nil {
|
||||
if err := silenceModAllowed(prev, s, now); err != nil {
|
||||
return err
|
||||
}
|
||||
st.m[s.ID] = s
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *silenceState) del(id uuid.UUID) (*types.Silence, error) {
|
||||
st.mtx.Lock()
|
||||
defer st.mtx.Unlock()
|
||||
|
||||
prev, ok := st.m[id]
|
||||
if !ok {
|
||||
return nil, provider.ErrNotFound
|
||||
}
|
||||
// Silences are immutable by contract so we create a
|
||||
// shallow copy.
|
||||
sil := *prev
|
||||
now := st.now()
|
||||
sil.UpdatedAt = now
|
||||
sil.EndsAt = now
|
||||
|
||||
if err := sil.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := silenceModAllowed(prev, &sil, now); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
st.m[sil.ID] = &sil
|
||||
return &sil, nil
|
||||
}
|
||||
|
||||
func (st *silenceState) Merge(other mesh.GossipData) mesh.GossipData {
|
||||
o := other.(*silenceState)
|
||||
o.mtx.RLock()
|
||||
|
|
|
@ -16,6 +16,7 @@ package types
|
|||
import (
|
||||
"fmt"
|
||||
"hash/fnv"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -276,6 +277,7 @@ func (s *Silence) Init() error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
sort.Sort(s.Matchers)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue