(_ context.Context, project *types.Project, opts api.VizOptions)
| 30 | type vizGraph map[*types.ServiceConfig][]*types.ServiceConfig |
| 31 | |
| 32 | func (s *composeService) Viz(_ context.Context, project *types.Project, opts api.VizOptions) (string, error) { |
| 33 | graph := make(vizGraph) |
| 34 | for _, service := range project.Services { |
| 35 | graph[&service] = make([]*types.ServiceConfig, 0, len(service.DependsOn)) |
| 36 | for dependencyName := range service.DependsOn { |
| 37 | // no error should be returned since dependencyName should exist |
| 38 | dependency, _ := project.GetService(dependencyName) |
| 39 | graph[&service] = append(graph[&service], &dependency) |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | // build graphviz graph |
| 44 | var graphBuilder strings.Builder |
| 45 | |
| 46 | // graph name |
| 47 | graphBuilder.WriteString("digraph ") |
| 48 | writeQuoted(&graphBuilder, project.Name) |
| 49 | graphBuilder.WriteString(" {\n") |
| 50 | |
| 51 | // graph layout |
| 52 | // dot is the perfect layout for this use case since graph is directed and hierarchical |
| 53 | graphBuilder.WriteString(opts.Indentation + "layout=dot;\n") |
| 54 | |
| 55 | addNodes(&graphBuilder, graph, project.Name, &opts) |
| 56 | graphBuilder.WriteByte('\n') |
| 57 | |
| 58 | addEdges(&graphBuilder, graph, &opts) |
| 59 | graphBuilder.WriteString("}\n") |
| 60 | |
| 61 | return graphBuilder.String(), nil |
| 62 | } |
| 63 | |
| 64 | // addNodes adds the corresponding graphviz representation of all the nodes in the given graph to the graphBuilder |
| 65 | // returns the same graphBuilder |
nothing calls this directly
no test coverage detected