mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-07-27 13:57:46 +00:00
Merge branch 'graph-api' of https://github.com/lebauce/aptly into lebauce-graph-api
This commit is contained in:
@@ -0,0 +1,56 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/smira/aptly/graph"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GET /api/graph
|
||||||
|
func apiGraph(c *gin.Context) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
output []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
graph, err := graph.BuildGraph(context)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(500, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := bytes.NewBufferString(graph.String())
|
||||||
|
|
||||||
|
command := exec.Command("dot", "-Tpng")
|
||||||
|
command.Stderr = os.Stderr
|
||||||
|
|
||||||
|
stdin, err := command.StdinPipe()
|
||||||
|
if err != nil {
|
||||||
|
c.Fail(500, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(stdin, buf)
|
||||||
|
if err != nil {
|
||||||
|
c.Fail(500, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = stdin.Close()
|
||||||
|
if err != nil {
|
||||||
|
c.Fail(500, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err = command.Output()
|
||||||
|
if err != nil {
|
||||||
|
c.Fail(500, fmt.Errorf("unable to execute dot: %s (is graphviz package installed?)", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data(200, "image/png", output)
|
||||||
|
}
|
||||||
@@ -52,5 +52,9 @@ func Router(c *ctx.AptlyContext) http.Handler {
|
|||||||
root.DELETE("/publish/:prefix/:distribution", apiPublishDrop)
|
root.DELETE("/publish/:prefix/:distribution", apiPublishDrop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
root.GET("/graph", apiGraph)
|
||||||
|
}
|
||||||
|
|
||||||
return router
|
return router
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-117
@@ -2,15 +2,13 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"code.google.com/p/gographviz"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/smira/aptly/deb"
|
|
||||||
"github.com/smira/commander"
|
"github.com/smira/commander"
|
||||||
|
"github.com/smira/aptly/graph"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func aptlyGraph(cmd *commander.Command, args []string) error {
|
func aptlyGraph(cmd *commander.Command, args []string) error {
|
||||||
@@ -21,121 +19,11 @@ func aptlyGraph(cmd *commander.Command, args []string) error {
|
|||||||
return commander.ErrCommandError
|
return commander.ErrCommandError
|
||||||
}
|
}
|
||||||
|
|
||||||
graph := gographviz.NewEscape()
|
|
||||||
graph.SetDir(true)
|
|
||||||
graph.SetName("aptly")
|
|
||||||
|
|
||||||
existingNodes := map[string]bool{}
|
|
||||||
|
|
||||||
fmt.Printf("Loading mirrors...\n")
|
|
||||||
|
|
||||||
err = context.CollectionFactory().RemoteRepoCollection().ForEach(func(repo *deb.RemoteRepo) error {
|
|
||||||
err := context.CollectionFactory().RemoteRepoCollection().LoadComplete(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
graph.AddNode("aptly", repo.UUID, map[string]string{
|
|
||||||
"shape": "Mrecord",
|
|
||||||
"style": "filled",
|
|
||||||
"fillcolor": "darkgoldenrod1",
|
|
||||||
"label": fmt.Sprintf("{Mirror %s|url: %s|dist: %s|comp: %s|arch: %s|pkgs: %d}",
|
|
||||||
repo.Name, repo.ArchiveRoot, repo.Distribution, strings.Join(repo.Components, ", "),
|
|
||||||
strings.Join(repo.Architectures, ", "), repo.NumPackages()),
|
|
||||||
})
|
|
||||||
existingNodes[repo.UUID] = true
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Loading local repos...\n")
|
|
||||||
|
|
||||||
err = context.CollectionFactory().LocalRepoCollection().ForEach(func(repo *deb.LocalRepo) error {
|
|
||||||
err := context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
graph.AddNode("aptly", repo.UUID, map[string]string{
|
|
||||||
"shape": "Mrecord",
|
|
||||||
"style": "filled",
|
|
||||||
"fillcolor": "mediumseagreen",
|
|
||||||
"label": fmt.Sprintf("{Repo %s|comment: %s|pkgs: %d}",
|
|
||||||
repo.Name, repo.Comment, repo.NumPackages()),
|
|
||||||
})
|
|
||||||
existingNodes[repo.UUID] = true
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Loading snapshots...\n")
|
|
||||||
|
|
||||||
context.CollectionFactory().SnapshotCollection().ForEach(func(snapshot *deb.Snapshot) error {
|
|
||||||
existingNodes[snapshot.UUID] = true
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
err = context.CollectionFactory().SnapshotCollection().ForEach(func(snapshot *deb.Snapshot) error {
|
|
||||||
err := context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
description := snapshot.Description
|
|
||||||
if snapshot.SourceKind == "repo" {
|
|
||||||
description = "Snapshot from repo"
|
|
||||||
}
|
|
||||||
|
|
||||||
graph.AddNode("aptly", snapshot.UUID, map[string]string{
|
|
||||||
"shape": "Mrecord",
|
|
||||||
"style": "filled",
|
|
||||||
"fillcolor": "cadetblue1",
|
|
||||||
"label": fmt.Sprintf("{Snapshot %s|%s|pkgs: %d}", snapshot.Name, description, snapshot.NumPackages()),
|
|
||||||
})
|
|
||||||
|
|
||||||
if snapshot.SourceKind == "repo" || snapshot.SourceKind == "local" || snapshot.SourceKind == "snapshot" {
|
|
||||||
for _, uuid := range snapshot.SourceIDs {
|
|
||||||
_, exists := existingNodes[uuid]
|
|
||||||
if exists {
|
|
||||||
graph.AddEdge(uuid, snapshot.UUID, true, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Loading published repos...\n")
|
|
||||||
|
|
||||||
context.CollectionFactory().PublishedRepoCollection().ForEach(func(repo *deb.PublishedRepo) error {
|
|
||||||
graph.AddNode("aptly", repo.UUID, map[string]string{
|
|
||||||
"shape": "Mrecord",
|
|
||||||
"style": "filled",
|
|
||||||
"fillcolor": "darkolivegreen1",
|
|
||||||
"label": fmt.Sprintf("{Published %s/%s|comp: %s|arch: %s}", repo.Prefix, repo.Distribution,
|
|
||||||
strings.Join(repo.Components(), " "), strings.Join(repo.Architectures, ", ")),
|
|
||||||
})
|
|
||||||
|
|
||||||
for _, uuid := range repo.Sources {
|
|
||||||
_, exists := existingNodes[uuid]
|
|
||||||
if exists {
|
|
||||||
graph.AddEdge(uuid, repo.UUID, true, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
fmt.Printf("Generating graph...\n")
|
fmt.Printf("Generating graph...\n")
|
||||||
|
graph, err := graph.BuildGraph(context)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
buf := bytes.NewBufferString(graph.String())
|
buf := bytes.NewBufferString(graph.String())
|
||||||
|
|
||||||
|
|||||||
+121
@@ -0,0 +1,121 @@
|
|||||||
|
package graph
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.google.com/p/gographviz"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"github.com/smira/aptly/context"
|
||||||
|
"github.com/smira/aptly/deb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BuildGraph(context *context.AptlyContext) (gographviz.Interface, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
graph := gographviz.NewEscape()
|
||||||
|
graph.SetDir(true)
|
||||||
|
graph.SetName("aptly")
|
||||||
|
|
||||||
|
existingNodes := map[string]bool{}
|
||||||
|
|
||||||
|
err = context.CollectionFactory().RemoteRepoCollection().ForEach(func(repo *deb.RemoteRepo) error {
|
||||||
|
err := context.CollectionFactory().RemoteRepoCollection().LoadComplete(repo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
graph.AddNode("aptly", repo.UUID, map[string]string{
|
||||||
|
"shape": "Mrecord",
|
||||||
|
"style": "filled",
|
||||||
|
"fillcolor": "darkgoldenrod1",
|
||||||
|
"label": fmt.Sprintf("{Mirror %s|url: %s|dist: %s|comp: %s|arch: %s|pkgs: %d}",
|
||||||
|
repo.Name, repo.ArchiveRoot, repo.Distribution, strings.Join(repo.Components, ", "),
|
||||||
|
strings.Join(repo.Architectures, ", "), repo.NumPackages()),
|
||||||
|
})
|
||||||
|
existingNodes[repo.UUID] = true
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = context.CollectionFactory().LocalRepoCollection().ForEach(func(repo *deb.LocalRepo) error {
|
||||||
|
err := context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
graph.AddNode("aptly", repo.UUID, map[string]string{
|
||||||
|
"shape": "Mrecord",
|
||||||
|
"style": "filled",
|
||||||
|
"fillcolor": "mediumseagreen",
|
||||||
|
"label": fmt.Sprintf("{Repo %s|comment: %s|pkgs: %d}",
|
||||||
|
repo.Name, repo.Comment, repo.NumPackages()),
|
||||||
|
})
|
||||||
|
existingNodes[repo.UUID] = true
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
context.CollectionFactory().SnapshotCollection().ForEach(func(snapshot *deb.Snapshot) error {
|
||||||
|
existingNodes[snapshot.UUID] = true
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
err = context.CollectionFactory().SnapshotCollection().ForEach(func(snapshot *deb.Snapshot) error {
|
||||||
|
err := context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
description := snapshot.Description
|
||||||
|
if snapshot.SourceKind == "repo" {
|
||||||
|
description = "Snapshot from repo"
|
||||||
|
}
|
||||||
|
|
||||||
|
graph.AddNode("aptly", snapshot.UUID, map[string]string{
|
||||||
|
"shape": "Mrecord",
|
||||||
|
"style": "filled",
|
||||||
|
"fillcolor": "cadetblue1",
|
||||||
|
"label": fmt.Sprintf("{Snapshot %s|%s|pkgs: %d}", snapshot.Name, description, snapshot.NumPackages()),
|
||||||
|
})
|
||||||
|
|
||||||
|
if snapshot.SourceKind == "repo" || snapshot.SourceKind == "local" || snapshot.SourceKind == "snapshot" {
|
||||||
|
for _, uuid := range snapshot.SourceIDs {
|
||||||
|
_, exists := existingNodes[uuid]
|
||||||
|
if exists {
|
||||||
|
graph.AddEdge(uuid, snapshot.UUID, true, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
context.CollectionFactory().PublishedRepoCollection().ForEach(func(repo *deb.PublishedRepo) error {
|
||||||
|
graph.AddNode("aptly", repo.UUID, map[string]string{
|
||||||
|
"shape": "Mrecord",
|
||||||
|
"style": "filled",
|
||||||
|
"fillcolor": "darkolivegreen1",
|
||||||
|
"label": fmt.Sprintf("{Published %s/%s|comp: %s|arch: %s}", repo.Prefix, repo.Distribution,
|
||||||
|
strings.Join(repo.Components(), " "), strings.Join(repo.Architectures, ", ")),
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, uuid := range repo.Sources {
|
||||||
|
_, exists := existingNodes[uuid]
|
||||||
|
if exists {
|
||||||
|
graph.AddEdge(uuid, repo.UUID, true, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return graph, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user