refactor(ish): reduce number of topology lists

Having 6 lists of topolgies in the same file is a bit much:

1. consts for topology names
2. Report type definition
3. MakeReport() Report initialisation
4. Report.Topology(name) lookup
5. Report.TopologyMap() mapping of names to topology references
6. Report.WalkPairedTopologies() iterator over topology references

We get rid of 5 and 6 by introducing a topologyNames slice. So we
are down to 5.

We replace Report.TopologyMap() with a new function,
WalkNamedTopologies, that uses topologyNames. WalkPairedTopologies()
is updated to operate in a similar fashion. Likewise for
WalkTopologies() and Topologies() - these were previously calling
Walk[Paired]Topologies, but it is clearer to simply implement them
directly.
This commit is contained in:
Matthias Radestock
2017-12-24 20:20:59 +00:00
parent 583e81d733
commit 9419c3ef5c
2 changed files with 68 additions and 64 deletions

View File

@@ -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
}

View File

@@ -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
}