added layer info

This commit is contained in:
Alex Goodman 2018-06-07 18:56:22 -04:00
parent e67734d38d
commit a8cc8db4a5
No known key found for this signature in database
GPG Key ID: 05328C611D8A520E
6 changed files with 111 additions and 50 deletions

24
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,24 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "debug",
"remotePath": "",
"port": 2345,
"host": "127.0.0.1",
"program": "${workspaceRoot}/cmd/die/main.go",
"externalConsole": true,
"env": {
"TERM": "xterm-256color"
},
"args": ["die-test"],
"showLog": true
}
]
}

View File

@ -208,9 +208,10 @@ func (tree *FileTree) MarkRemoved(path string) error {
return node.AssignDiffType(Removed)
}
func StackRange(trees []*FileTree, index uint) *FileTree {
func StackRange(trees []*FileTree, index int) *FileTree {
// TMP TMP TMP: TODO: later change the index of both of these to 0
tree := trees[1].Copy()
for idx := uint(1); idx <= index; idx++ {
for idx := 1; idx <= index; idx++ {
tree.Stack(trees[idx])
}
return tree

View File

@ -12,7 +12,9 @@ import (
"path/filepath"
"strings"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
humanize "github.com/dustin/go-humanize"
"github.com/wagoodman/docker-image-explorer/filetree"
"golang.org/x/net/context"
)
@ -24,9 +26,9 @@ func check(e error) {
}
type ImageManifest struct {
Config string
RepoTags []string
Layers []string
ConfigPath string `json:"Config"`
RepoTags []string `json:"RepoTags"`
LayerTarPaths []string `json:"Layers"`
}
func NewManifest(reader *tar.Reader, header *tar.Header) ImageManifest {
@ -44,24 +46,37 @@ func NewManifest(reader *tar.Reader, header *tar.Header) ImageManifest {
return m[0]
}
func InitializeData(imageID string) (*ImageManifest, []*filetree.FileTree) {
imageTarPath, tmpDir := saveImage(imageID)
type Layer struct {
TarPath string
History types.ImageHistory
}
f, err := os.Open(imageTarPath)
func (layer *Layer) String() string {
id := layer.History.ID[0:25]
if len(layer.History.Tags) > 0 {
id = "[" + strings.Join(layer.History.Tags, ",") + "]"
}
return fmt.Sprintf("%25s %7s %s", id, humanize.Bytes(uint64(layer.History.Size)), layer.History.CreatedBy)
}
func InitializeData(imageID string) ([]*Layer, []*filetree.FileTree) {
var manifest ImageManifest
var layerMap = make(map[string]*filetree.FileTree)
var trees []*filetree.FileTree = make([]*filetree.FileTree, 0)
// save this image to disk temporarily to get the content info
imageTarPath, tmpDir := saveImage(imageID)
defer os.RemoveAll(tmpDir)
// read through the image contents and build a tree
tarFile, err := os.Open(imageTarPath)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer tarFile.Close()
defer f.Close()
defer os.RemoveAll(tmpDir)
tarReader := tar.NewReader(f)
targetName := "manifest.json"
var manifest ImageManifest
var layerMap map[string]*filetree.FileTree
layerMap = make(map[string]*filetree.FileTree)
tarReader := tar.NewReader(tarFile)
for {
header, err := tarReader.Next()
@ -75,7 +90,7 @@ func InitializeData(imageID string) (*ImageManifest, []*filetree.FileTree) {
}
name := header.Name
if name == targetName {
if name == "manifest.json" {
manifest = NewManifest(tarReader, header)
}
@ -96,13 +111,30 @@ func InitializeData(imageID string) (*ImageManifest, []*filetree.FileTree) {
fmt.Printf("ERRG: unknown tar entry: %v: %s\n", header.Typeflag, name)
}
}
var trees []*filetree.FileTree
trees = make([]*filetree.FileTree, 0)
for _, treeName := range manifest.Layers {
// build the content tree
for _, treeName := range manifest.LayerTarPaths {
trees = append(trees, layerMap[treeName])
}
return &manifest, trees
// get the history of this image
ctx := context.Background()
dockerClient, err := client.NewEnvClient()
if err != nil {
panic(err)
}
history, err := dockerClient.ImageHistory(ctx, imageID)
// build the layers array
layers := make([]*Layer, len(history)-1)
for idx := 0; idx < len(layers); idx++ {
layers[idx] = new(Layer)
layers[idx].History = history[idx]
layers[idx].TarPath = manifest.LayerTarPaths[idx]
}
return layers, trees
}
func saveImage(imageID string) (string, string) {
@ -154,14 +186,14 @@ func saveImage(imageID string) (string, string) {
func getFileList(parentReader *tar.Reader, h *tar.Header) []filetree.FileChangeInfo {
var files []filetree.FileChangeInfo
size := h.Size
tarredBytes := make([]byte, size)
var tarredBytes = make([]byte, h.Size)
_, err := parentReader.Read(tarredBytes)
if err != nil {
panic(err)
}
r := bytes.NewReader(tarredBytes)
tarReader := tar.NewReader(r)
reader := bytes.NewReader(tarredBytes)
tarReader := tar.NewReader(reader)
for {
header, err := tarReader.Next()

View File

@ -11,7 +11,7 @@ type FileTreeView struct {
Name string
gui *gocui.Gui
view *gocui.View
TreeIndex uint
TreeIndex int
Tree *filetree.FileTree
RefTrees []*filetree.FileTree
}
@ -54,7 +54,7 @@ func (view *FileTreeView) Setup(v *gocui.View) error {
return nil
}
func (view *FileTreeView) setLayer(layerIndex uint) error {
func (view *FileTreeView) setLayer(layerIndex int) error {
view.Tree = filetree.StackRange(view.RefTrees, layerIndex-1)
view.Tree.Compare(view.RefTrees[layerIndex])
v, _ := view.gui.View("debug")
@ -84,7 +84,7 @@ func (view *FileTreeView) CursorUp() error {
func (view *FileTreeView) getAbsPositionNode() (node *filetree.FileNode) {
var visiter func(*filetree.FileNode) error
var evaluator func(*filetree.FileNode) bool
var dfsCounter uint
var dfsCounter int
visiter = func(curNode *filetree.FileNode) error {
if dfsCounter == view.TreeIndex {

View File

@ -11,17 +11,17 @@ type LayerView struct {
Name string
gui *gocui.Gui
view *gocui.View
LayerIndex uint
Manifest *image.ImageManifest
LayerIndex int
Layers []*image.Layer
}
func NewLayerView(name string, gui *gocui.Gui, manifest *image.ImageManifest) (layerview *LayerView) {
func NewLayerView(name string, gui *gocui.Gui, layers []*image.Layer) (layerview *LayerView) {
layerview = new(LayerView)
// populate main fields
layerview.Name = name
layerview.gui = gui
layerview.Manifest = manifest
layerview.Layers = layers
return layerview
}
@ -30,7 +30,7 @@ func (view *LayerView) Setup(v *gocui.View) error {
// set view options
view.view = v
view.view.Wrap = true
view.view.Wrap = false
view.view.Highlight = true
view.view.SelBgColor = gocui.ColorGreen
view.view.SelFgColor = gocui.ColorBlack
@ -51,8 +51,9 @@ func (view *LayerView) Setup(v *gocui.View) error {
func (view *LayerView) Render() error {
view.gui.Update(func(g *gocui.Gui) error {
view.view.Clear()
for ix, layerName := range view.Manifest.Layers {
fmt.Fprintf(view.view, "%d: %s\n", ix+1, layerName[0:25])
for idx := len(view.Layers) - 1; idx >= 0; idx-- {
layer := view.Layers[idx]
fmt.Fprintln(view.view, layer.String())
}
return nil
})
@ -61,22 +62,25 @@ func (view *LayerView) Render() error {
}
func (view *LayerView) CursorDown() error {
if int(view.LayerIndex) < len(view.Manifest.Layers) {
CursorDown(view.gui, view.view)
view.LayerIndex++
view.Render()
Views.Tree.setLayer(view.LayerIndex)
if int(view.LayerIndex) < len(view.Layers) {
err := CursorDown(view.gui, view.view)
if err == nil {
view.LayerIndex++
view.Render()
Views.Tree.setLayer(view.LayerIndex)
}
}
return nil
}
func (view *LayerView) CursorUp() error {
if int(view.LayerIndex) > 0 {
CursorUp(view.gui, view.view)
view.LayerIndex--
view.Render()
// this line is evil
Views.Tree.setLayer(view.LayerIndex)
err := CursorUp(view.gui, view.view)
if err == nil {
view.LayerIndex--
view.Render()
Views.Tree.setLayer(view.LayerIndex)
}
}
return nil
}

View File

@ -76,8 +76,8 @@ func keybindings(g *gocui.Gui) error {
func layout(g *gocui.Gui) error {
maxX, maxY := g.Size()
splitCol := 50
debugCol := maxX - 100
splitCol := 100
debugCol := maxX - 70
if view, err := g.SetView(Views.Layer.Name, -1, -1, splitCol, maxY); err != nil {
if err != gocui.ErrUnknownView {
return err
@ -105,7 +105,7 @@ func layout(g *gocui.Gui) error {
return nil
}
func Run(manifest *image.ImageManifest, refTrees []*filetree.FileTree) {
func Run(layers []*image.Layer, refTrees []*filetree.FileTree) {
g, err := gocui.NewGui(gocui.OutputNormal)
if err != nil {
@ -113,7 +113,7 @@ func Run(manifest *image.ImageManifest, refTrees []*filetree.FileTree) {
}
defer g.Close()
Views.Layer = NewLayerView("side", g, manifest)
Views.Layer = NewLayerView("side", g, layers)
Views.Tree = NewFileTreeView("main", g, filetree.StackRange(refTrees, 0), refTrees)
g.Cursor = false