func renderTo(rpt report.Report, topology string) (render.RenderableNodes, error) { renderer, ok := map[string]render.Renderer{ "applications": render.FilterUnconnected(render.ProcessWithContainerNameRenderer), "applications-by-name": render.FilterUnconnected(render.ProcessNameRenderer), "containers": render.ContainerWithImageNameRenderer, "containers-by-image": render.ContainerImageRenderer, "hosts": render.HostRenderer, }[topology] if !ok { return render.RenderableNodes{}, fmt.Errorf("unknown topology %v", topology) } return renderer.Render(rpt), nil }
func TestFilterUnconnectedSelf(t *testing.T) { // Test nodes that are only connected to themselves are filtered. { nodes := render.RenderableNodes{ "foo": {ID: "foo", Node: report.MakeNode().WithAdjacent("foo")}, } renderer := render.FilterUnconnected(mockRenderer{RenderableNodes: nodes}) want := render.RenderableNodes{} have := renderer.Render(report.MakeReport()).Prune() if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } } }
func TestFilterRender(t *testing.T) { renderer := render.FilterUnconnected( mockRenderer{RenderableNodes: render.RenderableNodes{ "foo": {ID: "foo", Node: report.MakeNode().WithAdjacent("bar")}, "bar": {ID: "bar", Node: report.MakeNode().WithAdjacent("foo")}, "baz": {ID: "baz", Node: report.MakeNode()}, }}) want := render.RenderableNodes{ "foo": {ID: "foo", Node: report.MakeNode().WithAdjacent("bar")}, "bar": {ID: "bar", Node: report.MakeNode().WithAdjacent("foo")}, } have := renderer.Render(report.MakeReport()).Prune() if !reflect.DeepEqual(want, have) { t.Error(test.Diff(want, have)) } }
func TestFilterRender(t *testing.T) { renderer := render.FilterUnconnected( mockRenderer{RenderableNodes: render.RenderableNodes{ "foo": {ID: "foo", Adjacency: report.MakeIDList("bar"), NodeMetadata: report.MakeNodeMetadata()}, "bar": {ID: "bar", Adjacency: report.MakeIDList("foo"), NodeMetadata: report.MakeNodeMetadata()}, "baz": {ID: "baz", Adjacency: report.MakeIDList(), NodeMetadata: report.MakeNodeMetadata()}, }}) want := render.RenderableNodes{ "foo": {ID: "foo", Adjacency: report.MakeIDList("bar"), NodeMetadata: report.MakeNodeMetadata()}, "bar": {ID: "bar", Adjacency: report.MakeIDList("foo"), NodeMetadata: report.MakeNodeMetadata()}, } have := sterilize(renderer.Render(report.MakeReport()), true) if !reflect.DeepEqual(want, have) { t.Errorf("want %+v, have %+v", want, have) } }
func TestFilterRender(t *testing.T) { renderer := render.FilterUnconnected( mockRenderer{RenderableNodes: render.RenderableNodes{ "foo": {ID: "foo", Node: report.MakeNode().WithAdjacent("bar")}, "bar": {ID: "bar", Node: report.MakeNode().WithAdjacent("foo")}, "baz": {ID: "baz", Node: report.MakeNode()}, }}) want := render.RenderableNodes{ "foo": {ID: "foo", Node: report.MakeNode().WithAdjacent("bar")}, "bar": {ID: "bar", Node: report.MakeNode().WithAdjacent("foo")}, } have := expected.Sterilize(renderer.Render(report.MakeReport())) if !reflect.DeepEqual(want, have) { t.Errorf("want %+v, have %+v", want, have) } }
type APIDetails struct { ID string `json:"id"` Version string `json:"version"` } func apiHandler(w http.ResponseWriter, r *http.Request) { respondWith(w, http.StatusOK, APIDetails{ID: uniqueID, Version: version}) } // Topology option labels should tell the current state. The first item must // be the verb to get to that state var topologyRegistry = map[string]topologyView{ "applications": { human: "Applications", parent: "", renderer: render.FilterUnconnected(render.ProcessWithContainerNameRenderer), options: optionParams{"unconnected": { // Show the user why there are filtered nodes in this view. // Don't give them the option to show those nodes. {"hide", "Unconnected nodes hidden", true, nop}, }}, }, "applications-by-name": { human: "by name", parent: "applications", renderer: render.FilterUnconnected(render.ProcessNameRenderer), options: optionParams{"unconnected": { // Ditto above. {"hide", "Unconnected nodes hidden", true, nop}, }}, },
func init() { containerFilters := map[string][]APITopologyOption{ "system": { {"show", "System containers shown", false, render.FilterNoop}, {"hide", "System containers hidden", true, render.FilterSystem}, }, "stopped": { {"show", "Stopped containers shown", false, render.FilterNoop}, {"hide", "Stopped containers hidden", true, render.FilterStopped}, }, } // Topology option labels should tell the current state. The first item must // be the verb to get to that state topologyRegistry.add( APITopologyDesc{ id: "processes", renderer: render.FilterUnconnected(render.ProcessWithContainerNameRenderer), Name: "Processes", Rank: 1, Options: map[string][]APITopologyOption{"unconnected": { // Show the user why there are filtered nodes in this view. // Don't give them the option to show those nodes. {"hide", "Unconnected nodes hidden", true, render.FilterNoop}, }}, }, APITopologyDesc{ id: "processes-by-name", parent: "processes", renderer: render.FilterUnconnected(render.ProcessNameRenderer), Name: "by name", Options: map[string][]APITopologyOption{"unconnected": { // Ditto above. {"hide", "Unconnected nodes hidden", true, render.FilterNoop}, }}, }, APITopologyDesc{ id: "containers", renderer: render.ContainerWithImageNameRenderer, Name: "Containers", Rank: 2, Options: containerFilters, }, APITopologyDesc{ id: "containers-by-image", parent: "containers", renderer: render.ContainerImageRenderer, Name: "by image", Options: containerFilters, }, APITopologyDesc{ id: "containers-by-hostname", parent: "containers", renderer: render.ContainerHostnameRenderer, Name: "by DNS name", Options: containerFilters, }, APITopologyDesc{ id: "hosts", renderer: render.HostRenderer, Name: "Hosts", Rank: 4, Options: map[string][]APITopologyOption{}, }, ) }
func init() { containerFilters := []APITopologyOptionGroup{ { ID: "system", Default: "application", Options: []APITopologyOption{ {"system", "System containers", render.IsSystem, false}, {"application", "Application containers", render.IsApplication, false}, {"both", "Both", nil, false}, }, }, { ID: "stopped", Default: "running", Options: []APITopologyOption{ {"stopped", "Stopped containers", render.IsStopped, false}, {"running", "Running containers", render.IsRunning, false}, {"both", "Both", nil, false}, }, }, { ID: "pseudo", Default: "show", Options: []APITopologyOption{ {"show", "Show Uncontained", nil, false}, {"hide", "Hide Uncontained", render.IsNotPseudo, true}, }, }, } unconnectedFilter := []APITopologyOptionGroup{ { ID: "unconnected", Default: "hide", Options: []APITopologyOption{ // Show the user why there are filtered nodes in this view. // Don't give them the option to show those nodes. {"hide", "Unconnected nodes hidden", nil, false}, }, }, } // Topology option labels should tell the current state. The first item must // be the verb to get to that state topologyRegistry.add( APITopologyDesc{ id: "processes", renderer: render.FilterUnconnected(render.ProcessWithContainerNameRenderer), Name: "Processes", Rank: 1, Options: unconnectedFilter, HideIfEmpty: true, }, APITopologyDesc{ id: "processes-by-name", parent: "processes", renderer: render.FilterUnconnected(render.ProcessNameRenderer), Name: "by name", Options: unconnectedFilter, HideIfEmpty: true, }, APITopologyDesc{ id: "containers", renderer: render.ContainerWithImageNameRenderer, Name: "Containers", Rank: 2, Options: containerFilters, }, APITopologyDesc{ id: "containers-by-hostname", parent: "containers", renderer: render.ContainerHostnameRenderer, Name: "by DNS name", Options: containerFilters, }, APITopologyDesc{ id: "containers-by-image", parent: "containers", renderer: render.ContainerImageRenderer, Name: "by image", Options: containerFilters, }, APITopologyDesc{ id: "pods", renderer: render.PodRenderer, Name: "Pods", Rank: 3, HideIfEmpty: true, }, APITopologyDesc{ id: "replica-sets", parent: "pods", renderer: render.ReplicaSetRenderer, Name: "replica sets", HideIfEmpty: true, }, APITopologyDesc{ id: "deployments", parent: "pods", renderer: render.DeploymentRenderer, Name: "deployments", HideIfEmpty: true, }, APITopologyDesc{ id: "services", parent: "pods", renderer: render.PodServiceRenderer, Name: "services", HideIfEmpty: true, }, APITopologyDesc{ id: "hosts", renderer: render.HostRenderer, Name: "Hosts", Rank: 4, }, ) }