From eb381f167d11b1804b9630620e1527ec9c39d609 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Mon, 14 Oct 2019 16:14:21 +0000 Subject: [PATCH] refactor: move Report backwards-compatibility code into its own file Makes report.go a little easier to read. --- report/backcompat.go | 102 +++++++++++++++++++++++++++++++++++++++++++ report/report.go | 99 ----------------------------------------- 2 files changed, 102 insertions(+), 99 deletions(-) create mode 100644 report/backcompat.go diff --git a/report/backcompat.go b/report/backcompat.go new file mode 100644 index 0000000000..28ca45932c --- /dev/null +++ b/report/backcompat.go @@ -0,0 +1,102 @@ +package report + +// Backwards-compatibility: code to read older reports and convert + +// Upgrade returns a new report based on a report received from the old probe. +// +func (r Report) Upgrade() Report { + return r.upgradePodNodes().upgradeNamespaces().upgradeDNSRecords() +} + +func (r Report) upgradePodNodes() Report { + // At the same time the probe stopped reporting replicasets, + // it also started reporting deployments as pods' parents + if len(r.ReplicaSet.Nodes) == 0 { + return r + } + + // For each pod, we check for any replica sets, and merge any deployments they point to + // into a replacement Parents value. + nodes := Nodes{} + for podID, pod := range r.Pod.Nodes { + if replicaSetIDs, ok := pod.Parents.Lookup(ReplicaSet); ok { + newParents := pod.Parents.Delete(ReplicaSet) + for _, replicaSetID := range replicaSetIDs { + if replicaSet, ok := r.ReplicaSet.Nodes[replicaSetID]; ok { + if deploymentIDs, ok := replicaSet.Parents.Lookup(Deployment); ok { + newParents = newParents.Add(Deployment, deploymentIDs) + } + } + } + // newParents contains a copy of the current parents without replicasets, + // PruneParents().WithParents() ensures replicasets are actually deleted + pod = pod.PruneParents().WithParents(newParents) + } + nodes[podID] = pod + } + r.Pod.Nodes = nodes + + return r +} + +func (r Report) upgradeNamespaces() Report { + if len(r.Namespace.Nodes) > 0 { + return r + } + + namespaces := map[string]struct{}{} + for _, t := range []Topology{r.Pod, r.Service, r.Deployment, r.DaemonSet, r.StatefulSet, r.CronJob} { + for _, n := range t.Nodes { + if state, ok := n.Latest.Lookup(KubernetesState); ok && state == "deleted" { + continue + } + if namespace, ok := n.Latest.Lookup(KubernetesNamespace); ok { + namespaces[namespace] = struct{}{} + } + } + } + + nodes := make(Nodes, len(namespaces)) + for ns := range namespaces { + // Namespace ID: + // Probes did not use to report namespace ids, but since creating a report node requires an id, + // the namespace name, which is unique, is passed to `MakeNamespaceNodeID` + namespaceID := MakeNamespaceNodeID(ns) + nodes[namespaceID] = MakeNodeWith(namespaceID, map[string]string{KubernetesName: ns}) + } + r.Namespace.Nodes = nodes + + return r +} + +func (r Report) upgradeDNSRecords() Report { + // For release 1.11.6, probes accidentally sent DNS records labeled "nodes". + // Translate the incorrect version here. Accident was in commit 951629a. + if len(r.BugDNS) > 0 { + r.DNS = r.BugDNS + r.BugDNS = nil + } + if len(r.DNS) > 0 { + return r + } + dns := make(DNSRecords) + for endpointID, endpoint := range r.Endpoint.Nodes { + _, addr, _, ok := ParseEndpointNodeID(endpointID) + snoopedNames, foundS := endpoint.Sets.Lookup(SnoopedDNSNames) + reverseNames, foundR := endpoint.Sets.Lookup(ReverseDNSNames) + if ok && (foundS || foundR) { + // Add address and names to report-level map + if existing, found := dns[addr]; found { + var sUnchanged, rUnchanged bool + snoopedNames, sUnchanged = snoopedNames.Merge(existing.Forward) + reverseNames, rUnchanged = reverseNames.Merge(existing.Reverse) + if sUnchanged && rUnchanged { + continue + } + } + dns[addr] = DNSRecord{Forward: snoopedNames, Reverse: reverseNames} + } + } + r.DNS = dns + return r +} diff --git a/report/report.go b/report/report.go index e47800b834..38c502b165 100644 --- a/report/report.go +++ b/report/report.go @@ -478,105 +478,6 @@ func (r Report) DropTopologiesOver(limit int) Report { return r } -// Upgrade returns a new report based on a report received from the old probe. -// -func (r Report) Upgrade() Report { - return r.upgradePodNodes().upgradeNamespaces().upgradeDNSRecords() -} - -func (r Report) upgradePodNodes() Report { - // At the same time the probe stopped reporting replicasets, - // it also started reporting deployments as pods' parents - if len(r.ReplicaSet.Nodes) == 0 { - return r - } - - // For each pod, we check for any replica sets, and merge any deployments they point to - // into a replacement Parents value. - nodes := Nodes{} - for podID, pod := range r.Pod.Nodes { - if replicaSetIDs, ok := pod.Parents.Lookup(ReplicaSet); ok { - newParents := pod.Parents.Delete(ReplicaSet) - for _, replicaSetID := range replicaSetIDs { - if replicaSet, ok := r.ReplicaSet.Nodes[replicaSetID]; ok { - if deploymentIDs, ok := replicaSet.Parents.Lookup(Deployment); ok { - newParents = newParents.Add(Deployment, deploymentIDs) - } - } - } - // newParents contains a copy of the current parents without replicasets, - // PruneParents().WithParents() ensures replicasets are actually deleted - pod = pod.PruneParents().WithParents(newParents) - } - nodes[podID] = pod - } - r.Pod.Nodes = nodes - - return r -} - -func (r Report) upgradeNamespaces() Report { - if len(r.Namespace.Nodes) > 0 { - return r - } - - namespaces := map[string]struct{}{} - for _, t := range []Topology{r.Pod, r.Service, r.Deployment, r.DaemonSet, r.StatefulSet, r.CronJob} { - for _, n := range t.Nodes { - if state, ok := n.Latest.Lookup(KubernetesState); ok && state == "deleted" { - continue - } - if namespace, ok := n.Latest.Lookup(KubernetesNamespace); ok { - namespaces[namespace] = struct{}{} - } - } - } - - nodes := make(Nodes, len(namespaces)) - for ns := range namespaces { - // Namespace ID: - // Probes did not use to report namespace ids, but since creating a report node requires an id, - // the namespace name, which is unique, is passed to `MakeNamespaceNodeID` - namespaceID := MakeNamespaceNodeID(ns) - nodes[namespaceID] = MakeNodeWith(namespaceID, map[string]string{KubernetesName: ns}) - } - r.Namespace.Nodes = nodes - - return r -} - -func (r Report) upgradeDNSRecords() Report { - // For release 1.11.6, probes accidentally sent DNS records labeled "nodes". - // Translate the incorrect version here. Accident was in commit 951629a. - if len(r.BugDNS) > 0 { - r.DNS = r.BugDNS - r.BugDNS = nil - } - if len(r.DNS) > 0 { - return r - } - dns := make(DNSRecords) - for endpointID, endpoint := range r.Endpoint.Nodes { - _, addr, _, ok := ParseEndpointNodeID(endpointID) - snoopedNames, foundS := endpoint.Sets.Lookup(SnoopedDNSNames) - reverseNames, foundR := endpoint.Sets.Lookup(ReverseDNSNames) - if ok && (foundS || foundR) { - // Add address and names to report-level map - if existing, found := dns[addr]; found { - var sUnchanged, rUnchanged bool - snoopedNames, sUnchanged = snoopedNames.Merge(existing.Forward) - reverseNames, rUnchanged = reverseNames.Merge(existing.Reverse) - if sUnchanged && rUnchanged { - continue - } - } - dns[addr] = DNSRecord{Forward: snoopedNames, Reverse: reverseNames} - } - } - r.DNS = dns - return r -} - // Summary returns a human-readable string summarising the contents, for diagnostic purposes func (r Report) Summary() string { ret := ""