Use non-persistent Salter for logging test message (#22308)

* use non-persistent Salter for logging test message

* adjust tests based on code changes to ProcessManual

* suggestion for log test message fix (#22320)

* clean up test code and fix misnamed elements

---------

Co-authored-by: Peter Wilson <peter.wilson@hashicorp.com>
This commit is contained in:
Marc Boudreau
2023-08-14 11:00:49 -04:00
committed by GitHub
parent ab9f0808e0
commit d66fdb4dfd
4 changed files with 143 additions and 59 deletions

View File

@@ -580,3 +580,13 @@ func doElideListResponseData(data map[string]interface{}) {
} }
} }
} }
// newTemporaryEntryFormatter creates a cloned EntryFormatter instance with a non-persistent Salter.
func newTemporaryEntryFormatter(n *EntryFormatter) *EntryFormatter {
return &EntryFormatter{
salter: &nonPersistentSalt{},
headerFormatter: n.headerFormatter,
config: n.config,
prefix: n.prefix,
}
}

View File

@@ -23,8 +23,8 @@ func ProcessManual(ctx context.Context, data *logical.LogInput, ids []eventlogge
switch { switch {
case data == nil: case data == nil:
return errors.New("data cannot be nil") return errors.New("data cannot be nil")
case len(ids) == 0: case len(ids) < 2:
return errors.New("ids are required") return errors.New("minimum of 2 ids are required")
case nodes == nil: case nodes == nil:
return errors.New("nodes cannot be nil") return errors.New("nodes cannot be nil")
case len(nodes) == 0: case len(nodes) == 0:
@@ -50,16 +50,26 @@ func ProcessManual(ctx context.Context, data *logical.LogInput, ids []eventlogge
var lastSeen eventlogger.NodeType var lastSeen eventlogger.NodeType
// Process nodes data order, updating the event with the result. // Process nodes in order, updating the event with the result.
// This means we *should* do: // This means we *should* do:
// 1. formatter // 1. formatter (temporary)
// 2. sink // 2. sink
for _, id := range ids { for _, id := range ids {
node, ok := nodes[id] node, ok := nodes[id]
if !ok { if !ok {
return fmt.Errorf("node not found: %v", id) return fmt.Errorf("node not found: %v", id)
} }
e, err = node.Process(ctx, e)
switch node.Type() {
case eventlogger.NodeTypeFormatter:
// Use a temporary formatter node which doesn't persist its salt anywhere.
if formatNode, ok := node.(*EntryFormatter); ok && formatNode != nil {
e, err = newTemporaryEntryFormatter(formatNode).Process(ctx, e)
}
default:
e, err = node.Process(ctx, e)
}
if err != nil { if err != nil {
return err return err
} }

View File

@@ -26,10 +26,10 @@ func TestProcessManual_NilData(t *testing.T) {
var ids []eventlogger.NodeID var ids []eventlogger.NodeID
nodes := make(map[eventlogger.NodeID]eventlogger.Node) nodes := make(map[eventlogger.NodeID]eventlogger.Node)
// Filter node // Formatter node
filterId, filterNode := newFilterNode(t) formatterId, formatterNode := newFormatterNode(t)
ids = append(ids, filterId) ids = append(ids, formatterId)
nodes[filterId] = filterNode nodes[formatterId] = formatterNode
// Sink node // Sink node
sinkId, sinkNode := newSinkNode(t) sinkId, sinkNode := newSinkNode(t)
@@ -41,29 +41,48 @@ func TestProcessManual_NilData(t *testing.T) {
require.EqualError(t, err, "data cannot be nil") require.EqualError(t, err, "data cannot be nil")
} }
// TestProcessManual_NoIds tests ProcessManual when no IDs are supplied // TestProcessManual_BadIDs tests ProcessManual when different bad values are
func TestProcessManual_NoIds(t *testing.T) { // supplied for the ID parameter.
t.Parallel() func TestProcessManual_BadIDs(t *testing.T) {
tests := map[string]struct {
IDs []eventlogger.NodeID
ExpectedErrorMessage string
}{
"nil": {
IDs: nil,
ExpectedErrorMessage: "minimum of 2 ids are required",
},
"one": {
IDs: []eventlogger.NodeID{"1"},
ExpectedErrorMessage: "minimum of 2 ids are required",
},
}
var ids []eventlogger.NodeID for name, tc := range tests {
nodes := make(map[eventlogger.NodeID]eventlogger.Node) name := name
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
nodes := make(map[eventlogger.NodeID]eventlogger.Node)
// Filter node // Formatter node
filterId, filterNode := newFilterNode(t) formatterId, formatterNode := newFormatterNode(t)
nodes[filterId] = filterNode nodes[formatterId] = formatterNode
// Sink node // Sink node
sinkId, sinkNode := newSinkNode(t) sinkId, sinkNode := newSinkNode(t)
nodes[sinkId] = sinkNode nodes[sinkId] = sinkNode
// Data // Data
requestId, err := uuid.GenerateUUID() requestId, err := uuid.GenerateUUID()
require.NoError(t, err) require.NoError(t, err)
data := newData(requestId) data := newData(requestId)
err = ProcessManual(namespace.RootContext(context.Background()), data, ids, nodes) err = ProcessManual(namespace.RootContext(context.Background()), data, tc.IDs, nodes)
require.Error(t, err) require.Error(t, err)
require.EqualError(t, err, "ids are required") require.EqualError(t, err, tc.ExpectedErrorMessage)
})
}
} }
// TestProcessManual_NoNodes tests ProcessManual when no nodes are supplied. // TestProcessManual_NoNodes tests ProcessManual when no nodes are supplied.
@@ -73,9 +92,9 @@ func TestProcessManual_NoNodes(t *testing.T) {
var ids []eventlogger.NodeID var ids []eventlogger.NodeID
nodes := make(map[eventlogger.NodeID]eventlogger.Node) nodes := make(map[eventlogger.NodeID]eventlogger.Node)
// Filter node // Formatter node
filterId, _ := newFilterNode(t) formatterId, _ := newFormatterNode(t)
ids = append(ids, filterId) ids = append(ids, formatterId)
// Sink node // Sink node
sinkId, _ := newSinkNode(t) sinkId, _ := newSinkNode(t)
@@ -99,10 +118,10 @@ func TestProcessManual_IdNodeMismatch(t *testing.T) {
var ids []eventlogger.NodeID var ids []eventlogger.NodeID
nodes := make(map[eventlogger.NodeID]eventlogger.Node) nodes := make(map[eventlogger.NodeID]eventlogger.Node)
// Filter node // Formatter node
filterId, filterNode := newFilterNode(t) formatterId, formatterNode := newFormatterNode(t)
ids = append(ids, filterId) ids = append(ids, formatterId)
nodes[filterId] = filterNode nodes[formatterId] = formatterNode
// Sink node // Sink node
sinkId, _ := newSinkNode(t) sinkId, _ := newSinkNode(t)
@@ -118,18 +137,46 @@ func TestProcessManual_IdNodeMismatch(t *testing.T) {
require.ErrorContains(t, err, "node not found: ") require.ErrorContains(t, err, "node not found: ")
} }
// TestProcessManual_LastNodeNotSink tests ProcessManual when the last node (by ID) // TestProcessManual_NotEnoughNodes tests ProcessManual when there is only one
// is not an eventlogger.NodeTypeSink. // node provided.
func TestProcessManual_NotEnoughNodes(t *testing.T) {
t.Parallel()
var ids []eventlogger.NodeID
nodes := make(map[eventlogger.NodeID]eventlogger.Node)
// Formatter node
formatterId, formatterNode := newFormatterNode(t)
ids = append(ids, formatterId)
nodes[formatterId] = formatterNode
// Data
requestId, err := uuid.GenerateUUID()
require.NoError(t, err)
data := newData(requestId)
err = ProcessManual(namespace.RootContext(context.Background()), data, ids, nodes)
require.Error(t, err)
require.EqualError(t, err, "minimum of 2 ids are required")
}
// TestProcessManual_LastNodeNotSink tests ProcessManual when the last node is
// not a Sink node.
func TestProcessManual_LastNodeNotSink(t *testing.T) { func TestProcessManual_LastNodeNotSink(t *testing.T) {
t.Parallel() t.Parallel()
var ids []eventlogger.NodeID var ids []eventlogger.NodeID
nodes := make(map[eventlogger.NodeID]eventlogger.Node) nodes := make(map[eventlogger.NodeID]eventlogger.Node)
// Filter node // Formatter node
filterId, filterNode := newFilterNode(t) formatterId, formatterNode := newFormatterNode(t)
ids = append(ids, filterId) ids = append(ids, formatterId)
nodes[filterId] = filterNode nodes[formatterId] = formatterNode
// Another Formatter node
formatterId, formatterNode = newFormatterNode(t)
ids = append(ids, formatterId)
nodes[formatterId] = formatterNode
// Data // Data
requestId, err := uuid.GenerateUUID() requestId, err := uuid.GenerateUUID()
@@ -149,10 +196,10 @@ func TestProcessManual(t *testing.T) {
var ids []eventlogger.NodeID var ids []eventlogger.NodeID
nodes := make(map[eventlogger.NodeID]eventlogger.Node) nodes := make(map[eventlogger.NodeID]eventlogger.Node)
// Filter node // Formatter node
filterId, filterNode := newFilterNode(t) formatterId, formatterNode := newFormatterNode(t)
ids = append(ids, filterId) ids = append(ids, formatterId)
nodes[filterId] = filterNode nodes[formatterId] = formatterNode
// Sink node // Sink node
sinkId, sinkNode := newSinkNode(t) sinkId, sinkNode := newSinkNode(t)
@@ -168,20 +215,6 @@ func TestProcessManual(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
} }
// newFilterNode creates a new UUID and EntryFormatter (filter node).
func newFilterNode(t *testing.T) (eventlogger.NodeID, *EntryFormatter) {
t.Helper()
filterId, err := event.GenerateNodeID()
require.NoError(t, err)
cfg, err := NewFormatterConfig()
require.NoError(t, err)
filterNode, err := NewEntryFormatter(cfg, newStaticSalt(t))
require.NoError(t, err)
return filterId, filterNode
}
// newSinkNode creates a new UUID and NoopSink (sink node). // newSinkNode creates a new UUID and NoopSink (sink node).
func newSinkNode(t *testing.T) (eventlogger.NodeID, *event.NoopSink) { func newSinkNode(t *testing.T) (eventlogger.NodeID, *event.NoopSink) {
t.Helper() t.Helper()
@@ -193,6 +226,37 @@ func newSinkNode(t *testing.T) (eventlogger.NodeID, *event.NoopSink) {
return sinkId, sinkNode return sinkId, sinkNode
} }
// TestFormatter is a trivial implementation of the eventlogger.Node interface
// used as a place-holder for Formatter nodes in tests.
type TestFormatter struct{}
// Process trivially formats the event by storing "test" as a byte slice under
// the test format type.
func (f *TestFormatter) Process(_ context.Context, e *eventlogger.Event) (*eventlogger.Event, error) {
e.FormattedAs("test", []byte("test"))
return e, nil
}
// Reopen does nothing.
func (f *TestFormatter) Reopen() error {
return nil
}
// Type returns the eventlogger.NodeTypeFormatter type.
func (f *TestFormatter) Type() eventlogger.NodeType {
return eventlogger.NodeTypeFormatter
}
// newFormatterNode creates a new TestFormatter (formatter node).
func newFormatterNode(t *testing.T) (eventlogger.NodeID, *TestFormatter) {
nodeId, err := event.GenerateNodeID()
require.NoError(t, err)
node := &TestFormatter{}
return nodeId, node
}
// newData creates a sample logical.LogInput to be used as data for tests. // newData creates a sample logical.LogInput to be used as data for tests.
func newData(id string) *logical.LogInput { func newData(id string) *logical.LogInput {
return &logical.LogInput{ return &logical.LogInput{

View File

@@ -257,7 +257,7 @@ type Namespace struct {
Path string `json:"path,omitempty"` Path string `json:"path,omitempty"`
} }
// nonPersistentSalt is used for obtaining a salt that is // nonPersistentSalt is used for obtaining a salt that is not persisted.
type nonPersistentSalt struct{} type nonPersistentSalt struct{}
// Backend interface must be implemented for an audit // Backend interface must be implemented for an audit