2023-08-30 02:00:09 +08:00
|
|
|
package dnsgraph
|
|
|
|
|
|
|
|
import "github.com/StackExchange/dnscontrol/v4/pkg/dnstree"
|
|
|
|
|
|
|
|
type edgeDirection uint8
|
|
|
|
|
|
|
|
const (
|
2023-12-12 05:24:11 +08:00
|
|
|
// IncomingEdge is an edge inbound.
|
2023-08-30 02:00:09 +08:00
|
|
|
IncomingEdge edgeDirection = iota
|
2023-12-12 05:24:11 +08:00
|
|
|
// OutgoingEdge is an edge outbound.
|
2023-08-30 02:00:09 +08:00
|
|
|
OutgoingEdge
|
|
|
|
)
|
|
|
|
|
2023-12-12 05:24:11 +08:00
|
|
|
// DNSGraphEdge an edge on the graph.
|
2023-08-30 02:00:09 +08:00
|
|
|
type DNSGraphEdge[T Graphable] struct {
|
|
|
|
Dependency Dependency
|
|
|
|
Node *DNSGraphNode[T]
|
|
|
|
Direction edgeDirection
|
|
|
|
}
|
|
|
|
|
2023-12-12 05:24:11 +08:00
|
|
|
// DNSGraphEdges a list of edges.
|
2023-08-30 02:00:09 +08:00
|
|
|
type DNSGraphEdges[T Graphable] []DNSGraphEdge[T]
|
|
|
|
|
2023-12-12 05:24:11 +08:00
|
|
|
// DNSGraphNode a node in the graph.
|
2023-08-30 02:00:09 +08:00
|
|
|
type DNSGraphNode[T Graphable] struct {
|
|
|
|
Data T
|
|
|
|
Edges DNSGraphEdges[T]
|
|
|
|
}
|
|
|
|
|
|
|
|
type dnsGraphNodes[T Graphable] []*DNSGraphNode[T]
|
|
|
|
|
2023-12-12 05:24:11 +08:00
|
|
|
// DNSGraph a graph.
|
2023-08-30 02:00:09 +08:00
|
|
|
type DNSGraph[T Graphable] struct {
|
|
|
|
All dnsGraphNodes[T]
|
|
|
|
Tree *dnstree.DomainTree[dnsGraphNodes[T]]
|
|
|
|
}
|
|
|
|
|
2023-12-12 05:24:11 +08:00
|
|
|
// CreateGraph returns a graph.
|
2023-08-30 02:00:09 +08:00
|
|
|
func CreateGraph[T Graphable](entries []T) *DNSGraph[T] {
|
|
|
|
graph := &DNSGraph[T]{
|
|
|
|
All: dnsGraphNodes[T]{},
|
|
|
|
Tree: dnstree.Create[dnsGraphNodes[T]](),
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, data := range entries {
|
|
|
|
graph.AddNode(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, sourceNode := range graph.All {
|
|
|
|
for _, dependency := range sourceNode.Data.GetDependencies() {
|
|
|
|
graph.AddEdge(sourceNode, dependency)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return graph
|
|
|
|
}
|
|
|
|
|
2023-12-12 05:24:11 +08:00
|
|
|
// RemoveNode removes a node from a graph.
|
2023-08-30 02:00:09 +08:00
|
|
|
func (graph *DNSGraph[T]) RemoveNode(toRemove *DNSGraphNode[T]) {
|
|
|
|
for _, edge := range toRemove.Edges {
|
|
|
|
edge.Node.Edges = edge.Node.Edges.RemoveNode(toRemove)
|
|
|
|
}
|
|
|
|
|
|
|
|
graph.All = graph.All.RemoveNode(toRemove)
|
|
|
|
|
|
|
|
nodes := graph.Tree.Get(toRemove.Data.GetName())
|
|
|
|
if nodes != nil {
|
|
|
|
nodes = nodes.RemoveNode(toRemove)
|
|
|
|
graph.Tree.Set(toRemove.Data.GetName(), nodes)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-12 05:24:11 +08:00
|
|
|
// AddNode adds a node to a graph.
|
2023-08-30 02:00:09 +08:00
|
|
|
func (graph *DNSGraph[T]) AddNode(data T) {
|
|
|
|
nodes := graph.Tree.Get(data.GetName())
|
|
|
|
node := &DNSGraphNode[T]{
|
|
|
|
Data: data,
|
|
|
|
Edges: DNSGraphEdges[T]{},
|
|
|
|
}
|
|
|
|
if nodes == nil {
|
|
|
|
nodes = dnsGraphNodes[T]{}
|
|
|
|
}
|
|
|
|
nodes = append(nodes, node)
|
|
|
|
|
|
|
|
graph.All = append(graph.All, node)
|
|
|
|
graph.Tree.Set(data.GetName(), nodes)
|
|
|
|
}
|
|
|
|
|
2023-12-12 05:24:11 +08:00
|
|
|
// AddEdge adds an edge to a graph.
|
2023-08-30 02:00:09 +08:00
|
|
|
func (graph *DNSGraph[T]) AddEdge(sourceNode *DNSGraphNode[T], dependency Dependency) {
|
|
|
|
destinationNodes := graph.Tree.Get(dependency.NameFQDN)
|
|
|
|
|
|
|
|
if destinationNodes == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, destinationNode := range destinationNodes {
|
|
|
|
if sourceNode == destinationNode {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if sourceNode.Edges.Contains(destinationNode, OutgoingEdge) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
sourceNode.Edges = append(sourceNode.Edges, DNSGraphEdge[T]{
|
|
|
|
Dependency: dependency,
|
|
|
|
Node: destinationNode,
|
|
|
|
Direction: OutgoingEdge,
|
|
|
|
})
|
|
|
|
|
|
|
|
destinationNode.Edges = append(destinationNode.Edges, DNSGraphEdge[T]{
|
|
|
|
Dependency: dependency,
|
|
|
|
Node: sourceNode,
|
|
|
|
Direction: IncomingEdge,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-12 05:24:11 +08:00
|
|
|
// RemoveNode removes a node from a graph.
|
2023-08-30 02:00:09 +08:00
|
|
|
func (nodes dnsGraphNodes[T]) RemoveNode(toRemove *DNSGraphNode[T]) dnsGraphNodes[T] {
|
|
|
|
var newNodes dnsGraphNodes[T]
|
|
|
|
|
|
|
|
for _, node := range nodes {
|
|
|
|
if node != toRemove {
|
|
|
|
newNodes = append(newNodes, node)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newNodes
|
|
|
|
}
|
|
|
|
|
2023-12-12 05:24:11 +08:00
|
|
|
// RemoveNode removes a node from a graph.
|
2023-08-30 02:00:09 +08:00
|
|
|
func (edges DNSGraphEdges[T]) RemoveNode(toRemove *DNSGraphNode[T]) DNSGraphEdges[T] {
|
|
|
|
var newEdges DNSGraphEdges[T]
|
|
|
|
|
|
|
|
for _, edge := range edges {
|
|
|
|
if edge.Node != toRemove {
|
|
|
|
newEdges = append(newEdges, edge)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newEdges
|
|
|
|
}
|
|
|
|
|
2023-12-12 05:24:11 +08:00
|
|
|
// Contains returns true if a node is in the graph AND is in that direction.
|
2023-08-30 02:00:09 +08:00
|
|
|
func (edges DNSGraphEdges[T]) Contains(toFind *DNSGraphNode[T], direction edgeDirection) bool {
|
|
|
|
|
|
|
|
for _, edge := range edges {
|
|
|
|
if edge.Node == toFind && edge.Direction == direction {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|