123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- package app_test
- import (
- "bytes"
- "context"
- "net/http/httptest"
- "net/url"
- "testing"
- "time"
- "github.com/gorilla/mux"
- "github.com/ugorji/go/codec"
- apiv1 "k8s.io/api/core/v1"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "github.com/weaveworks/common/test"
- "github.com/weaveworks/scope/app"
- "github.com/weaveworks/scope/probe/docker"
- "github.com/weaveworks/scope/probe/kubernetes"
- "github.com/weaveworks/scope/render"
- "github.com/weaveworks/scope/render/detailed"
- "github.com/weaveworks/scope/render/expected"
- "github.com/weaveworks/scope/report"
- "github.com/weaveworks/scope/test/fixture"
- "github.com/weaveworks/scope/test/reflect"
- "github.com/weaveworks/scope/test/utils"
- )
- const (
- systemGroupID = "system"
- customAPITopologyOptionFilterID = "containerLabelFilter0"
- )
- func TestAPITopology(t *testing.T) {
- ts := topologyServer()
- defer ts.Close()
- body := getRawJSON(t, ts, "/api/topology")
- var topologies []app.APITopologyDesc
- decoder := codec.NewDecoderBytes(body, &codec.JsonHandle{})
- if err := decoder.Decode(&topologies); err != nil {
- t.Fatalf("JSON parse error: %s", err)
- }
- equals(t, 6, len(topologies))
- for _, topology := range topologies {
- is200(t, ts, topology.URL)
- for _, subTopology := range topology.SubTopologies {
- is200(t, ts, subTopology.URL)
- }
- // TODO: add ECS nodes in report fixture
- if topology.Name == "Tasks" || topology.Name == "Services" {
- continue
- }
- if have := topology.Stats.EdgeCount; have <= 0 {
- t.Errorf("EdgeCount isn't positive for %s: %d", topology.Name, have)
- }
- if have := topology.Stats.NodeCount; have <= 0 {
- t.Errorf("NodeCount isn't positive for %s: %d", topology.Name, have)
- }
- if have := topology.Stats.NonpseudoNodeCount; have <= 0 {
- t.Errorf("NonpseudoNodeCount isn't positive for %s: %d", topology.Name, have)
- }
- }
- }
- func TestContainerLabelFilter(t *testing.T) {
- topologySummaries, err := getTestContainerLabelFilterTopologySummary(t, false)
- if err != nil {
- t.Fatalf("Topology Registry Report error: %s", err)
- }
- // only the filtered container with fixture.TestLabelKey1 should be present
- equals(t, 1, len(topologySummaries))
- for key := range topologySummaries {
- equals(t, report.MakeContainerNodeID(fixture.ClientContainerID), key)
- }
- }
- func TestContainerLabelFilterExclude(t *testing.T) {
- topologySummaries, err := getTestContainerLabelFilterTopologySummary(t, true)
- if err != nil {
- t.Fatalf("Topology Registry Report error: %s", err)
- }
- // all containers but the excluded container should be present
- for key := range topologySummaries {
- id := report.MakeContainerNodeID(fixture.ServerContainerNodeID)
- if id == key {
- t.Errorf("Didn't expect to find %q in report", id)
- }
- }
- }
- func TestRendererForTopologyWithFiltering(t *testing.T) {
- ts := topologyServer()
- defer ts.Close()
- topologyRegistry := app.MakeRegistry()
- option := app.MakeAPITopologyOption(customAPITopologyOptionFilterID, "title", render.IsApplication, false)
- topologyRegistry.AddContainerFilters(option)
- urlvalues := url.Values{}
- urlvalues.Set(systemGroupID, customAPITopologyOptionFilterID)
- urlvalues.Set("stopped", "running")
- urlvalues.Set("pseudo", "hide")
- renderer, filter, err := topologyRegistry.RendererForTopology("containers", urlvalues, fixture.Report)
- if err != nil {
- t.Fatalf("Topology Registry Report error: %s", err)
- }
- input := fixture.Report.Copy()
- input.Container.Nodes[fixture.ClientContainerNodeID] = input.Container.Nodes[fixture.ClientContainerNodeID].WithLatests(map[string]string{
- docker.LabelPrefix + "works.weave.role": "system",
- })
- have := utils.Prune(render.Render(context.Background(), input, renderer, filter).Nodes)
- want := utils.Prune(expected.RenderedContainers.Copy())
- delete(want, fixture.ClientContainerNodeID)
- delete(want, render.MakePseudoNodeID(render.UncontainedID, fixture.ServerHostID))
- delete(want, render.OutgoingInternetID)
- if !reflect.DeepEqual(want, have) {
- t.Error(test.Diff(want, have))
- }
- }
- func TestRendererForTopologyNoFiltering(t *testing.T) {
- ts := topologyServer()
- defer ts.Close()
- topologyRegistry := app.MakeRegistry()
- option := app.MakeAPITopologyOption(customAPITopologyOptionFilterID, "title", nil, false)
- topologyRegistry.AddContainerFilters(option)
- urlvalues := url.Values{}
- urlvalues.Set(systemGroupID, customAPITopologyOptionFilterID)
- urlvalues.Set("stopped", "running")
- urlvalues.Set("pseudo", "hide")
- renderer, filter, err := topologyRegistry.RendererForTopology("containers", urlvalues, fixture.Report)
- if err != nil {
- t.Fatalf("Topology Registry Report error: %s", err)
- }
- input := fixture.Report.Copy()
- input.Container.Nodes[fixture.ClientContainerNodeID] = input.Container.Nodes[fixture.ClientContainerNodeID].WithLatests(map[string]string{
- docker.LabelPrefix + "works.weave.role": "system",
- })
- have := utils.Prune(render.Render(context.Background(), input, renderer, filter).Nodes)
- want := utils.Prune(expected.RenderedContainers.Copy())
- delete(want, render.MakePseudoNodeID(render.UncontainedID, fixture.ServerHostID))
- delete(want, render.OutgoingInternetID)
- if !reflect.DeepEqual(want, have) {
- t.Error(test.Diff(want, have))
- }
- }
- func getTestContainerLabelFilterTopologySummary(t *testing.T, exclude bool) (detailed.NodeSummaries, error) {
- ts := topologyServer()
- defer ts.Close()
- var (
- topologyRegistry = app.MakeRegistry()
- filterFunc render.FilterFunc
- )
- if exclude == true {
- filterFunc = render.DoesNotHaveLabel(fixture.TestLabelKey2, fixture.ApplicationLabelValue2)
- } else {
- filterFunc = render.HasLabel(fixture.TestLabelKey1, fixture.ApplicationLabelValue1)
- }
- option := app.MakeAPITopologyOption(customAPITopologyOptionFilterID, "title", filterFunc, false)
- topologyRegistry.AddContainerFilters(option)
- urlvalues := url.Values{}
- urlvalues.Set(systemGroupID, customAPITopologyOptionFilterID)
- urlvalues.Set("stopped", "running")
- urlvalues.Set("pseudo", "hide")
- renderer, filter, err := topologyRegistry.RendererForTopology("containers", urlvalues, fixture.Report)
- if err != nil {
- return nil, err
- }
- ctx := context.Background()
- return detailed.Summaries(ctx, detailed.RenderContext{Report: fixture.Report}, render.Render(ctx, fixture.Report, renderer, filter).Nodes), nil
- }
- func TestAPITopologyAddsKubernetes(t *testing.T) {
- router := mux.NewRouter()
- c := app.NewCollector(1 * time.Minute)
- app.RegisterReportPostHandler(c, router)
- app.RegisterTopologyRoutes(router, c, map[string]bool{"foo_capability": true})
- ts := httptest.NewServer(router)
- defer ts.Close()
- body := getRawJSON(t, ts, "/api/topology")
- var topologies []app.APITopologyDesc
- decoder := codec.NewDecoderBytes(body, &codec.JsonHandle{})
- if err := decoder.Decode(&topologies); err != nil {
- t.Fatalf("JSON parse error: %s", err)
- }
- equals(t, 6, len(topologies))
- // Enable the kubernetes topologies
- rpt := report.MakeReport()
- rpt.Pod = report.MakeTopology()
- rpt.Pod.Nodes[fixture.ClientPodNodeID] = kubernetes.NewPod(&apiv1.Pod{
- ObjectMeta: metav1.ObjectMeta{
- Name: "pong-a",
- Namespace: "ping",
- Labels: map[string]string{"ponger": "true"},
- },
- Status: apiv1.PodStatus{
- HostIP: "1.2.3.4",
- ContainerStatuses: []apiv1.ContainerStatus{
- {ContainerID: "container1"},
- {ContainerID: "container2"},
- },
- },
- Spec: apiv1.PodSpec{
- SecurityContext: &apiv1.PodSecurityContext{},
- },
- }).GetNode("")
- buf := &bytes.Buffer{}
- encoder := codec.NewEncoder(buf, &codec.MsgpackHandle{})
- if err := encoder.Encode(rpt); err != nil {
- t.Fatalf("Msgpack encoding error: %s", err)
- }
- checkRequest(t, ts, "POST", "/api/report", buf.Bytes())
- body = getRawJSON(t, ts, "/api/topology")
- decoder = codec.NewDecoderBytes(body, &codec.JsonHandle{})
- if err := decoder.Decode(&topologies); err != nil {
- t.Fatalf("JSON parse error: %s", err)
- }
- equals(t, 6, len(topologies))
- found := false
- for _, topology := range topologies {
- if topology.Name == "Pods" {
- found = true
- break
- }
- }
- if !found {
- t.Error("Could not find pods topology")
- }
- }
|