kdnotify/schema/notify/message.go
Paul Stemmet c277b1e813
schema/notify: strip quotes and whitespace from INSTANCE fields
Keepalived returns dirty instance names, containing any and all quotes
from the declaration in keepalived.conf, plus an additional pair of
double quotes.

Here we strip those out, as they will just cause confusion and make it
difficult to properly match of instances in WatchRules.

As an demonstration observed from keepalived (v2.2.7):

| .conf line    | notify INSTANCE |
| -             | -               |
| my_instance   | "my_instance"   |
| 'my.instance' | "'my.instance'" |
| "my.instance" | ""my.instance"" |

After this commit, each will have all of its quotes stripped

Closes: #1
2022-12-10 16:53:02 +00:00

106 lines
2.4 KiB
Go

/*
* 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 = cleanInstance(pt[1])
m.State = state.ParseState(pt[2])
if l > 3 {
m.Priority = prio.ParsePriority(pt[3])
}
return m, nil
}
// 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, `"'`))
}