Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extracting filesystem accesses; 'workspace inspect' command #13

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
44 changes: 15 additions & 29 deletions cmd/warpforge/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/warpfork/warpforge/pkg/dab"
"github.com/warpfork/warpforge/pkg/formulaexec"
"github.com/warpfork/warpforge/pkg/plotexec"
"github.com/warpfork/warpforge/wfapi"
)

Expand Down Expand Up @@ -127,42 +128,27 @@ func cmdStatus(c *cli.Context) error {
len(plot.Steps.Keys),
len(plot.Outputs.Keys))

// check for missing catalog refs
// Load up workspaces; we'll need to read them to check for missing catalog refs.
wss, err := openWorkspaceSet(fsys)
if err != nil {
return fmt.Errorf("failed to open workspace: %s", err)
}
catalogRefCount := 0
resolvedCatalogRefCount := 0
ingestCount := 0
mountCount := 0
for _, input := range plot.Inputs.Values {
if input.Basis().Mount != nil {
mountCount++
} else if input.Basis().Ingest != nil {
ingestCount++
} else if input.Basis().CatalogRef != nil {
catalogRefCount++
ware, _, err := wss.GetCatalogWare(*input.PlotInputSimple.CatalogRef)
if err != nil {
return fmt.Errorf("failed to lookup catalog ref: %s", err)
}
if ware == nil {
fmt.Fprintf(c.App.Writer, "\tMissing catalog item: %q.\n", input.Basis().CatalogRef.String())
} else if err == nil {
resolvedCatalogRefCount++
}
}

// Compute stats on the plot and report on them (especially any problematic ones).
plotStats, err := plotexec.ComputeStats(plot, wss)

fmt.Fprintf(c.App.Writer, "\tPlot contains %d catalog inputs. %d/%d catalog inputs resolved successfully.\n", plotStats.InputsUsingCatalog, plotStats.ResolvableCatalogInputs, plotStats.InputsUsingCatalog)
if plotStats.ResolvableCatalogInputs < plotStats.InputsUsingCatalog {
fmt.Fprintf(c.App.Writer, "\tWarning: plot contains %d unresolved catalog inputs!\n", (plotStats.InputsUsingCatalog - plotStats.ResolvableCatalogInputs))
}
fmt.Fprintf(c.App.Writer, "\tPlot contains %d catalog inputs. %d/%d catalog inputs resolved successfully.\n", catalogRefCount, resolvedCatalogRefCount, catalogRefCount)
if resolvedCatalogRefCount < catalogRefCount {
fmt.Fprintf(c.App.Writer, "\tWarning: plot contains %d unresolved catalog inputs!\n", (catalogRefCount - resolvedCatalogRefCount))
for k, _ := range plotStats.UnresolvedCatalogInputs {
fmt.Fprintf(c.App.Writer, "\tMissing catalog item: %q.\n", k.String())
}
if ingestCount > 0 {
fmt.Fprintf(c.App.Writer, "\tWarning: plot contains %d ingest inputs and is not hermetic!\n", ingestCount)
if plotStats.InputsUsingIngest > 0 {
fmt.Fprintf(c.App.Writer, "\tWarning: plot contains %d ingest inputs and is not hermetic!\n", plotStats.InputsUsingIngest)
}
if mountCount > 0 {
fmt.Fprintf(c.App.Writer, "\tWarning: plot contains %d mount inputs and is not hermetic!\n", mountCount)
if plotStats.InputsUsingMount > 0 {
fmt.Fprintf(c.App.Writer, "\tWarning: plot contains %d mount inputs and is not hermetic!\n", plotStats.InputsUsingMount)
}

} else if isModule {
Expand Down
57 changes: 57 additions & 0 deletions pkg/plotexec/plot_stats.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package plotexec

import (
"github.com/warpfork/warpforge/pkg/workspace"
"github.com/warpfork/warpforge/wfapi"
)

// Might not match the package name -- funcs in this file certainly don't exec anything.
Copy link
Collaborator

@TripleDogDare TripleDogDare Aug 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So? I don't really care and I don't think this comment is useful.


type PlotStats struct {
InputsUsingCatalog int
InputsUsingIngest int
InputsUsingMount int
ResolvableCatalogInputs int
ResolvedCatalogInputs map[wfapi.CatalogRef]wfapi.WareID // might as well remember it if we already did all that work.
UnresolvedCatalogInputs map[wfapi.CatalogRef]struct{}
}

// ComputeStats counts up how many times a plot uses various features,
// and also checks for reference resolvablity.
func ComputeStats(plot wfapi.Plot, wsSet workspace.WorkspaceSet) (PlotStats, error) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The is one thing in this PR that should definitely be rescued: this ComputeStats function is more correct than where it was hoisted from. The old occurrence isn't recursive, which is... wrong.

v := PlotStats{
ResolvedCatalogInputs: make(map[wfapi.CatalogRef]wfapi.WareID),
UnresolvedCatalogInputs: make(map[wfapi.CatalogRef]struct{}),
}
for _, input := range plot.Inputs.Values {
inputBasis := input.Basis() // unwrap if it's a complex filtered thing.
switch {
// This switch should be exhaustive on the possible members of PlotInputSimple.
case inputBasis.WareID != nil:
// not interesting :)
case inputBasis.Mount != nil:
v.InputsUsingMount++
case inputBasis.Literal != nil:
// not interesting :)
case inputBasis.Pipe != nil:
// not interesting :)
case inputBasis.CatalogRef != nil:
v.InputsUsingCatalog++
ware, _, err := wsSet.GetCatalogWare(*inputBasis.CatalogRef)
if err != nil {
return v, err // These mean catalog read failed entirely, so we're in deep water.
}
if ware == nil {
v.UnresolvedCatalogInputs[*inputBasis.CatalogRef] = struct{}{}
} else {
v.ResolvableCatalogInputs++
v.ResolvedCatalogInputs[*inputBasis.CatalogRef] = *ware
}
case inputBasis.Ingest != nil:
v.InputsUsingIngest++
default:
panic("unreachable")
}
}
return v, nil
}