diff --git a/app/api_topologies.go b/app/api_topologies.go index d63edd77d..fd68a2ac9 100644 --- a/app/api_topologies.go +++ b/app/api_topologies.go @@ -33,6 +33,7 @@ const ( weaveID = "weave" ecsTasksID = "ecs-tasks" ecsServicesID = "ecs-services" + swarmServicesID = "swarm-services" ) var ( @@ -252,6 +253,14 @@ func MakeRegistry() *Registry { Options: []APITopologyOptionGroup{unmanagedFilter}, HideIfEmpty: true, }, + APITopologyDesc{ + id: swarmServicesID, + renderer: render.SwarmServiceRenderer, + Name: "services", + Rank: 3, + Options: []APITopologyOptionGroup{unmanagedFilter}, + HideIfEmpty: true, + }, APITopologyDesc{ id: hostsID, renderer: render.HostRenderer, diff --git a/app/api_topologies_test.go b/app/api_topologies_test.go index 6ce9b49f1..c5dc75fc9 100644 --- a/app/api_topologies_test.go +++ b/app/api_topologies_test.go @@ -40,7 +40,7 @@ func TestAPITopology(t *testing.T) { if err := decoder.Decode(&topologies); err != nil { t.Fatalf("JSON parse error: %s", err) } - equals(t, 5, len(topologies)) + equals(t, 6, len(topologies)) for _, topology := range topologies { is200(t, ts, topology.URL) @@ -50,7 +50,7 @@ func TestAPITopology(t *testing.T) { } // TODO: add ECS nodes in report fixture - if topology.Name == "Tasks" { + if topology.Name == "Tasks" || topology.Name == "services" { continue } @@ -200,7 +200,7 @@ func TestAPITopologyAddsKubernetes(t *testing.T) { if err := decoder.Decode(&topologies); err != nil { t.Fatalf("JSON parse error: %s", err) } - equals(t, 5, len(topologies)) + equals(t, 6, len(topologies)) // Enable the kubernetes topologies rpt := report.MakeReport() @@ -234,7 +234,7 @@ func TestAPITopologyAddsKubernetes(t *testing.T) { if err := decoder.Decode(&topologies); err != nil { t.Fatalf("JSON parse error: %s", err) } - equals(t, 5, len(topologies)) + equals(t, 6, len(topologies)) found := false for _, topology := range topologies { diff --git a/render/detailed/parents.go b/render/detailed/parents.go index b749e1326..5fce99de5 100644 --- a/render/detailed/parents.go +++ b/render/detailed/parents.go @@ -4,6 +4,7 @@ import ( "sort" "github.com/weaveworks/scope/probe/awsecs" + "github.com/weaveworks/scope/probe/docker" "github.com/weaveworks/scope/probe/host" "github.com/weaveworks/scope/probe/kubernetes" "github.com/weaveworks/scope/report" @@ -27,6 +28,7 @@ var ( report.Service: kubernetesParentLabel, report.ECSTask: latestLookup(awsecs.TaskFamily), report.ECSService: ecsServiceParentLabel, + report.SwarmService: latestLookup(docker.ServiceName), report.ContainerImage: containerImageParentLabel, report.Host: latestLookup(host.HostName), } diff --git a/render/detailed/summary.go b/render/detailed/summary.go index cd7f457b1..63d4620da 100644 --- a/render/detailed/summary.go +++ b/render/detailed/summary.go @@ -71,6 +71,7 @@ var renderers = map[string]func(NodeSummary, report.Node) (NodeSummary, bool){ report.ReplicaSet: podGroupNodeSummary, report.ECSTask: ecsTaskNodeSummary, report.ECSService: ecsServiceNodeSummary, + report.SwarmService: swarmServiceNodeSummary, report.Host: hostNodeSummary, report.Overlay: weaveNodeSummary, report.Endpoint: nil, // Do not render @@ -93,6 +94,7 @@ var primaryAPITopology = map[string]string{ report.Service: "services", report.ECSTask: "ecs-tasks", report.ECSService: "ecs-services", + report.SwarmService: "swarm-services", report.Host: "hosts", } @@ -276,6 +278,11 @@ func ecsServiceNodeSummary(base NodeSummary, n report.Node) (NodeSummary, bool) return base, true } +func swarmServiceNodeSummary(base NodeSummary, n report.Node) (NodeSummary, bool) { + base.Label, _ = n.Latest.Lookup(docker.ServiceName) + return base, true +} + func hostNodeSummary(base NodeSummary, n report.Node) (NodeSummary, bool) { var ( hostname, _ = n.Latest.Lookup(host.HostName) diff --git a/render/selectors.go b/render/selectors.go index b4894b9c7..eb369f932 100644 --- a/render/selectors.go +++ b/render/selectors.go @@ -33,5 +33,6 @@ var ( SelectReplicaSet = TopologySelector(report.ReplicaSet) SelectECSTask = TopologySelector(report.ECSTask) SelectECSService = TopologySelector(report.ECSService) + SelectSwarmService = TopologySelector(report.SwarmService) SelectOverlay = TopologySelector(report.Overlay) ) diff --git a/render/swarm.go b/render/swarm.go new file mode 100644 index 000000000..b77177a5e --- /dev/null +++ b/render/swarm.go @@ -0,0 +1,26 @@ +package render + +import ( + "github.com/weaveworks/scope/report" +) + +// SwarmServiceRenderer is a Renderer for Docker Swarm services +var SwarmServiceRenderer = ConditionalRenderer(renderSwarmTopologies, + MakeMap( + PropagateSingleMetrics(report.Container), + MakeReduce( + MakeMap( + Map2Parent(report.SwarmService, UnmanagedID, nil), + MakeFilter( + IsRunning, + ContainerWithImageNameRenderer, + ), + ), + SelectSwarmService, + ), + ), +) + +func renderSwarmTopologies(rpt report.Report) bool { + return len(rpt.SwarmService.Nodes) >= 1 +}