func captureContainerID(f func(string, xfer.Request) xfer.Response) func(xfer.Request) xfer.Response { return func(req xfer.Request) xfer.Response { containerID, ok := report.ParseContainerNodeID(req.NodeID) if !ok { return xfer.ResponseErrorf("Invalid ID: %s", req.NodeID) } return f(containerID, req) } }
func (r *Reporter) containerTopology(localAddrs []net.IP) report.Topology { result := report.MakeTopology(). WithMetadataTemplates(ContainerMetadataTemplates). WithMetricTemplates(ContainerMetricTemplates). WithTableTemplates(ContainerTableTemplates) result.Controls.AddControls(ContainerControls) metadata := map[string]string{report.ControlProbeID: r.probeID} nodes := []report.Node{} r.registry.WalkContainers(func(c Container) { nodes = append(nodes, c.GetNode().WithLatests(metadata)) }) // Copy the IP addresses from other containers where they share network // namespaces & deal with containers in the host net namespace. This // is recursive to deal with people who decide to be clever. { hostNetworkInfo := report.EmptySets if hostIPs, err := getLocalIPs(); err == nil { hostIPsWithScopes := addScopeToIPs(r.hostID, hostIPs) hostNetworkInfo = hostNetworkInfo. Add(ContainerIPs, report.MakeStringSet(hostIPs...)). Add(ContainerIPsWithScopes, report.MakeStringSet(hostIPsWithScopes...)) } var networkInfo func(prefix string) report.Sets networkInfo = func(prefix string) report.Sets { container, ok := r.registry.GetContainerByPrefix(prefix) if !ok { return report.EmptySets } networkMode, ok := container.NetworkMode() if ok && strings.HasPrefix(networkMode, "container:") { return networkInfo(networkMode[10:]) } else if ok && networkMode == NetworkModeHost { return hostNetworkInfo } return container.NetworkInfo(localAddrs) } for _, node := range nodes { id, ok := report.ParseContainerNodeID(node.ID) if !ok { continue } networkInfo := networkInfo(id) result.AddNode(node.WithSets(networkInfo)) } } return result }