Skip to content

Commit

Permalink
WIP: add a layers subtree for image layers
Browse files Browse the repository at this point in the history
some TODOs, still need to think harder about the displaystring, and add
a useful summary.

also want to be able to toggle these globally, it's a lot to show them
for every image

Signed-off-by: Michael McCracken <mikmccra@cisco.com>
  • Loading branch information
mikemccracken committed Jun 6, 2024
1 parent f3a4032 commit ffdce00
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 2 deletions.
35 changes: 35 additions & 0 deletions ociutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
"text/tabwriter"
Expand Down Expand Up @@ -121,6 +122,40 @@ func (sr subIndexRef) summary() string {
return fmt.Sprintf("sub-index with %d manifests", len(info.manifestDescriptors))
}

type layerRef struct {
blobfilepath string
hash string
displayString string
}

var LayerSummaryCache = map[string]string{}

func (lr layerRef) summary(filter string) string {
layerfilterkey := lr.blobfilepath + "\\" + filter
cachedSummary, ok := LayerSummaryCache[layerfilterkey]
if ok {
return cachedSummary
}

filterArg := ""
if filter != "" {
filterArg = " | grep " + filter
}
cmdstr := "tar tzvf " + lr.blobfilepath + filterArg
cmd := exec.Command("sh", "-c", cmdstr)
var out strings.Builder
var stderr strings.Builder
cmd.Stdout = &out
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
log.Printf(fmt.Sprintf("error: %v", err))
}
summaryString := fmt.Sprintf("%q\n%q\n%s\n%s", lr.displayString, cmdstr, out.String(), stderr.String())
LayerSummaryCache[layerfilterkey] = summaryString
return summaryString
}

// ImageInfoMap - global map of manifest hashes to info
var ImageInfoMap = map[string]imageInfo{}

Expand Down
59 changes: 57 additions & 2 deletions ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,25 @@ func addContentsOfLayout(target *tview.TreeNode, path string) ([]imageInfo, []su

node.AddChild(refNode)
}

layerTreeNode := tview.NewTreeNode("layers").
SetReference(imageInfo.ref).
SetSelectable(true)
node.AddChild(layerTreeNode)

for _, layerDigest := range imageInfo.layerDigests {
displayString := layerDigest
if len(LayerNameMap[layerDigest]) > 0 {
displayString = strings.Join(LayerNameMap[layerDigest], ",")
}
blobfilepath := filepath.Join(path, "blobs", "sha256", layerDigest)
newLayerRef := layerRef{hash: layerDigest, blobfilepath: blobfilepath, displayString: displayString}
layerNode := tview.NewTreeNode(displayString).
SetReference(newLayerRef).
SetSelectable(true)
layerTreeNode.AddChild(layerNode)
}

target.AddChild(node)
log.Printf(" done loading image %q", imageInfo.displayName)
}
Expand Down Expand Up @@ -382,6 +401,9 @@ func getMatchingTreeNodes(node *tview.TreeNode, needle string) []*tview.TreeNode
case imageref:
haystacks = reference.(imageref).searchString()

case layerRef:
haystacks = []string{ref.hash, ref.displayString}

case subIndexRef:
haystacks = []string{}
info := SubIndexInfoMap[ref.hash]
Expand Down Expand Up @@ -435,6 +457,8 @@ func clearTreeFormatting(node *tview.TreeNode, selectable bool) {
node.SetColor(tcell.ColorBlue)
case imageref:
node.SetColor(tcell.ColorRed)
case layerRef:
node.SetColor(tcell.ColorGreen)
case subIndexRef:
node.SetColor(tcell.ColorBlue)
default:
Expand Down Expand Up @@ -550,7 +574,32 @@ func doTViewStuff(ctxt *cli.Context) error {
SetText(strings.Join(summaries, "\n")).
SetDynamicColors(true).
SetRegions(true)

infoPane.Box.SetBorder(true)
currentFilter := ""
summaryFilterField := tview.NewInputField().
SetLabel("Filter Output: ").
SetChangedFunc(func(needle string) {

currentFilter = needle

reference := tree.GetCurrentNode().GetReference()
switch ref := reference.(type) {
case layerRef:
infoPane.SetText(ref.summary(currentFilter))
}

// update info pane with summaries
})
summaryFilterField.SetDoneFunc(func(key tcell.Key) {
app.SetFocus(infoPane)
})

summaryFilterField.Box.SetBorder(true)

infoPaneGrid := tview.NewGrid().SetRows(0, 3).SetColumns(0).
AddItem(infoPane, 0, 0, 1, 1, 0, 0, true).
AddItem(summaryFilterField, 1, 0, 1, 1, 0, 0, false)

statusLine := tview.NewTextView().
SetTextAlign(tview.AlignCenter).
Expand All @@ -571,6 +620,8 @@ func doTViewStuff(ctxt *cli.Context) error {
infoPane.ScrollToBeginning()
case treeInfo:
infoPane.SetText(tview.Escape(ref.summary()))
case layerRef:
infoPane.SetText(ref.summary(currentFilter))
case subIndexRef:
infoPane.SetText(ref.summary())
default:
Expand All @@ -584,6 +635,10 @@ func doTViewStuff(ctxt *cli.Context) error {
case treeInfo:
infoPane.SetText(ref.summary())
infoPane.ScrollToBeginning()
case layerRef:
// todo mmcc didn't think through this behavior:
infoPane.SetText(ref.summary(currentFilter))
infoPane.ScrollToBeginning()
case subIndexRef:
infoPane.SetText(ref.summary())
default:
Expand Down Expand Up @@ -634,10 +689,10 @@ func doTViewStuff(ctxt *cli.Context) error {
SetRows(0, 1).
SetColumns(-1, -3).
AddItem(treeGrid, 0, 0, 1, 1, 0, 0, true).
AddItem(infoPane, 0, 1, 1, 1, 0, 0, false).
AddItem(infoPaneGrid, 0, 1, 1, 1, 0, 0, false).
AddItem(statusLine, 1, 0, 1, 2, 0, 0, false)

tabbableViews := []tview.Primitive{tree, searchInputField, infoPane}
tabbableViews := []tview.Primitive{tree, searchInputField, infoPane, summaryFilterField}
tabbableViewIdx := 0

setNewFocusedViewIdx := func(prevIdx int, newIdx int) {
Expand Down

0 comments on commit ffdce00

Please sign in to comment.