diff --git a/schema/notify/message.go b/schema/notify/message.go new file mode 100644 index 0000000..226c4b4 --- /dev/null +++ b/schema/notify/message.go @@ -0,0 +1,99 @@ +/* + * 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]) + m.Instance = pt[1] + m.State = state.ParseState(pt[2]) + if l > 3 { + m.Priority = prio.ParsePriority(pt[3]) + } + + return m, nil +}