From 69ceb4eab3494f5e181b71b633eba294d437a8a4 Mon Sep 17 00:00:00 2001 From: Bazaah Date: Fri, 9 Dec 2022 12:00:18 +0000 Subject: [PATCH] schema/notify: Message, VrrpMessage The in-memory representation of a keepalived notify event. Message is not strictly accurate for non VRRP events, but as we don't care about IPVS events now this is fine for our purposes. We do explicitly provide a VrrpMessage type however which is guaranteed to be a VRRP event. --- schema/notify/message.go | 99 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 schema/notify/message.go 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 +}