From 77c7f67b2cfa87d2f20ca99bae1cc5bd869da0dc Mon Sep 17 00:00:00 2001 From: Sebastian Estrella <2049686+sestrella@users.noreply.github.com> Date: Mon, 2 Feb 2026 20:36:35 -0500 Subject: [PATCH 1/4] refactor: Initialize AWS client and selectors in root command --- cmd/exec.go | 10 +--------- cmd/logs.go | 12 ++---------- cmd/root.go | 17 ++++++++++++++++- cmd/update.go | 11 +---------- 4 files changed, 20 insertions(+), 30 deletions(-) diff --git a/cmd/exec.go b/cmd/exec.go index 12fa9e6..3fe4e59 100644 --- a/cmd/exec.go +++ b/cmd/exec.go @@ -8,7 +8,6 @@ import ( "regexp" "syscall" - "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/ecs/types" "github.com/sestrella/iecs/client" "github.com/sestrella/iecs/selector" @@ -58,16 +57,9 @@ var execCmd = &cobra.Command{ return nil }, RunE: func(cmd *cobra.Command, args []string) error { - cfg, err := config.LoadDefaultConfig(context.TODO()) - if err != nil { - return err - } - - awsClient := client.NewClient(cfg) - selection, err := execSelector( context.TODO(), - selector.NewSelectors(awsClient, *theme), + selectors, rootClusterRegex, rootServiceRegex, execTaskRegex, diff --git a/cmd/logs.go b/cmd/logs.go index 4225c20..aee93d8 100644 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -8,7 +8,6 @@ import ( "sync" "time" - "github.com/aws/aws-sdk-go-v2/config" logsTypes "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types" "github.com/aws/aws-sdk-go-v2/service/ecs/types" "github.com/fatih/color" @@ -46,14 +45,7 @@ var logsCmd = &cobra.Command{ return err } - cfg, err := config.LoadDefaultConfig(context.TODO()) - if err != nil { - return err - } - - client := client.NewClient(cfg) - - selection, err := logsSelector(context.TODO(), selector.NewSelectors(client, *theme)) + selection, err := logsSelector(context.TODO(), selectors) if err != nil { return err } @@ -61,7 +53,7 @@ var logsCmd = &cobra.Command{ err = runLogs( context.TODO(), noColors, - client, + awsClient, *selection, ) if err != nil { diff --git a/cmd/root.go b/cmd/root.go index 5528174..f54a7c0 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,12 +1,16 @@ package cmd import ( + "context" _ "embed" "fmt" "regexp" "strings" + "github.com/aws/aws-sdk-go-v2/config" "github.com/charmbracelet/huh" + "github.com/sestrella/iecs/client" + "github.com/sestrella/iecs/selector" "github.com/spf13/cobra" ) @@ -14,6 +18,8 @@ var ( availableThemes string themeStr string theme *huh.Theme + awsClient client.Client + selectors selector.Selectors rootCluster string rootClusterRegex *regexp.Regexp rootService string @@ -33,13 +39,22 @@ var rootCmd = &cobra.Command{ Short: "An interactive CLI for ECS", Long: "Performs commons tasks on ECS, such as getting remote access or viewing logs", PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + var err error + + cfg, err := config.LoadDefaultConfig(context.TODO()) + if err != nil { + return err + } + + awsClient := client.NewClient(cfg) + if selectedTheme, ok := themes[themeStr]; ok { theme = selectedTheme } else { return fmt.Errorf("unsupported theme \"%s\" expecting one of: %s", themeStr, availableThemes) } - var err error + selectors = selector.NewSelectors(awsClient, *theme) if rootCluster != "" { rootClusterRegex, err = regexp.Compile(rootCluster) diff --git a/cmd/update.go b/cmd/update.go index 6aa3504..892eda0 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -4,7 +4,6 @@ import ( "context" "time" - "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/ecs/types" "github.com/sestrella/iecs/client" "github.com/sestrella/iecs/selector" @@ -23,14 +22,6 @@ var updateCmd = &cobra.Command{ Use: "update", Short: "Updates a serice configuration", RunE: func(cmd *cobra.Command, args []string) error { - cfg, err := config.LoadDefaultConfig(context.Background()) - if err != nil { - return err - } - - client := client.NewClient(cfg) - selectors := selector.NewSelectors(client, *theme) - selection, err := updateSelector( context.Background(), selectors, @@ -39,7 +30,7 @@ var updateCmd = &cobra.Command{ return err } - err = runUpdate(context.Background(), *selection, client, waitTimeoutFlag) + err = runUpdate(context.Background(), *selection, awsClient, waitTimeoutFlag) if err != nil { return err } From 1c6014ee9639a60570ad6a1292c291dba7d8fb67 Mon Sep 17 00:00:00 2001 From: Sebastian Estrella <2049686+sestrella@users.noreply.github.com> Date: Mon, 2 Feb 2026 20:50:27 -0500 Subject: [PATCH 2/4] refactor: remove unused cluster and service selectors --- cmd/exec.go | 14 -------------- cmd/logs.go | 10 ---------- cmd/root.go | 44 +++++++++++++++++++++++++++----------------- cmd/update.go | 10 ---------- 4 files changed, 27 insertions(+), 51 deletions(-) diff --git a/cmd/exec.go b/cmd/exec.go index 3fe4e59..476078e 100644 --- a/cmd/exec.go +++ b/cmd/exec.go @@ -60,8 +60,6 @@ var execCmd = &cobra.Command{ selection, err := execSelector( context.TODO(), selectors, - rootClusterRegex, - rootServiceRegex, execTaskRegex, execContainerRegex, ) @@ -87,21 +85,9 @@ var execCmd = &cobra.Command{ func execSelector( ctx context.Context, selectors selector.Selectors, - clusterRegex *regexp.Regexp, - serviceRegex *regexp.Regexp, taskRegex *regexp.Regexp, containerRegex *regexp.Regexp, ) (*ExecSelection, error) { - cluster, err := selectors.Cluster(ctx, clusterRegex) - if err != nil { - return nil, err - } - - service, err := selectors.Service(ctx, cluster, serviceRegex) - if err != nil { - return nil, err - } - task, err := selectors.Task(ctx, service, taskRegex) if err != nil { return nil, err diff --git a/cmd/logs.go b/cmd/logs.go index aee93d8..fbe40c5 100644 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -166,16 +166,6 @@ func logsSelector( ctx context.Context, selectors selector.Selectors, ) (*LogsSelection, error) { - cluster, err := selectors.Cluster(ctx, rootClusterRegex) - if err != nil { - return nil, err - } - - service, err := selectors.Service(ctx, cluster, rootServiceRegex) - if err != nil { - return nil, err - } - tasks, err := selectors.Tasks(ctx, service) if err != nil { return nil, err diff --git a/cmd/root.go b/cmd/root.go index f54a7c0..d8187f0 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/ecs/types" "github.com/charmbracelet/huh" "github.com/sestrella/iecs/client" "github.com/sestrella/iecs/selector" @@ -15,15 +16,15 @@ import ( ) var ( - availableThemes string - themeStr string - theme *huh.Theme - awsClient client.Client - selectors selector.Selectors - rootCluster string - rootClusterRegex *regexp.Regexp - rootService string - rootServiceRegex *regexp.Regexp + availableThemes string + themeStr string + theme *huh.Theme + awsClient client.Client + selectors selector.Selectors + clusterStr string + cluster *types.Cluster + serviceStr string + service *types.Service ) var themes = map[string]*huh.Theme{ @@ -39,8 +40,6 @@ var rootCmd = &cobra.Command{ Short: "An interactive CLI for ECS", Long: "Performs commons tasks on ECS, such as getting remote access or viewing logs", PersistentPreRunE: func(cmd *cobra.Command, args []string) error { - var err error - cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { return err @@ -56,18 +55,29 @@ var rootCmd = &cobra.Command{ selectors = selector.NewSelectors(awsClient, *theme) - if rootCluster != "" { - rootClusterRegex, err = regexp.Compile(rootCluster) + if clusterStr != "" { + clusterRegex, err := regexp.Compile(clusterStr) + if err != nil { + return err + } + + cluster, err = selectors.Cluster(context.TODO(), clusterRegex) if err != nil { return err } } - if rootService != "" { - rootServiceRegex, err = regexp.Compile(rootService) + if serviceStr != "" { + serviceRegex, err := regexp.Compile(serviceStr) if err != nil { return err } + + service, err = selectors.Service(context.TODO(), cluster, serviceRegex) + if err != nil { + return err + } + } return nil @@ -103,7 +113,7 @@ func init() { ), ) rootCmd.PersistentFlags(). - StringVar(&rootCluster, "cluster", "", "A regex pattern for filtering clusters") + StringVar(&clusterStr, "cluster", "", "A regex pattern for filtering clusters") rootCmd.PersistentFlags(). - StringVar(&rootService, "service", "", "A regex pattern for filtering services") + StringVar(&serviceStr, "service", "", "A regex pattern for filtering services") } diff --git a/cmd/update.go b/cmd/update.go index 892eda0..f5a303f 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -43,16 +43,6 @@ func updateSelector( ctx context.Context, selectors selector.Selectors, ) (*UpdateSelection, error) { - cluster, err := selectors.Cluster(ctx, rootClusterRegex) - if err != nil { - return nil, err - } - - service, err := selectors.Service(ctx, cluster, rootServiceRegex) - if err != nil { - return nil, err - } - serviceConfig, err := selectors.ServiceConfig(ctx, service) if err != nil { return nil, err From 8ed2cfd53a885a9a173747e7cc0071bbf30947af Mon Sep 17 00:00:00 2001 From: Sebastian Estrella <2049686+sestrella@users.noreply.github.com> Date: Mon, 2 Feb 2026 21:01:18 -0500 Subject: [PATCH 3/4] refactor: Rename root command flags and variables This commit renames several variables and flags related to the root command to be more descriptive. The changes include: - Renaming `awsClient` to `rootClient` - Renaming `selectors` to `rootSelectors` - Renaming `clusterStr` to `rootClusterStr` - Renaming `cluster` to `rootCluster` - Renaming `serviceStr` to `rootServiceStr` - Renaming `service` to `rootService` These changes improve the clarity and maintainability of the codebase by making the purpose of these variables and flags more explicit. --- cmd/exec.go | 10 +++++----- cmd/logs.go | 12 ++++++------ cmd/root.go | 30 +++++++++++++++--------------- cmd/update.go | 10 +++++----- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/cmd/exec.go b/cmd/exec.go index 476078e..633de08 100644 --- a/cmd/exec.go +++ b/cmd/exec.go @@ -59,7 +59,7 @@ var execCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { selection, err := execSelector( context.TODO(), - selectors, + rootSelectors, execTaskRegex, execContainerRegex, ) @@ -69,7 +69,7 @@ var execCmd = &cobra.Command{ err = runExec( context.TODO(), - awsClient, + rootClient, *selection, execCommand, execInteractive, @@ -88,7 +88,7 @@ func execSelector( taskRegex *regexp.Regexp, containerRegex *regexp.Regexp, ) (*ExecSelection, error) { - task, err := selectors.Task(ctx, service, taskRegex) + task, err := selectors.Task(ctx, rootService, taskRegex) if err != nil { return nil, err } @@ -99,8 +99,8 @@ func execSelector( } return &ExecSelection{ - cluster: cluster, - service: service, + cluster: rootCluster, + service: rootService, task: task, container: container, }, nil diff --git a/cmd/logs.go b/cmd/logs.go index fbe40c5..dbd876e 100644 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -45,7 +45,7 @@ var logsCmd = &cobra.Command{ return err } - selection, err := logsSelector(context.TODO(), selectors) + selection, err := logsSelector(context.TODO(), rootSelectors) if err != nil { return err } @@ -53,7 +53,7 @@ var logsCmd = &cobra.Command{ err = runLogs( context.TODO(), noColors, - awsClient, + rootClient, *selection, ) if err != nil { @@ -166,19 +166,19 @@ func logsSelector( ctx context.Context, selectors selector.Selectors, ) (*LogsSelection, error) { - tasks, err := selectors.Tasks(ctx, service) + tasks, err := selectors.Tasks(ctx, rootService) if err != nil { return nil, err } - containers, err := selectors.ContainerDefinitions(ctx, *service.TaskDefinition) + containers, err := selectors.ContainerDefinitions(ctx, *rootService.TaskDefinition) if err != nil { return nil, err } return &LogsSelection{ - cluster: cluster, - service: service, + cluster: rootCluster, + service: rootService, tasks: tasks, containers: containers, }, nil diff --git a/cmd/root.go b/cmd/root.go index d8187f0..a6c72dc 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -19,12 +19,12 @@ var ( availableThemes string themeStr string theme *huh.Theme - awsClient client.Client - selectors selector.Selectors - clusterStr string - cluster *types.Cluster - serviceStr string - service *types.Service + rootClient client.Client + rootSelectors selector.Selectors + rootClusterStr string + rootCluster *types.Cluster + rootServiceStr string + rootService *types.Service ) var themes = map[string]*huh.Theme{ @@ -53,27 +53,27 @@ var rootCmd = &cobra.Command{ return fmt.Errorf("unsupported theme \"%s\" expecting one of: %s", themeStr, availableThemes) } - selectors = selector.NewSelectors(awsClient, *theme) + rootSelectors = selector.NewSelectors(awsClient, *theme) - if clusterStr != "" { - clusterRegex, err := regexp.Compile(clusterStr) + if rootClusterStr != "" { + clusterRegex, err := regexp.Compile(rootClusterStr) if err != nil { return err } - cluster, err = selectors.Cluster(context.TODO(), clusterRegex) + rootCluster, err = rootSelectors.Cluster(context.TODO(), clusterRegex) if err != nil { return err } } - if serviceStr != "" { - serviceRegex, err := regexp.Compile(serviceStr) + if rootServiceStr != "" { + serviceRegex, err := regexp.Compile(rootServiceStr) if err != nil { return err } - service, err = selectors.Service(context.TODO(), cluster, serviceRegex) + rootService, err = rootSelectors.Service(context.TODO(), rootCluster, serviceRegex) if err != nil { return err } @@ -113,7 +113,7 @@ func init() { ), ) rootCmd.PersistentFlags(). - StringVar(&clusterStr, "cluster", "", "A regex pattern for filtering clusters") + StringVar(&rootClusterStr, "cluster", "", "A regex pattern for filtering clusters") rootCmd.PersistentFlags(). - StringVar(&serviceStr, "service", "", "A regex pattern for filtering services") + StringVar(&rootServiceStr, "service", "", "A regex pattern for filtering services") } diff --git a/cmd/update.go b/cmd/update.go index f5a303f..5e1bd18 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -24,13 +24,13 @@ var updateCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { selection, err := updateSelector( context.Background(), - selectors, + rootSelectors, ) if err != nil { return err } - err = runUpdate(context.Background(), *selection, awsClient, waitTimeoutFlag) + err = runUpdate(context.Background(), *selection, rootClient, waitTimeoutFlag) if err != nil { return err } @@ -43,14 +43,14 @@ func updateSelector( ctx context.Context, selectors selector.Selectors, ) (*UpdateSelection, error) { - serviceConfig, err := selectors.ServiceConfig(ctx, service) + serviceConfig, err := selectors.ServiceConfig(ctx, rootService) if err != nil { return nil, err } return &UpdateSelection{ - cluster: *cluster, - service: *service, + cluster: *rootCluster, + service: *rootService, serviceConfig: *serviceConfig, }, nil } From bffd3744dc00d001d580d4213b46f36f42734317 Mon Sep 17 00:00:00 2001 From: Sebastian Estrella <2049686+sestrella@users.noreply.github.com> Date: Thu, 12 Feb 2026 22:16:21 -0500 Subject: [PATCH 4/4] fix: Use global variables for client and selectors This commit introduces global variables `rootClient` and `rootSelectors` to store the AWS client and selectors respectively. This allows these variables to be accessed and used across different commands within the application. Additionally, the commit refactors the cluster and service selection logic to use these global variables, ensuring consistency and simplifying the code. The regular expression compilation for cluster and service strings is also improved to prevent potential errors. --- cmd/root.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index a6c72dc..91bac84 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -45,7 +45,7 @@ var rootCmd = &cobra.Command{ return err } - awsClient := client.NewClient(cfg) + rootClient = client.NewClient(cfg) if selectedTheme, ok := themes[themeStr]; ok { theme = selectedTheme @@ -53,31 +53,33 @@ var rootCmd = &cobra.Command{ return fmt.Errorf("unsupported theme \"%s\" expecting one of: %s", themeStr, availableThemes) } - rootSelectors = selector.NewSelectors(awsClient, *theme) + rootSelectors = selector.NewSelectors(rootClient, *theme) + var clusterRegex *regexp.Regexp if rootClusterStr != "" { - clusterRegex, err := regexp.Compile(rootClusterStr) + clusterRegex, err = regexp.Compile(rootClusterStr) if err != nil { return err } + } - rootCluster, err = rootSelectors.Cluster(context.TODO(), clusterRegex) - if err != nil { - return err - } + rootCluster, err = rootSelectors.Cluster(context.TODO(), clusterRegex) + if err != nil { + return err } + var serviceRegex *regexp.Regexp if rootServiceStr != "" { - serviceRegex, err := regexp.Compile(rootServiceStr) + serviceRegex, err = regexp.Compile(rootServiceStr) if err != nil { return err } - rootService, err = rootSelectors.Service(context.TODO(), rootCluster, serviceRegex) - if err != nil { - return err - } + } + rootService, err = rootSelectors.Service(context.TODO(), rootCluster, serviceRegex) + if err != nil { + return err } return nil