func TestDNSAdd(t *testing.T) { mtx := sync.Mutex{} published := map[string]entry{} s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { mtx.Lock() defer mtx.Unlock() parts := strings.SplitN(r.URL.Path, "/", 4) containerID, ip := parts[2], net.ParseIP(parts[3]) fqdn := r.FormValue("fqdn") published[fqdn] = entry{containerID, ip} w.WriteHeader(http.StatusNoContent) })) defer s.Close() client := weave.NewClient(s.URL) err := client.AddDNSEntry(mockHostname, mockContainerID, mockIP) if err != nil { t.Fatal(err) } want := map[string]entry{ mockHostname: {mockContainerID, mockIP}, } if !reflect.DeepEqual(published, want) { t.Fatal(test.Diff(published, want)) } }
func newWeavePublisher(dockerEndpoint, weaveAddr, weaveHostname, containerName string) (*app.WeavePublisher, error) { dockerClient, err := docker.NewDockerClientStub(dockerEndpoint) if err != nil { return nil, err } weaveClient := weave.NewClient(weaveAddr) return app.NewWeavePublisher( weaveClient, dockerClient, app.Interfaces, weaveHostname, containerName, ), nil }
func TestExpose(t *testing.T) { oldExecCmd := exec.Command defer func() { exec.Command = oldExecCmd }() psCalled := false exec.Command = func(name string, args ...string) exec.Cmd { if args[0] == "expose" { t.Fatal("Expose not expected") return nil } psCalled = true return testExec.NewMockCmdString(fmt.Sprintf("%s %s %s/24\n", mockContainerID, mockContainerMAC, mockContainerIP)) } client := weave.NewClient("") if err := client.Expose(); err != nil { t.Fatal(err) } if !psCalled { t.Fatal("Expected a call to weave ps") } psCalled, exposeCalled := false, false exec.Command = func(name string, args ...string) exec.Cmd { if args[0] == "expose" { exposeCalled = true return testExec.NewMockCmdString("") } psCalled = true return testExec.NewMockCmdString("") } if err := client.Expose(); err != nil { t.Fatal(err) } if !psCalled || !exposeCalled { t.Fatal("Expected a call to weave ps & expose") } }
func TestStatus(t *testing.T) { s := httptest.NewServer(http.HandlerFunc(mockWeaveRouter)) defer s.Close() client := weave.NewClient(s.URL) status, err := client.Status() if err != nil { t.Fatal(err) } want := weave.Status{ Router: weave.Router{ Peers: []struct { Name string NickName string }{ { Name: mockWeavePeerName, NickName: mockWeavePeerNickName, }, }, }, DNS: weave.DNS{ Entries: []struct { Hostname string ContainerID string Tombstone int64 }{ { Hostname: mockHostname + ".", ContainerID: mockContainerID, Tombstone: 0, }, }, }, } if !reflect.DeepEqual(status, want) { t.Fatal(test.Diff(status, want)) } }
func TestPS(t *testing.T) { oldExecCmd := exec.Command defer func() { exec.Command = oldExecCmd }() exec.Command = func(name string, args ...string) exec.Cmd { return testExec.NewMockCmdString(fmt.Sprintf("%s %s %s/24\n", mockContainerID, mockContainerMAC, mockContainerIP)) } client := weave.NewClient("") entries, err := client.PS() if err != nil { t.Fatal(err) } want := map[string]weave.PSEntry{ mockContainerID: { ContainerIDPrefix: mockContainerID, MACAddress: mockContainerMAC, IPs: []string{mockContainerIP}, }, } if !reflect.DeepEqual(entries, want) { t.Fatal(test.Diff(entries, want)) } }
// Main runs the probe func probeMain(flags probeFlags) { setLogLevel(flags.logLevel) setLogFormatter(flags.logPrefix) // Setup in memory metrics sink inm := metrics.NewInmemSink(time.Minute, 2*time.Minute) sig := metrics.DefaultInmemSignal(inm) defer sig.Stop() metrics.NewGlobal(metrics.DefaultConfig("scope-probe"), inm) defer log.Info("probe exiting") if flags.spyProcs && os.Getegid() != 0 { log.Warn("--probe.process=true, but that requires root to find everything") } rand.Seed(time.Now().UnixNano()) var ( probeID = strconv.FormatInt(rand.Int63(), 16) hostName = hostname.Get() hostID = hostName // TODO(pb): we should sanitize the hostname ) log.Infof("probe starting, version %s, ID %s", version, probeID) log.Infof("command line: %v", os.Args) checkpointFlags := map[string]string{} if flags.kubernetesEnabled { checkpointFlags["kubernetes_enabled"] = "true" } go check(checkpointFlags) var targets = []string{} if !flags.noApp { targets = append(targets, fmt.Sprintf("localhost:%d", xfer.AppPort)) } if len(flag.Args()) > 0 { targets = append(targets, flag.Args()...) } log.Infof("publishing to: %s", strings.Join(targets, ", ")) probeConfig := appclient.ProbeConfig{ Token: flags.token, ProbeID: probeID, Insecure: flags.insecure, } clients := appclient.NewMultiAppClient(func(hostname, endpoint string) (appclient.AppClient, error) { return appclient.NewAppClient( probeConfig, hostname, endpoint, xfer.ControlHandlerFunc(controls.HandleControlRequest), ) }) defer clients.Stop() dnsLookupFn := net.LookupIP if flags.resolver != "" { dnsLookupFn = appclient.LookupUsing(flags.resolver) } resolver := appclient.NewResolver(targets, dnsLookupFn, clients.Set) defer resolver.Stop() processCache := process.NewCachingWalker(process.NewWalker(flags.procRoot)) scanner := procspy.NewConnectionScanner(processCache) endpointReporter := endpoint.NewReporter(hostID, hostName, flags.spyProcs, flags.useConntrack, scanner) defer endpointReporter.Stop() p := probe.New(flags.spyInterval, flags.publishInterval, clients) p.AddTicker(processCache) hostReporter := host.NewReporter(hostID, hostName, probeID, version, clients) defer hostReporter.Stop() p.AddReporter( endpointReporter, hostReporter, process.NewReporter(processCache, hostID, process.GetDeltaTotalJiffies), ) p.AddTagger(probe.NewTopologyTagger(), host.NewTagger(hostID)) if flags.dockerEnabled { // Don't add the bridge in Kubernetes since container IPs are global and // shouldn't be scoped if !flags.kubernetesEnabled { if err := report.AddLocalBridge(flags.dockerBridge); err != nil { log.Errorf("Docker: problem with bridge %s: %v", flags.dockerBridge, err) } } if registry, err := docker.NewRegistry(flags.dockerInterval, clients, true, hostID); err == nil { defer registry.Stop() p.AddTagger(docker.NewTagger(registry, processCache)) p.AddReporter(docker.NewReporter(registry, hostID, probeID, p)) } else { log.Errorf("Docker: failed to start registry: %v", err) } } if flags.kubernetesEnabled { if client, err := kubernetes.NewClient(flags.kubernetesAPI, flags.kubernetesInterval); err == nil { defer client.Stop() reporter := kubernetes.NewReporter(client, clients, probeID, hostID, p) defer reporter.Stop() p.AddReporter(reporter) p.AddTagger(reporter) } else { log.Errorf("Kubernetes: failed to start client: %v", err) log.Errorf("Kubernetes: make sure to run Scope inside a POD with a service account or provide a valid kubernetes.api url") } } if flags.weaveAddr != "" { client := weave.NewClient(sanitize.URL("http://", 6784, "")(flags.weaveAddr)) weave := overlay.NewWeave(hostID, client) defer weave.Stop() p.AddTagger(weave) p.AddReporter(weave) dockerBridgeIP, err := network.GetFirstAddressOf(flags.dockerBridge) if err != nil { log.Println("Error getting docker bridge ip:", err) } else { weaveDNSLookup := appclient.LookupUsing(dockerBridgeIP + ":53") weaveResolver := appclient.NewResolver([]string{flags.weaveHostname}, weaveDNSLookup, clients.Set) defer weaveResolver.Stop() } } pluginRegistry, err := plugins.NewRegistry( flags.pluginsRoot, pluginAPIVersion, map[string]string{ "probe_id": probeID, "api_version": pluginAPIVersion, }, ) if err != nil { log.Errorf("plugins: problem loading: %v", err) } else { defer pluginRegistry.Close() p.AddReporter(pluginRegistry) } if flags.httpListen != "" { go func() { log.Infof("Profiling data being exported to %s", flags.httpListen) log.Infof("go tool pprof http://%s/debug/pprof/{profile,heap,block}", flags.httpListen) log.Infof("Profiling endpoint %s terminated: %v", flags.httpListen, http.ListenAndServe(flags.httpListen, nil)) }() } p.Start() defer p.Stop() common.SignalHandlerLoop() }