// MapEndpoint2IP maps endpoint nodes to their IP address, for joining // with container nodes. We drop endpoint nodes with pids, as they // will be joined to containers through the process topology, and we // don't want to double count edges. func MapEndpoint2IP(m report.Node, local report.Networks) report.Nodes { // Don't include procspied connections, to prevent double counting _, ok := m.Latest.Lookup(endpoint.Procspied) if ok { return report.Nodes{} } scope, addr, port, ok := report.ParseEndpointNodeID(m.ID) if !ok { return report.Nodes{} } if ip := net.ParseIP(addr); ip != nil && !local.Contains(ip) { return report.Nodes{TheInternetID: theInternetNode(m)} } // We don't always know what port a container is listening on, and // container-to-container communications can be unambiguously identified // without ports. OTOH, connections to the host IPs which have been port // mapped to a container can only be unambiguously identified with the port. // So we need to emit two nodes, for two different cases. id := report.MakeScopedEndpointNodeID(scope, addr, "") idWithPort := report.MakeScopedEndpointNodeID(scope, addr, port) return report.Nodes{ id: NewDerivedNode(id, m).WithTopology(IP), idWithPort: NewDerivedNode(idWithPort, m).WithTopology(IP), } }
// MapContainer2IP maps container nodes to their IP addresses (outputs // multiple nodes). This allows container to be joined directly with // the endpoint topology. func MapContainer2IP(m report.Node, _ report.Networks) report.Nodes { containerID, ok := m.Latest.Lookup(docker.ContainerID) if !ok { return report.Nodes{} } // if this container doesn't make connections, we can ignore it _, doesntMakeConnections := m.Latest.Lookup(report.DoesNotMakeConnections) if doesntMakeConnections { return report.Nodes{} } result := report.Nodes{} if addrs, ok := m.Sets.Lookup(docker.ContainerIPsWithScopes); ok { for _, addr := range addrs { scope, addr, ok := report.ParseAddressNodeID(addr) if !ok { continue } id := report.MakeScopedEndpointNodeID(scope, addr, "") result[id] = NewDerivedNode(id, m). WithTopology(IP). WithLatests(map[string]string{docker.ContainerID: containerID}). WithCounters(map[string]int{IP: 1}) } } // Also output all the host:port port mappings (see above comment). // In this case we assume this doesn't need a scope, as they are for host IPs. ports, _ := m.Sets.Lookup(docker.ContainerPorts) for _, portMapping := range ports { if mapping := portMappingMatch.FindStringSubmatch(portMapping); mapping != nil { ip, port := mapping[1], mapping[2] id := report.MakeScopedEndpointNodeID("", ip, port) result[id] = NewDerivedNode(id, m). WithTopology(IP). WithLatests(map[string]string{docker.ContainerID: containerID}). WithCounters(map[string]int{IP: 1}) } } return result }