Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
po3rin committed Jun 14, 2019
0 parents commit 9db89f8
Show file tree
Hide file tree
Showing 28 changed files with 3,345 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"go.formatTool": "goimports"
}
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build:
GOOS=js GOARCH=wasm go build -o main.wasm
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# dockerbot

in development ...

## Warn

dockerbot/dockerfile2llb package is copied from moby/buildkit. but sygnal package is not used.
99 changes: 99 additions & 0 deletions docker2dot/docker2dot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package docker2dot

import (
"bytes"
"context"
"fmt"
"io"
"strings"

"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/solver/pb"
digest "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/po3rin/dockerdot/dockerfile2llb"
)

// Docker2Dot convert dockerfile to llb Expressed in DOT language.
func Docker2Dot(df []byte) ([]byte, error) {
st, img, err := dockerfile2llb.Dockerfile2LLB(context.Background(), df, dockerfile2llb.ConvertOpt{})
if err != nil {
return nil, err
}

// ignore image
_ = img

def, err := st.Marshal()
if err != nil {
return nil, err
}

ops, err := loadLLB(def)
if err != nil {
return nil, err
}

var b bytes.Buffer
writeDot(ops, &b)
result := b.Bytes()

return result, nil
}

type llbOp struct {
Op pb.Op
Digest digest.Digest
OpMetadata pb.OpMetadata
}

// loadLLB load llbOp from llb.Definition.
func loadLLB(def *llb.Definition) ([]llbOp, error) {
var ops []llbOp
for _, dt := range def.Def {
var op pb.Op
if err := (&op).Unmarshal(dt); err != nil {
return nil, errors.Wrap(err, "failed to parse op")
}
dgst := digest.FromBytes(dt)
ent := llbOp{Op: op, Digest: dgst, OpMetadata: def.Metadata[dgst]}
ops = append(ops, ent)
}
return ops, nil
}

func writeDot(ops []llbOp, w io.Writer) {
// TODO: print OpMetadata
fmt.Fprintln(w, "digraph {")
defer fmt.Fprintln(w, "}")
for _, op := range ops {
name, shape := attr(op.Digest, op.Op)
fmt.Fprintf(w, " %q [label=%q shape=%q];\n", op.Digest, name, shape)
}
for _, op := range ops {
for i, inp := range op.Op.Inputs {
label := ""
if eo, ok := op.Op.Op.(*pb.Op_Exec); ok {
for _, m := range eo.Exec.Mounts {
if int(m.Input) == i && m.Dest != "/" {
label = m.Dest
}
}
}
fmt.Fprintf(w, " %q -> %q [label=%q];\n", inp.Digest, op.Digest, label)
}
}
}

func attr(dgst digest.Digest, op pb.Op) (string, string) {
switch op := op.Op.(type) {
case *pb.Op_Source:
return op.Source.Identifier, "ellipse"
case *pb.Op_Exec:
return strings.Join(op.Exec.Meta.Args, " "), "box"
case *pb.Op_Build:
return "build", "box3d"
default:
return dgst.String(), "plaintext"
}
}
Loading

0 comments on commit 9db89f8

Please sign in to comment.