diff --git a/app/api_topologies.go b/app/api_topologies.go index e9bcb2a67..848cee933 100644 --- a/app/api_topologies.go +++ b/app/api_topologies.go @@ -16,18 +16,21 @@ import ( ) const ( - apiTopologyURL = "/api/topology/" - processesTopologyDescID = "processes" - processesByNameTopologyDescID = "processes-by-name" - containerLabelFiltersGroupID = "container_label_filters_group" - containersTopologyDescID = "containers" - containersByHostnameTopologyDescID = "containers-by-hostname" - containersByImageTopologyDescID = "containers-by-image" - podsTopologyDescID = "pods" - replicaSetsTopologyDescID = "replica-sets" - deploymentsTopologyDescID = "deployments" - servicesTopologyDescID = "services" - hostsTopologyDescID = "hosts" + apiTopologyURL = "/api/topology/" + processesID = "processes" + processesByNameID = "processes-by-name" + containerLabelFiltersGroupID = "container-label-filters-group" + containersID = "containers" + containersByHostnameID = "containers-by-hostname" + containersByImageID = "containers-by-image" + podsID = "pods" + replicaSetsID = "replica-sets" + deploymentsID = "deployments" + servicesID = "services" + hostsID = "hosts" + weaveID = "weave" + ecsTasksID = "ecs-tasks" + ecsServicesID = "ecs-services" ) var ( @@ -53,7 +56,10 @@ func AddInitialTopologiesToRegistry(registry *Registry) { { ID: containerLabelFiltersGroupID, Default: "application", - Options: []APITopologyOption{{Value: "all", Label: "All", filter: nil, filterPseudo: false}, {Value: "system", Label: "System Containers", filter: render.IsSystem, filterPseudo: false}, {Value: "notsystem", Label: "Application Containers", filter: render.IsApplication, filterPseudo: false}}, + Options: []APITopologyOption{ + {Value: "all", Label: "All", filter: nil, filterPseudo: false}, + {Value: "system", Label: "System Containers", filter: render.IsSystem, filterPseudo: false}, + {Value: "notsystem", Label: "Application Containers", filter: render.IsApplication, filterPseudo: false}}, }, { ID: "stopped", @@ -90,7 +96,7 @@ func AddInitialTopologiesToRegistry(registry *Registry) { // be the verb to get to that state registry.Add( APITopologyDesc{ - id: processesTopologyDescID, + id: processesID, renderer: render.FilterUnconnected(render.ProcessWithContainerNameRenderer), Name: "Processes", Rank: 1, @@ -98,71 +104,85 @@ func AddInitialTopologiesToRegistry(registry *Registry) { HideIfEmpty: true, }, APITopologyDesc{ - id: processesByNameTopologyDescID, - parent: "processes", + id: processesByNameID, + parent: processesID, renderer: render.FilterUnconnected(render.ProcessNameRenderer), Name: "by name", Options: unconnectedFilter, HideIfEmpty: true, }, APITopologyDesc{ - id: containersTopologyDescID, + id: containersID, renderer: render.ContainerWithImageNameRenderer, Name: "Containers", Rank: 2, Options: containerFilters, }, APITopologyDesc{ - id: containersByHostnameTopologyDescID, - parent: "containers", + id: containersByHostnameID, + parent: containersID, renderer: render.ContainerHostnameRenderer, Name: "by DNS name", Options: containerFilters, }, APITopologyDesc{ - id: containersByImageTopologyDescID, - parent: "containers", + id: containersByImageID, + parent: containersID, renderer: render.ContainerImageRenderer, Name: "by image", Options: containerFilters, }, APITopologyDesc{ - id: podsTopologyDescID, + id: podsID, renderer: render.PodRenderer, Name: "Pods", Rank: 3, HideIfEmpty: true, }, APITopologyDesc{ - id: replicaSetsTopologyDescID, - parent: "pods", + id: replicaSetsID, + parent: podsID, renderer: render.ReplicaSetRenderer, Name: "replica sets", HideIfEmpty: true, }, APITopologyDesc{ - id: deploymentsTopologyDescID, - parent: "pods", + id: deploymentsID, + parent: podsID, renderer: render.DeploymentRenderer, Name: "deployments", HideIfEmpty: true, }, APITopologyDesc{ - id: servicesTopologyDescID, - parent: "pods", + id: servicesID, + parent: podsID, renderer: render.PodServiceRenderer, Name: "services", HideIfEmpty: true, }, APITopologyDesc{ - id: hostsTopologyDescID, + id: ecsTasksID, + renderer: render.ECSTaskRenderer, + Name: "Tasks", + Rank: 3, + HideIfEmpty: true, + }, + APITopologyDesc{ + id: ecsServicesID, + parent: ecsTasksID, + renderer: render.ECSServiceRenderer, + Name: "services", + HideIfEmpty: true, + }, + APITopologyDesc{ + id: hostsID, renderer: render.HostRenderer, Name: "Hosts", Rank: 4, }, APITopologyDesc{ - id: "weave", - parent: "hosts", + id: weaveID, + parent: hostsID, renderer: render.WeaveRenderer, Name: "weave net", HideIfEmpty: true, @@ -206,7 +226,7 @@ func updateFilters(rpt report.Report, topologies []APITopologyDesc) []APITopolog } sort.Strings(ns) for i, t := range topologies { - if t.id == podsTopologyDescID || t.id == servicesTopologyDescID || t.id == deploymentsTopologyDescID || t.id == replicaSetsTopologyDescID { + if t.id == podsID || t.id == servicesID || t.id == deploymentsID || t.id == replicaSetsID { topologies[i] = updateTopologyFilters(t, []APITopologyOptionGroup{ kubernetesFilters(ns...), k8sPseudoFilter, }) @@ -297,7 +317,7 @@ func AddContainerFilters(newFilters ...APITopologyOption) { func (r *Registry) AddContainerFilters(newFilters ...APITopologyOption) { r.Lock() defer r.Unlock() - for _, key := range []string{containersTopologyDescID, containersByHostnameTopologyDescID, containersByImageTopologyDescID} { + for _, key := range []string{containersID, containersByHostnameID, containersByImageID} { for i := range r.items[key].Options { if r.items[key].Options[i].ID == containerLabelFiltersGroupID { r.items[key].Options[i].Options = append(r.items[key].Options[i].Options, newFilters...) diff --git a/probe/awsecs/reporter.go b/probe/awsecs/reporter.go index 895bf8e8e..3932151ff 100644 --- a/probe/awsecs/reporter.go +++ b/probe/awsecs/reporter.go @@ -1,13 +1,15 @@ package awsecs import ( - "fmt" - log "github.com/Sirupsen/logrus" "github.com/weaveworks/scope/probe/docker" "github.com/weaveworks/scope/report" ) +const ( + TaskFamily = "ecs_task_family" +) + type taskInfo struct { containerIDs []string family string @@ -75,7 +77,8 @@ func (r Reporter) Tag(rpt report.Report) (report.Report, error) { unique := make(map[string]bool) for _, serviceName := range taskServices { if !unique[serviceName] { - rpt.ECSService = rpt.ECSService.AddNode(report.MakeNode(serviceNodeID(serviceName))) + serviceID := report.MakeECSServiceNodeID(serviceName) + rpt.ECSService = rpt.ECSService.AddNode(report.MakeNode(serviceID)) unique[serviceName] = true } } @@ -84,14 +87,16 @@ func (r Reporter) Tag(rpt report.Report) (report.Report, error) { for taskArn, info := range taskMap { // new task node - node := report.MakeNodeWith(taskNodeID(taskArn), map[string]string{"family": info.family}) + taskID := report.MakeECSTaskNodeID(taskArn) + node := report.MakeNodeWith(taskID, map[string]string{TaskFamily: info.family}) rpt.ECSTask = rpt.ECSTask.AddNode(node) // parents sets to merge into all matching container nodes parentsSets := report.MakeSets() - parentsSets.Add(report.ECSTask, report.MakeStringSet(taskNodeID(taskArn))) + parentsSets.Add(report.ECSTask, report.MakeStringSet(taskID)) if serviceName, ok := taskServices[taskArn]; ok { - parentsSets.Add(report.ECSService, report.MakeStringSet(serviceNodeID(serviceName))) + serviceID := report.MakeECSServiceNodeID(serviceName) + parentsSets.Add(report.ECSService, report.MakeStringSet(serviceID)) } for _, containerID := range info.containerIDs { @@ -113,11 +118,3 @@ func (r Reporter) Tag(rpt report.Report) (report.Report, error) { func (r Reporter) Name() string { return "awsecs" } - -func serviceNodeID(id string) string { - return fmt.Sprintf("%s;ECSService", id) -} - -func taskNodeID(id string) string { - return fmt.Sprintf("%s;ECSTask", id) -} diff --git a/render/detailed/summary.go b/render/detailed/summary.go index caa2d0a3e..e4ad49e24 100644 --- a/render/detailed/summary.go +++ b/render/detailed/summary.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/weaveworks/scope/probe/awsecs" "github.com/weaveworks/scope/probe/docker" "github.com/weaveworks/scope/probe/endpoint" "github.com/weaveworks/scope/probe/host" @@ -68,6 +69,8 @@ var renderers = map[string]func(NodeSummary, report.Node) (NodeSummary, bool){ report.Service: podGroupNodeSummary, report.Deployment: podGroupNodeSummary, report.ReplicaSet: podGroupNodeSummary, + report.ECSTask: ecsTaskNodeSummary, + report.ECSService: ecsServiceNodeSummary, report.Host: hostNodeSummary, report.Overlay: weaveNodeSummary, } @@ -240,6 +243,17 @@ func podGroupNodeSummary(base NodeSummary, n report.Node) (NodeSummary, bool) { return base, true } +func ecsTaskNodeSummary(base NodeSummary, n report.Node) (NodeSummary, bool) { + base.Label, _ = n.Latest.Lookup(awsecs.TaskFamily) + return base, true +} + +func ecsServiceNodeSummary(base NodeSummary, n report.Node) (NodeSummary, bool) { + base.Label, _ = report.ParseECSServiceNodeID(n.ID) + base.Stack = true + return base, true +} + func hostNodeSummary(base NodeSummary, n report.Node) (NodeSummary, bool) { var ( hostname, _ = n.Latest.Lookup(host.HostName) diff --git a/render/ecs.go b/render/ecs.go new file mode 100644 index 000000000..595772b93 --- /dev/null +++ b/render/ecs.go @@ -0,0 +1,19 @@ +package render + +import ( + "github.com/weaveworks/scope/report" +) + +// ECSTaskRenderer is a Renderer for Amazon ECS tasks. +var ECSTaskRenderer = MakeFilter( + // TODO + func(n report.Node) bool { return true }, + SelectECSTask, +) + +// ECSServiceRenderer is a Renderer for Amazon ECS services. +var ECSServiceRenderer = MakeFilter( + // TODO + func(n report.Node) bool { return true }, + SelectECSService, +) diff --git a/render/selectors.go b/render/selectors.go index 286bc29ee..b4894b9c7 100644 --- a/render/selectors.go +++ b/render/selectors.go @@ -31,5 +31,7 @@ var ( SelectService = TopologySelector(report.Service) SelectDeployment = TopologySelector(report.Deployment) SelectReplicaSet = TopologySelector(report.ReplicaSet) + SelectECSTask = TopologySelector(report.ECSTask) + SelectECSService = TopologySelector(report.ECSService) SelectOverlay = TopologySelector(report.Overlay) ) diff --git a/report/id.go b/report/id.go index 0f5466e80..66a5b3418 100644 --- a/report/id.go +++ b/report/id.go @@ -119,6 +119,18 @@ var ( // ParseReplicaSetNodeID parses a replica set node ID ParseReplicaSetNodeID = parseSingleComponentID("replica_set") + + // MakeECSTaskNodeID produces a replica set node ID from its composite parts. + MakeECSTaskNodeID = makeSingleComponentID("ecs_task") + + // ParseECSTaskNodeID parses a replica set node ID + ParseECSTaskNodeID = parseSingleComponentID("ecs_task") + + // MakeECSServiceNodeID produces a replica set node ID from its composite parts. + MakeECSServiceNodeID = makeSingleComponentID("ecs_service") + + // ParseECSServiceNodeID parses a replica set node ID + ParseECSServiceNodeID = parseSingleComponentID("ecs_service") ) // makeSingleComponentID makes a single-component node id encoder diff --git a/report/report.go b/report/report.go index 932756a8d..890ab5be1 100644 --- a/report/report.go +++ b/report/report.go @@ -158,7 +158,9 @@ func MakeReport() Report { WithShape(Heptagon). WithLabel("replica set", "replica sets"), - Overlay: MakeTopology(), + Overlay: MakeTopology(). + WithShape(Circle). + WithLabel("peer", "peers"), ECSTask: MakeTopology(). WithShape(Heptagon).