diff --git a/probe/topology_tagger.go b/probe/topology_tagger.go index ce37e19a3..49dfc3bb3 100644 --- a/probe/topology_tagger.go +++ b/probe/topology_tagger.go @@ -16,10 +16,10 @@ func (topologyTagger) Name() string { return "Topology" } // Tag implements Tagger func (topologyTagger) Tag(r report.Report) (report.Report, error) { - for name, t := range r.TopologyMap() { + r.WalkNamedTopologies(func(name string, t *report.Topology) { for _, node := range t.Nodes { t.AddNode(node.WithTopology(name)) } - } + }) return r, nil } diff --git a/report/report.go b/report/report.go index c314e34a4..71a67456d 100644 --- a/report/report.go +++ b/report/report.go @@ -43,6 +43,26 @@ const ( ContainersKey = "containers" ) +// topologyNames are the names of all report topologies. +var topologyNames = []string{ + Endpoint, + Process, + Container, + ContainerImage, + Pod, + Service, + Deployment, + ReplicaSet, + DaemonSet, + StatefulSet, + CronJob, + Host, + Overlay, + ECSTask, + ECSService, + SwarmService, +} + // Report is the core data type. It's produced by probes, and consumed and // stored by apps. It's composed of multiple topologies, each representing // a different (related, but not equivalent) view of the network. @@ -226,28 +246,6 @@ func MakeReport() Report { } } -// TopologyMap gets a map from topology names to pointers to the respective topologies -func (r *Report) TopologyMap() map[string]*Topology { - return map[string]*Topology{ - Endpoint: &r.Endpoint, - Process: &r.Process, - Container: &r.Container, - ContainerImage: &r.ContainerImage, - Pod: &r.Pod, - Service: &r.Service, - Deployment: &r.Deployment, - ReplicaSet: &r.ReplicaSet, - DaemonSet: &r.DaemonSet, - StatefulSet: &r.StatefulSet, - CronJob: &r.CronJob, - Host: &r.Host, - Overlay: &r.Overlay, - ECSTask: &r.ECSTask, - ECSService: &r.ECSService, - SwarmService: &r.SwarmService, - } -} - // Copy returns a value copy of the report. func (r Report) Copy() Report { newReport := Report{ @@ -277,76 +275,82 @@ func (r Report) Merge(other Report) Report { // Topologies returns a slice of Topologies in this report func (r Report) Topologies() []Topology { - result := []Topology{} - r.WalkTopologies(func(t *Topology) { - result = append(result, *t) - }) + result := make([]Topology, len(topologyNames)) + for i, name := range topologyNames { + t, _ := r.Topology(name) + result[i] = t + } return result } // WalkTopologies iterates through the Topologies of the report, // potentially modifying them func (r *Report) WalkTopologies(f func(*Topology)) { - var dummy Report - r.WalkPairedTopologies(&dummy, func(t, _ *Topology) { f(t) }) + for _, name := range topologyNames { + f(r.topology(name)) + } +} + +// WalkNamedTopologies iterates through the Topologies of the report, +// potentially modifying them. +func (r *Report) WalkNamedTopologies(f func(string, *Topology)) { + for _, name := range topologyNames { + f(name, r.topology(name)) + } } // WalkPairedTopologies iterates through the Topologies of this and another report, // potentially modifying one or both. func (r *Report) WalkPairedTopologies(o *Report, f func(*Topology, *Topology)) { - f(&r.Endpoint, &o.Endpoint) - f(&r.Process, &o.Process) - f(&r.Container, &o.Container) - f(&r.ContainerImage, &o.ContainerImage) - f(&r.Pod, &o.Pod) - f(&r.Service, &o.Service) - f(&r.Deployment, &o.Deployment) - f(&r.ReplicaSet, &o.ReplicaSet) - f(&r.DaemonSet, &o.DaemonSet) - f(&r.StatefulSet, &o.StatefulSet) - f(&r.CronJob, &o.CronJob) - f(&r.Host, &o.Host) - f(&r.Overlay, &o.Overlay) - f(&r.ECSTask, &o.ECSTask) - f(&r.ECSService, &o.ECSService) - f(&r.SwarmService, &o.SwarmService) + for _, name := range topologyNames { + f(r.topology(name), o.topology(name)) + } } -// Topology gets a topology by name -func (r Report) Topology(name string) (Topology, bool) { +// topology returns a reference to one of the report's topologies, +// selected by name. +func (r *Report) topology(name string) *Topology { switch name { case Endpoint: - return r.Endpoint, true + return &r.Endpoint case Process: - return r.Process, true + return &r.Process case Container: - return r.Container, true + return &r.Container case ContainerImage: - return r.ContainerImage, true + return &r.ContainerImage case Pod: - return r.Pod, true + return &r.Pod case Service: - return r.Service, true + return &r.Service case Deployment: - return r.Deployment, true + return &r.Deployment case ReplicaSet: - return r.ReplicaSet, true + return &r.ReplicaSet case DaemonSet: - return r.DaemonSet, true + return &r.DaemonSet case StatefulSet: - return r.StatefulSet, true + return &r.StatefulSet case CronJob: - return r.CronJob, true + return &r.CronJob case Host: - return r.Host, true + return &r.Host case Overlay: - return r.Overlay, true + return &r.Overlay case ECSTask: - return r.ECSTask, true + return &r.ECSTask case ECSService: - return r.ECSService, true + return &r.ECSService case SwarmService: - return r.SwarmService, true + return &r.SwarmService + } + return nil +} + +// Topology returns one of the report's topologies, selected by name. +func (r Report) Topology(name string) (Topology, bool) { + if t := r.topology(name); t != nil { + return *t, true } return Topology{}, false }