github.com/rajeev159/opa@v0.45.0/topdown/lineage/lineage.go (about)

     1  // Copyright 2019 The OPA Authors.  All rights reserved.
     2  // Use of this source code is governed by an Apache2
     3  // license that can be found in the LICENSE file.
     4  
     5  package lineage
     6  
     7  import (
     8  	"github.com/open-policy-agent/opa/topdown"
     9  )
    10  
    11  // Notes returns a filtered trace that contains Note events and context to
    12  // understand where the Note was emitted.
    13  func Notes(trace []*topdown.Event) []*topdown.Event {
    14  	return Filter(trace, func(event *topdown.Event) bool {
    15  		return event.Op == topdown.NoteOp
    16  	})
    17  }
    18  
    19  // Fails returns a filtered trace that contains Fail events and context to
    20  // understand where the Fail occurred.
    21  func Fails(trace []*topdown.Event) []*topdown.Event {
    22  	return Filter(trace, func(event *topdown.Event) bool {
    23  		return event.Op == topdown.FailOp
    24  	})
    25  }
    26  
    27  // Filter will filter a given trace using the specified filter function. The
    28  // filtering function should return true for events that should be kept, false
    29  // for events that should be filtered out.
    30  func Filter(trace []*topdown.Event, filter func(*topdown.Event) bool) (result []*topdown.Event) {
    31  
    32  	qids := map[uint64]*topdown.Event{}
    33  
    34  	for _, event := range trace {
    35  
    36  		if filter(event) {
    37  			// Path will end with the Note event.
    38  			path := []*topdown.Event{event}
    39  
    40  			// Construct path of recorded Enter/Redo events that lead to the
    41  			// Note event. The path is constructed in reverse order by iterating
    42  			// backwards through the Enter/Redo events from the Note event.
    43  			curr := qids[event.QueryID]
    44  			var prev *topdown.Event
    45  
    46  			for curr != nil && curr != prev {
    47  				path = append(path, curr)
    48  				prev = curr
    49  				curr = qids[curr.ParentID]
    50  			}
    51  
    52  			// Add the path to the result, reversing it in the process.
    53  			for i := len(path) - 1; i >= 0; i-- {
    54  				result = append(result, path[i])
    55  			}
    56  
    57  			qids = map[uint64]*topdown.Event{}
    58  		}
    59  
    60  		if event.Op == topdown.EnterOp || event.Op == topdown.RedoOp {
    61  			if event.HasRule() || event.HasBody() {
    62  				qids[event.QueryID] = event
    63  			}
    64  		}
    65  	}
    66  
    67  	return result
    68  }