Skip to content
This repository has been archived by the owner on Dec 26, 2023. It is now read-only.

introduce list instances command #34

Merged
merged 1 commit into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 8 additions & 23 deletions cmd/cli/list_definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ func init() {

var listDefinitionsCmd = &cobra.Command{
Use: "definitions",
Short: "List layer definitions",
Short: "List layers definitions",
Long: `List layers definitions.

Prints a table of the most important information about layer definitions.`,

RunE: func(cmd *cobra.Command, args []string) error {
RunE: func(_ *cobra.Command, _ []string) error {
logger := hclog.Default()
logLevel := hclog.LevelFromString(os.Getenv("LF_LOG"))
if logLevel != hclog.NoLevel {
Expand Down Expand Up @@ -55,7 +55,7 @@ Prints a table of the most important information about layer definitions.`,
return errors.Wrap(err, "fail to print output")
}

layers = sortLayersByDepth(layers)
sortLayersByDepth(layers)

w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
fmt.Fprintln(w, "NAME\tDEPENDENCIES")
Expand All @@ -69,31 +69,16 @@ Prints a table of the most important information about layer definitions.`,
},
}

func sortLayersByDepth(layers []*model.Layer) []*model.Layer {
func sortLayersByDepth(layers []*model.Layer) {
byName := make(map[string]*model.Layer)
for _, l := range layers {
byName[l.Name] = l
}

depthArr := make([]int, len(layers))
for i, l := range layers {
depth := 0
deps := l.Dependencies
for len(deps) > 0 {
d := deps[0]
deps = deps[1:]
depth += 1

depDeps := byName[d].Dependencies
deps = append(deps, depDeps...)
}

depthArr[i] = depth
}

sort.SliceStable(layers, func(x, y int) bool {
return depthArr[x] < depthArr[y]
})
lx := layers[x]
ly := layers[y]

return layers
return computeDepth(lx, byName, 0) < computeDepth(ly, byName, 0)
})
}
121 changes: 121 additions & 0 deletions cmd/cli/list_instances.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package cli

import (
"context"
"fmt"
"os"
"sort"
"text/tabwriter"

"github.com/hashicorp/go-hclog"
"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/ergomake/layerform/internal/data/model"
"github.com/ergomake/layerform/internal/layerstate"
"github.com/ergomake/layerform/internal/lfconfig"
)

func init() {
listCmd.AddCommand(listInstancesCmd)
}

var listInstancesCmd = &cobra.Command{
Use: "instances",
Short: "List layers instances",
Long: `List layers instances.

Prints a table of the most important information about layer instances.`,

RunE: func(_ *cobra.Command, _ []string) error {
logger := hclog.Default()
logLevel := hclog.LevelFromString(os.Getenv("LF_LOG"))
if logLevel != hclog.NoLevel {
logger.SetLevel(logLevel)
}
ctx := hclog.WithContext(context.Background(), logger)

cfg, err := lfconfig.Load("")
if err != nil {
return errors.Wrap(err, "fail to load config")
}

layersBackend, err := cfg.GetLayersBackend(ctx)
if err != nil {
return errors.Wrap(err, "fail to get layers backend")
}

instancesBackend, err := cfg.GetStateBackend(ctx)
if err != nil {
return errors.Wrap(err, "fail to get layers instances backend")
}

instances, err := instancesBackend.ListStates(ctx)
if err != nil {
return errors.Wrap(err, "fail to list layer instances")
}

if len(instances) == 0 {
_, err := fmt.Println("No layer instances are spawned, spawn layers by running \"layerform spawn\"")
return errors.Wrap(err, "fail to print output")
}

layers, err := layersBackend.ListLayers(ctx)
if err != nil {
return errors.Wrap(err, "fail to list layer definitions")
}

layersByName := make(map[string]*model.Layer)
for _, l := range layers {
layersByName[l.Name] = l
}

sortInstancesByDepth(instances, layersByName)

w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
fmt.Fprintln(w, "INSTANCE NAME\tLAYER NAME\tDEPENDENCIES")
for _, instance := range instances {
layer := layersByName[instance.LayerName]
deps := ""
for i, dep := range layer.Dependencies {
if i > 0 {
deps += ","
}

depInstName := instance.GetDependencyStateName(dep)
deps += dep + "=" + depInstName
}

fmt.Fprintln(w, instance.StateName+"\t"+instance.LayerName+"\t"+deps)
}
err = w.Flush()

return errors.Wrap(err, "fail to print output")
},
}

func computeDepth(layer *model.Layer, layers map[string]*model.Layer, level int) int {
depth := level
for _, d := range layer.Dependencies {
dDepth := computeDepth(layers[d], layers, level+1)
if dDepth > depth {
depth = dDepth
}
}

return depth
}

func sortInstancesByDepth(instances []*layerstate.State, layers map[string]*model.Layer) {
sort.SliceStable(instances, func(x, y int) bool {
instX := instances[x]
layerX := layers[instX.LayerName]
depthX := computeDepth(layerX, layers, 0)

instY := instances[y]
layerY := layers[instY.LayerName]
depthY := computeDepth(layerY, layers, 0)

return depthX < depthY
})
}
6 changes: 6 additions & 0 deletions internal/layerstate/filelike.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,9 @@ func (flb *fileLikeBackend) ListStatesByLayer(ctx context.Context, layerName str

return result, nil
}

func (flb *fileLikeBackend) ListStates(ctx context.Context) ([]*State, error) {
hclog.FromContext(ctx).Debug("Listing all layers states")

return flb.model.States, nil
}
1 change: 1 addition & 0 deletions internal/layerstate/states.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ type Backend interface {
ListStatesByLayer(ctx context.Context, layerName string) ([]*State, error)
SaveState(ctx context.Context, state *State) error
DeleteState(ctx context.Context, layerName, stateName string) error
ListStates(ctx context.Context) ([]*State, error)
}