2022-12-09 12:00:18 +00:00
|
|
|
/*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package notify
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"git.st8l.com/luxolus/kdnotify/schema/notify/prio"
|
|
|
|
"git.st8l.com/luxolus/kdnotify/schema/notify/state"
|
|
|
|
"git.st8l.com/luxolus/kdnotify/schema/notify/ty"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Keepalived VRRP notify message
|
|
|
|
type VrrpMessage struct {
|
|
|
|
Message
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse the given line of text into a VrrpMessage if possible,
|
|
|
|
// erroring out if not.
|
|
|
|
func ParseVrrp(line string) (VrrpMessage, error) {
|
|
|
|
msg, err := ParseMessage(line)
|
|
|
|
if err != nil {
|
|
|
|
return VrrpMessage{}, fmt.Errorf("unable parse message from '%s': %w", line, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
vrrp, err := NewVrrp(msg)
|
|
|
|
if err != nil {
|
|
|
|
return vrrp, fmt.Errorf("unable parse vrrp from '%s': %w", line, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return vrrp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Upgrade a Message into a VrrpMessage that is guaranteed to be a valid VRRP message
|
|
|
|
func NewVrrp(m Message) (VrrpMessage, error) {
|
|
|
|
var v VrrpMessage
|
|
|
|
|
|
|
|
if !m.Type.IsVRRP() {
|
|
|
|
return v, fmt.Errorf("'%s' is not a valid VRRP message type", m.Type.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
if m.State == state.UNKNOWN {
|
|
|
|
return v, fmt.Errorf("unknown VRRP message state")
|
|
|
|
}
|
|
|
|
|
|
|
|
v.Type = m.Type
|
|
|
|
v.Instance = m.Instance
|
|
|
|
v.State = m.State
|
|
|
|
v.Priority = m.Priority
|
|
|
|
|
|
|
|
return v, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Keepalived notify message
|
|
|
|
type Message struct {
|
|
|
|
Type ty.Type
|
|
|
|
Instance string
|
|
|
|
State state.State
|
|
|
|
Priority prio.Priority
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new Message from its components
|
|
|
|
func New(t ty.Type, instance string, s state.State, p prio.Priority) Message {
|
|
|
|
return Message{
|
|
|
|
Type: t,
|
|
|
|
Instance: instance,
|
|
|
|
State: s,
|
|
|
|
Priority: p,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse a line into a Message, erroring out if the line format is invalid
|
|
|
|
func ParseMessage(line string) (Message, error) {
|
|
|
|
var m Message
|
|
|
|
|
|
|
|
line = strings.TrimSpace(line)
|
|
|
|
// $TYPE $INSTANCE $STATE $PRIORITY $REST...
|
|
|
|
pt := strings.SplitN(line, " ", 5)
|
|
|
|
l := len(pt)
|
|
|
|
|
|
|
|
// Priority is optional
|
|
|
|
if l < 3 {
|
|
|
|
return m, fmt.Errorf("unable to parse message from '%s': not enough fields", line)
|
|
|
|
}
|
|
|
|
|
|
|
|
m.Type = ty.ParseType(pt[0])
|
2022-12-10 16:53:02 +00:00
|
|
|
m.Instance = cleanInstance(pt[1])
|
2022-12-09 12:00:18 +00:00
|
|
|
m.State = state.ParseState(pt[2])
|
|
|
|
if l > 3 {
|
|
|
|
m.Priority = prio.ParsePriority(pt[3])
|
|
|
|
}
|
|
|
|
|
|
|
|
return m, nil
|
|
|
|
}
|
2022-12-10 16:53:02 +00:00
|
|
|
|
|
|
|
// Cleans up messy INSTANCE fields, which can contain many quotes when
|
|
|
|
// Keepalived sends them
|
|
|
|
func cleanInstance(instance string) string {
|
|
|
|
return strings.TrimSpace(strings.Trim(instance, `"'`))
|
|
|
|
}
|