/
governor.go
128 lines (103 loc) · 3.44 KB
/
governor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright (c) 2021, R.I. Pienaar and the Choria Project contributors
//
// SPDX-License-Identifier: Apache-2.0
package lifecycle
import (
"encoding/json"
"fmt"
)
// GovernorEvent is a io.choria.lifecycle.v1.governor event
//
// In addition to the usual required fields it requires a GovernorName(), GovernorSequence() and GovernorType() specified when producing this kind of event
type GovernorEvent struct {
basicEvent
Governor string `json:"governor"`
Sequence uint64 `json:"sequence"`
EventType GovernorEventType `json:"event_type"`
}
type GovernorEventType string
const (
// GovernorEnterEvent is when a Governor slot is obtained through active campaigning
GovernorEnterEvent GovernorEventType = "enter"
// GovernorExitEvent is when a slot is left, but not expired or evicted
GovernorExitEvent GovernorEventType = "exit"
// GovernorTimeoutEvent is when a slot could not be obtained after some time
GovernorTimeoutEvent GovernorEventType = "timeouts"
// GovernorEvictEvent is when a slot is evicted using a admin API
GovernorEvictEvent GovernorEventType = "eviction"
)
func init() {
eventTypes["governor"] = Governor
eventJSONParsers[Governor] = func(j []byte) (Event, error) {
return newGovernorEnterEventFromJSON(j)
}
eventFactories[Governor] = func(opts ...Option) Event {
return newGovernorEvent(opts...)
}
}
func newGovernorEvent(opts ...Option) *GovernorEvent {
event := &GovernorEvent{basicEvent: newBasicEvent("governor")}
for _, o := range opts {
o(event)
}
return event
}
func (g *GovernorEvent) SetEventType(stage GovernorEventType) error {
switch stage {
case GovernorEnterEvent, GovernorExitEvent, GovernorTimeoutEvent, GovernorEvictEvent:
g.EventType = stage
default:
return fmt.Errorf("invalid stage")
}
return nil
}
func (g *GovernorEvent) SetSequence(seq uint64) {
g.Sequence = seq
}
func (g *GovernorEvent) SetGovernor(name string) {
g.Governor = name
}
func (g *GovernorEvent) String() string {
switch g.EventType {
case GovernorExitEvent:
if g.Sequence > 0 {
return fmt.Sprintf("[governor] %s: vacated slot %d on %s", g.Ident, g.Sequence, g.Governor)
} else {
return fmt.Sprintf("[governor] %s: vacated %s", g.Ident, g.Governor)
}
case GovernorEnterEvent:
if g.Sequence > 0 {
return fmt.Sprintf("[governor] %s: obtained slot %d on %s", g.Ident, g.Sequence, g.Governor)
} else {
return fmt.Sprintf("[governor] %s: obtained slot on %s", g.Ident, g.Governor)
}
case GovernorTimeoutEvent:
return fmt.Sprintf("[governor] %s: failed to obtain a slot on %s", g.Ident, g.Governor)
case GovernorEvictEvent:
if g.Sequence > 0 {
return fmt.Sprintf("[governor] %s: evicted from slot %d on %s", g.Ident, g.Sequence, g.Governor)
} else {
return fmt.Sprintf("[governor] %s: evicted from %s", g.Ident, g.Governor)
}
default:
return fmt.Sprintf("[governor] %s: unknown stage on Governor %s", g.Ident, g.Governor)
}
}
func newGovernorEnterEventFromJSON(j []byte) (*GovernorEvent, error) {
event := &GovernorEvent{basicEvent: newBasicEvent("governor")}
err := json.Unmarshal(j, event)
if err != nil {
return nil, err
}
switch event.EventProtocol {
case "io.choria.lifecycle.v1.governor":
case "choria:lifecycle:governor:1":
event.EventProtocol = "io.choria.lifecycle.v1.governor"
default:
return nil, fmt.Errorf("invalid protocol '%s'", event.EventProtocol)
}
if event.Governor == "" {
return nil, fmt.Errorf("governor name is not set")
}
return event, nil
}