From b8c7fadc86f446eb394d2ff1cbf7b881ca8f1827 Mon Sep 17 00:00:00 2001 From: David Gamba Date: Tue, 5 Mar 2024 22:48:54 -0700 Subject: [PATCH] bt: unify dag generation for graph and build command Also enable non-workspaces components in stacks. --- bt/stack/build.go | 63 +-------------------------- bt/stack/dag.go | 106 ++++++++++++++++++++++++++++++++++++++++++++++ bt/stack/graph.go | 53 ++--------------------- 3 files changed, 112 insertions(+), 110 deletions(-) create mode 100644 bt/stack/dag.go diff --git a/bt/stack/build.go b/bt/stack/build.go index 009f11b..a38cc3f 100644 --- a/bt/stack/build.go +++ b/bt/stack/build.go @@ -7,9 +7,7 @@ import ( "github.com/DavidGamba/dgtools/bt/config" sconfig "github.com/DavidGamba/dgtools/bt/stack/config" - "github.com/DavidGamba/dgtools/bt/terraform" "github.com/DavidGamba/go-getoptions" - "github.com/DavidGamba/go-getoptions/dag" ) func BuildCMD(ctx context.Context, parent *getoptions.GetOpt) *getoptions.GetOpt { @@ -50,66 +48,9 @@ func BuildRun(ctx context.Context, opt *getoptions.GetOpt, args []string) error cfg := sconfig.ConfigFromContext(ctx) - tm := dag.NewTaskMap() - g := dag.NewGraph("stack " + id) - - fn := func(dir string) getoptions.CommandFn { - return func(ctx context.Context, opt *getoptions.GetOpt, args []string) error { - return nil - } - } - wsFn := func(component, dir, ws string) getoptions.CommandFn { - return func(ctx context.Context, opt *getoptions.GetOpt, args []string) error { - ctx = terraform.NewComponentContext(ctx, fmt.Sprintf("%s:%s", component, ws)) - ctx = terraform.NewDirContext(ctx, dir) - err := opt.SetValue("ws", ws) - if err != nil { - return fmt.Errorf("failed to set workspace: %w", err) - } - return terraform.BuildRun(ctx, opt, args) - } - } - - for _, c := range cfg.Stack[sconfig.ID(id)].Components { - cID := string(c.ID) - tm.Add(cID, fn(cID)) - g.AddTask(tm.Get(cID)) - for _, w := range c.Workspaces { - wID := fmt.Sprintf("%s:%s", c.ID, w) - tm.Add(wID, wsFn(string(c.ID), c.Path, w)) - g.AddTask(tm.Get(wID)) - - if normal { - g.TaskDependensOn(tm.Get(cID), tm.Get(wID)) - } else { - g.TaskDependensOn(tm.Get(wID), tm.Get(cID)) - } - } - } - - for _, c := range cfg.Stack[sconfig.ID(id)].Components { - if normal { - for _, e := range c.DependsOn { - eID := e - for _, w := range c.Workspaces { - wID := fmt.Sprintf("%s:%s", c.ID, w) - g.TaskDependensOn(tm.Get(wID), tm.Get(eID)) - } - } - } else { - for _, e := range c.DependsOn { - eID := e - for _, w := range c.Workspaces { - wID := fmt.Sprintf("%s:%s", c.ID, w) - g.TaskDependensOn(tm.Get(eID), tm.Get(wID)) - } - } - } - } - - err := g.Validate(tm) + g, err := generateDAG(id, cfg, normal) if err != nil { - return fmt.Errorf("failed to build graph: %w", err) + return err } if serial { diff --git a/bt/stack/dag.go b/bt/stack/dag.go new file mode 100644 index 0000000..b6f8696 --- /dev/null +++ b/bt/stack/dag.go @@ -0,0 +1,106 @@ +package stack + +import ( + "context" + "fmt" + + sconfig "github.com/DavidGamba/dgtools/bt/stack/config" + "github.com/DavidGamba/dgtools/bt/terraform" + "github.com/DavidGamba/go-getoptions" + "github.com/DavidGamba/go-getoptions/dag" +) + +func generateDAG(id string, cfg *sconfig.Config, normal bool) (*dag.Graph, error) { + tm := dag.NewTaskMap() + g := dag.NewGraph("stack " + id) + + emptyFn := func(dir string) getoptions.CommandFn { + return func(ctx context.Context, opt *getoptions.GetOpt, args []string) error { + return nil + } + } + normalFn := func(component, dir string) getoptions.CommandFn { + return func(ctx context.Context, opt *getoptions.GetOpt, args []string) error { + ctx = terraform.NewComponentContext(ctx, component) + ctx = terraform.NewDirContext(ctx, dir) + return terraform.BuildRun(ctx, opt, args) + } + } + wsFn := func(component, dir, ws string) getoptions.CommandFn { + return func(ctx context.Context, opt *getoptions.GetOpt, args []string) error { + ctx = terraform.NewComponentContext(ctx, fmt.Sprintf("%s:%s", component, ws)) + ctx = terraform.NewDirContext(ctx, dir) + err := opt.SetValue("ws", ws) + if err != nil { + return fmt.Errorf("failed to set workspace: %w", err) + } + return terraform.BuildRun(ctx, opt, args) + } + } + + for _, c := range cfg.Stack[sconfig.ID(id)].Components { + cID := string(c.ID) + + if len(c.Workspaces) > 0 { + // workspace mode + tm.Add(cID, emptyFn(cID)) + g.AddTask(tm.Get(cID)) + for _, w := range c.Workspaces { + wID := fmt.Sprintf("%s:%s", cID, w) + tm.Add(wID, wsFn(cID, c.Path, w)) + g.AddTask(tm.Get(wID)) + + if normal { + g.TaskDependensOn(tm.Get(cID), tm.Get(wID)) + } else { + g.TaskDependensOn(tm.Get(wID), tm.Get(cID)) + } + } + } else { + // normal mode + tm.Add(cID, normalFn(cID, c.Path)) + g.AddTask(tm.Get(cID)) + } + } + + for _, c := range cfg.Stack[sconfig.ID(id)].Components { + cID := string(c.ID) + + if normal { + for _, e := range c.DependsOn { + eID := e + if len(c.Workspaces) > 0 { + // workspace mode + for _, w := range c.Workspaces { + wID := fmt.Sprintf("%s:%s", cID, w) + g.TaskDependensOn(tm.Get(wID), tm.Get(eID)) + } + } else { + // normal mode + g.TaskDependensOn(tm.Get(cID), tm.Get(eID)) + } + } + } else { + for _, e := range c.DependsOn { + eID := e + if len(c.Workspaces) > 0 { + // workspace mode + for _, w := range c.Workspaces { + wID := fmt.Sprintf("%s:%s", cID, w) + g.TaskDependensOn(tm.Get(eID), tm.Get(wID)) + } + } else { + // normal mode + g.TaskDependensOn(tm.Get(eID), tm.Get(cID)) + } + } + } + } + + err := g.Validate(tm) + if err != nil { + return g, fmt.Errorf("failed to build graph: %w", err) + } + + return g, nil +} diff --git a/bt/stack/graph.go b/bt/stack/graph.go index 235a15c..4168b2a 100644 --- a/bt/stack/graph.go +++ b/bt/stack/graph.go @@ -5,10 +5,9 @@ import ( "fmt" "os" - "github.com/DavidGamba/dgtools/bt/stack/config" + sconfig "github.com/DavidGamba/dgtools/bt/stack/config" "github.com/DavidGamba/dgtools/run" "github.com/DavidGamba/go-getoptions" - "github.com/DavidGamba/go-getoptions/dag" ) func GraphCMD(ctx context.Context, parent *getoptions.GetOpt) *getoptions.GetOpt { @@ -39,55 +38,11 @@ func GraphRun(ctx context.Context, opt *getoptions.GetOpt, args []string) error normal := !reverse - cfg := config.ConfigFromContext(ctx) + cfg := sconfig.ConfigFromContext(ctx) - tm := dag.NewTaskMap() - g := dag.NewGraph("stack " + id) - - fn := func(ctx context.Context, opt *getoptions.GetOpt, args []string) error { - return nil - } - - for _, c := range cfg.Stack[config.ID(id)].Components { - cID := string(c.ID) - tm.Add(cID, fn) - g.AddTask(tm.Get(cID)) - for _, w := range c.Workspaces { - wID := fmt.Sprintf("%s:%s", c.ID, w) - tm.Add(wID, fn) - g.AddTask(tm.Get(wID)) - - if normal { - g.TaskDependensOn(tm.Get(cID), tm.Get(wID)) - } else { - g.TaskDependensOn(tm.Get(wID), tm.Get(cID)) - } - } - } - - for _, c := range cfg.Stack[config.ID(id)].Components { - if normal { - for _, e := range c.DependsOn { - eID := e - for _, w := range c.Workspaces { - wID := fmt.Sprintf("%s:%s", c.ID, w) - g.TaskDependensOn(tm.Get(wID), tm.Get(eID)) - } - } - } else { - for _, e := range c.DependsOn { - eID := e - for _, w := range c.Workspaces { - wID := fmt.Sprintf("%s:%s", c.ID, w) - g.TaskDependensOn(tm.Get(eID), tm.Get(wID)) - } - } - } - } - - err := g.Validate(tm) + g, err := generateDAG(id, cfg, normal) if err != nil { - return fmt.Errorf("failed to build graph: %w", err) + return err } fmt.Printf("%s\n", g)