From fc46be54b3d424ac32c58eab1718446bb390ef72 Mon Sep 17 00:00:00 2001 From: Ethan Blackburn Date: Thu, 4 Apr 2024 11:27:44 -0400 Subject: [PATCH] run TUI in main thread --- cmd/deploy.go | 47 ++------------------------------------- cmd/diff.go | 45 ++----------------------------------- cmd/iac.go | 1 - cmd/provisionaccounts.go | 13 ++++++----- cmd/root.go | 48 ++++++++++++++++++++++++++++++++++++++++ cmd/runner/interface.go | 2 +- cmd/runner/stdout.go | 2 +- cmd/runner/tui.go | 20 ++++++++++++----- 8 files changed, 76 insertions(+), 102 deletions(-) diff --git a/cmd/deploy.go b/cmd/deploy.go index 8d82bdf..f0b8b7f 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -1,13 +1,7 @@ package cmd import ( - "context" - "fmt" - "github.com/santiago-labs/telophasecli/cmd/runner" - "github.com/santiago-labs/telophasecli/lib/awsorgs" - "github.com/santiago-labs/telophasecli/lib/ymlparser" - "github.com/santiago-labs/telophasecli/resource" "github.com/santiago-labs/telophasecli/resourceoperation" "github.com/spf13/cobra" @@ -33,8 +27,6 @@ var compileCmd = &cobra.Command{ Use: "deploy", Short: "deploy - Deploy a CDK and/or TF stacks to your AWS account(s). Accounts in organization.yml will be created if they do not exist.", Run: func(cmd *cobra.Command, args []string) { - orgClient := awsorgs.New() - ctx := context.Background() var consoleUI runner.ConsoleUI if useTUI { @@ -43,43 +35,8 @@ var compileCmd = &cobra.Command{ consoleUI = runner.NewSTDOut() } - var accountsToApply []resource.Account - rootAWSGroup, err := ymlparser.ParseOrganizationV2(orgFile) - if err != nil { - panic(fmt.Sprintf("error: %s", err)) - } - - ops := orgV2Diff(ctx, consoleUI, orgClient, rootAWSGroup, resourceoperation.Deploy) - for _, op := range ops { - if err := op.Call(ctx); err != nil { - panic(err) - } - } - - if rootAWSGroup != nil { - for _, acct := range rootAWSGroup.AllDescendentAccounts() { - if contains(tag, acct.AllTags()) || tag == "" { - accountsToApply = append(accountsToApply, *acct) - } - } - } + go processOrgEndToEnd(consoleUI, resourceoperation.Deploy) + consoleUI.Start() - if len(accountsToApply) == 0 { - fmt.Println("No accounts to deploy") - } - - runIAC(ctx, consoleUI, resourceoperation.Deploy, accountsToApply) - - mgmtAcct, err := orgClient.FetchManagementAccount(ctx) - if err != nil { - panic(err) - } - scpOps := resourceoperation.CollectSCPOps(ctx, orgClient, consoleUI, resourceoperation.Deploy, rootAWSGroup, mgmtAcct) - for _, op := range scpOps { - err := op.Call(ctx) - if err != nil { - consoleUI.Print(fmt.Sprintf("Error on SCP Operation: %v", err), *mgmtAcct) - } - } }, } diff --git a/cmd/diff.go b/cmd/diff.go index 57b12ff..675c0b3 100644 --- a/cmd/diff.go +++ b/cmd/diff.go @@ -1,13 +1,7 @@ package cmd import ( - "context" - "fmt" - "github.com/santiago-labs/telophasecli/cmd/runner" - "github.com/santiago-labs/telophasecli/lib/awsorgs" - "github.com/santiago-labs/telophasecli/lib/ymlparser" - "github.com/santiago-labs/telophasecli/resource" "github.com/santiago-labs/telophasecli/resourceoperation" "github.com/spf13/cobra" @@ -25,7 +19,6 @@ var diffCmd = &cobra.Command{ Use: "diff", Short: "diff - Show accounts to create/update and CDK and/or TF changes for each account.", Run: func(cmd *cobra.Command, args []string) { - orgClient := awsorgs.New() var consoleUI runner.ConsoleUI if useTUI { @@ -34,41 +27,7 @@ var diffCmd = &cobra.Command{ consoleUI = runner.NewSTDOut() } - var accountsToApply []resource.Account - - ctx := context.Background() - - rootAWSGroup, err := ymlparser.ParseOrganizationV2(orgFile) - if err != nil { - panic(fmt.Sprintf("error: %s", err)) - } - orgV2Diff(ctx, consoleUI, orgClient, rootAWSGroup, resourceoperation.Diff) - - if rootAWSGroup != nil { - for _, acct := range rootAWSGroup.AllDescendentAccounts() { - if contains(tag, acct.AllTags()) || tag == "" { - accountsToApply = append(accountsToApply, *acct) - } - } - } - - if len(accountsToApply) == 0 { - fmt.Println("No accounts to deploy") - } - - runIAC(ctx, consoleUI, resourceoperation.Diff, accountsToApply) - - mgmtAcct, err := orgClient.FetchManagementAccount(ctx) - if err != nil { - panic(err) - } - - scpOps := resourceoperation.CollectSCPOps(ctx, orgClient, consoleUI, resourceoperation.Diff, rootAWSGroup, mgmtAcct) - for _, op := range scpOps { - err := op.Call(ctx) - if err != nil { - consoleUI.Print(fmt.Sprintf("Error on SCP Operation: %v", err), *mgmtAcct) - } - } + go processOrgEndToEnd(consoleUI, resourceoperation.Diff) + consoleUI.Start() }, } diff --git a/cmd/iac.go b/cmd/iac.go index 796594a..c793392 100644 --- a/cmd/iac.go +++ b/cmd/iac.go @@ -42,7 +42,6 @@ func runIAC( }(accts[i]) } - consoleUI.PostProcess() wg.Wait() } func contains(e string, s []string) bool { diff --git a/cmd/provisionaccounts.go b/cmd/provisionaccounts.go index 5fbb61e..ce45e4a 100644 --- a/cmd/provisionaccounts.go +++ b/cmd/provisionaccounts.go @@ -61,6 +61,10 @@ var accountProvision = &cobra.Command{ } ctx := context.Background() + mgmtAcct, err := orgClient.FetchManagementAccount(ctx) + if err != nil { + panic(err) + } if args[0] == "import" { if err := importOrgV2(orgClient); err != nil { panic(fmt.Sprintf("error importing organization: %s", err)) @@ -72,11 +76,11 @@ var accountProvision = &cobra.Command{ panic(fmt.Sprintf("error: %s", err)) } if args[0] == "diff" { - orgV2Diff(ctx, consoleUI, orgClient, rootAWSGroup, resourceoperation.Diff) + orgV2Diff(ctx, consoleUI, orgClient, rootAWSGroup, mgmtAcct, resourceoperation.Diff) } if args[0] == "deploy" { - operations := orgV2Diff(ctx, consoleUI, orgClient, rootAWSGroup, resourceoperation.Deploy) + operations := orgV2Diff(ctx, consoleUI, orgClient, rootAWSGroup, mgmtAcct, resourceoperation.Deploy) for _, op := range operations { err := op.Call(ctx) @@ -93,15 +97,12 @@ func orgV2Diff( outputUI runner.ConsoleUI, orgClient awsorgs.Client, rootAWSGroup *resource.AccountGroup, + mgmtAcct *resource.Account, operation int, ) []resourceoperation.ResourceOperation { var operations []resourceoperation.ResourceOperation if rootAWSGroup != nil { - mgmtAcct, err := orgClient.FetchManagementAccount(ctx) - if err != nil { - panic(err) - } operations = append(operations, resourceoperation.CollectOrganizationUnitOps( ctx, outputUI, orgClient, rootAWSGroup, operation, )...) diff --git a/cmd/root.go b/cmd/root.go index 74f0b08..1000cfe 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,10 +1,16 @@ package cmd import ( + "context" "fmt" "os" + "github.com/santiago-labs/telophasecli/cmd/runner" + "github.com/santiago-labs/telophasecli/lib/awsorgs" "github.com/santiago-labs/telophasecli/lib/metrics" + "github.com/santiago-labs/telophasecli/lib/ymlparser" + "github.com/santiago-labs/telophasecli/resource" + "github.com/santiago-labs/telophasecli/resourceoperation" "github.com/spf13/cobra" ) @@ -27,3 +33,45 @@ func Execute() { os.Exit(1) } } + +func processOrgEndToEnd(consoleUI runner.ConsoleUI, cmd int) { + ctx := context.Background() + orgClient := awsorgs.New() + mgmtAcct, err := orgClient.FetchManagementAccount(ctx) + if err != nil { + panic(err) + } + + var accountsToApply []resource.Account + rootAWSGroup, err := ymlparser.ParseOrganizationV2(orgFile) + if err != nil { + panic(fmt.Sprintf("error: %s", err)) + } + orgV2Diff(ctx, consoleUI, orgClient, rootAWSGroup, mgmtAcct, cmd) + + if rootAWSGroup != nil { + for _, acct := range rootAWSGroup.AllDescendentAccounts() { + if contains(tag, acct.AllTags()) || tag == "" { + accountsToApply = append(accountsToApply, *acct) + } + } + } + + if len(accountsToApply) == 0 { + consoleUI.Print("No accounts to deploy.", *mgmtAcct) + } + + runIAC(ctx, consoleUI, cmd, accountsToApply) + + scpOps := resourceoperation.CollectSCPOps(ctx, orgClient, consoleUI, cmd, rootAWSGroup, mgmtAcct) + for _, op := range scpOps { + err := op.Call(ctx) + if err != nil { + consoleUI.Print(fmt.Sprintf("Error on SCP Operation: %v", err), *mgmtAcct) + } + } + + if len(scpOps) == 0 { + consoleUI.Print("No Service Control Policies to deploy.", *mgmtAcct) + } +} diff --git a/cmd/runner/interface.go b/cmd/runner/interface.go index 98d6b31..44e9cc3 100644 --- a/cmd/runner/interface.go +++ b/cmd/runner/interface.go @@ -9,5 +9,5 @@ import ( type ConsoleUI interface { Print(string, resource.Account) RunCmd(*exec.Cmd, resource.Account) error - PostProcess() + Start() } diff --git a/cmd/runner/stdout.go b/cmd/runner/stdout.go index 0cac76e..5355280 100644 --- a/cmd/runner/stdout.go +++ b/cmd/runner/stdout.go @@ -86,4 +86,4 @@ func (s *stdOut) Print(msg string, acct resource.Account) { fmt.Printf("%s %v\n", s.ColoredId(acct), msg) } -func (s *stdOut) PostProcess() {} +func (s *stdOut) Start() {} diff --git a/cmd/runner/tui.go b/cmd/runner/tui.go index ac7a517..7513f09 100644 --- a/cmd/runner/tui.go +++ b/cmd/runner/tui.go @@ -35,7 +35,7 @@ func NewTUI() ConsoleUI { SetChangedFunc(func() { tv.ScrollToEnd() app.Draw() - }).SetText("Starting CDK...") + }).SetText("Starting Telophase...") return &tui{ list: tview.NewList(), @@ -95,6 +95,8 @@ func (t *tui) createIfNotExists(acct resource.Account) { t.tails[acctId] = &setter t.files[acctId] = file + + t.app.Draw() } func (t *tui) RunCmd(cmd *exec.Cmd, acct resource.Account) error { @@ -114,12 +116,15 @@ func (t *tui) RunCmd(cmd *exec.Cmd, acct resource.Account) error { return nil } -func (t *tui) PostProcess() { +func (t *tui) Start() { t.list.AddItem("Quit", "Press to exit", 'q', func() { t.app.Stop() }) - // Start index at 0 for the first account. + startScreen := func() string { return "Starting Telophase..." } + t.tails["quit"] = &startScreen + t.index["quit"] = 0 + tuiIndex.Swap(0) go t.liveTextSetter() @@ -133,10 +138,10 @@ func (t *tui) PostProcess() { grid.AddItem(t.list, 0, 0, 1, 1, 0, 100, false). AddItem(t.main, 0, 1, 1, 1, 0, 100, false) - if err := t.app.SetRoot(grid, true).SetFocus(t.list).Run(); err != nil { + err := t.app.SetRoot(grid, true).SetFocus(t.list).Run() + if err != nil { panic(err) } - } func (t tui) Print(msg string, acct resource.Account) { @@ -160,6 +165,11 @@ func runeIndex(i int) rune { // liveTextSetter updates the current tui view with the current tail's text. func (t *tui) liveTextSetter() { + defer func() { + if r := recover(); r != nil { + t.app.Stop() + } + }() for { func() { time.Sleep(200 * time.Millisecond)