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

chore: move around some functions, rename some files, try to improve readability #52

Merged
merged 1 commit into from
Oct 11, 2024
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
66 changes: 51 additions & 15 deletions internal/app.go
Original file line number Diff line number Diff line change
@@ -1,35 +1,72 @@
/* app.go contains the main logic for running the app */

package app

import (
"context"
"errors"
"flag"
"fmt"
"os"
"os/exec"
"os/signal"
"sort"
"strings"
"syscall"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ecs"
ecsTypes "github.com/aws/aws-sdk-go-v2/service/ecs/types"
"github.com/fatih/color"
"github.com/spf13/viper"
)

type EC2Client interface {
DescribeInstances(ctx context.Context, params *ec2.DescribeInstancesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstancesOutput, error)
}
var (
region string

Red = color.New(color.FgRed).SprintFunc()
Magenta = color.New(color.FgMagenta).SprintFunc()
Cyan = color.New(color.FgCyan).SprintFunc()
Green = color.New(color.FgGreen).SprintFunc()
Yellow = color.New(color.FgYellow).SprintFunc()

pageSize = 15
backOpt = "⏎ Back" // backOpt is used to allow the user to navigate backwards in the selection prompt
awsMaxResults = aws.Int32(int32(100))
)

// runCommand executes a command in the current shell and returns an error if the command fails
func runCommand(process string, args ...string) error {
if flag.Lookup("test.v") != nil {
// emulate successful return for testing purposes
return nil
}

// Capture any SIGINTs and discard them
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, os.Interrupt, syscall.SIGINT)
go func() {
for {
select {
case <-sigs:
}
}
}()
defer close(sigs)

cmd := exec.Command(process, args...)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin

type ECSClient interface {
ListClusters(ctx context.Context, params *ecs.ListClustersInput, optFns ...func(*ecs.Options)) (*ecs.ListClustersOutput, error)
ListServices(ctx context.Context, params *ecs.ListServicesInput, optFns ...func(*ecs.Options)) (*ecs.ListServicesOutput, error)
ListTasks(ctx context.Context, params *ecs.ListTasksInput, optFns ...func(*ecs.Options)) (*ecs.ListTasksOutput, error)
DescribeTasks(ctx context.Context, params *ecs.DescribeTasksInput, optFns ...func(*ecs.Options)) (*ecs.DescribeTasksOutput, error)
DescribeTaskDefinition(ctx context.Context, params *ecs.DescribeTaskDefinitionInput, optFns ...func(*ecs.Options)) (*ecs.DescribeTaskDefinitionOutput, error)
DescribeContainerInstances(ctx context.Context, params *ecs.DescribeContainerInstancesInput, optFns ...func(*ecs.Options)) (*ecs.DescribeContainerInstancesOutput, error)
ExecuteCommand(ctx context.Context, params *ecs.ExecuteCommandInput, optFns ...func(*ecs.Options)) (*ecs.ExecuteCommandOutput, error)
if err := cmd.Run(); err != nil {
return err
}

return nil
}

// App is a struct that contains information about our command state
// App is the main struct for the application which holds the state and methods for the application
type App struct {
input chan string
err chan error
Expand Down Expand Up @@ -127,7 +164,6 @@ func (e *App) getCluster() {
}

if e.client == nil {

panic("oh no")
}
list, err := e.client.ListClusters(context.TODO(), &ecs.ListClustersInput{
Expand Down Expand Up @@ -445,7 +481,7 @@ func (e *App) getContainerOS() {
// if the OperatingSystemFamily has not been specified in the task definition
// then we refer to the container instance to determine the OS
if family == "" {
ec2Client := createEc2Client()
ec2Client := createEC2Client()
family, err = getContainerInstanceOS(e.client, ec2Client, e.cluster, *e.task.ContainerInstanceArn)
if err != nil {
e.err <- err
Expand Down
68 changes: 14 additions & 54 deletions internal/internal.go → internal/aws.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
/* aws.go contains AWS Client creation funcs and other helpers used by the main app */

package app

import (
"context"
"flag"
"os"
"os/exec"
"os/signal"
"syscall"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
Expand All @@ -15,27 +12,21 @@ import (
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ecs"
ecsTypes "github.com/aws/aws-sdk-go-v2/service/ecs/types"
"github.com/fatih/color"
"github.com/spf13/viper"
)

var (
region string

Red = color.New(color.FgRed).SprintFunc()
Magenta = color.New(color.FgMagenta).SprintFunc()
Cyan = color.New(color.FgCyan).SprintFunc()
Green = color.New(color.FgGreen).SprintFunc()
Yellow = color.New(color.FgYellow).SprintFunc()

pageSize = 15
backOpt = "⏎ Back" // backOpt is used to allow the user to navigate backwards in the selection prompt
awsMaxResults = aws.Int32(int32(100))
)
type EC2Client interface {
DescribeInstances(ctx context.Context, params *ec2.DescribeInstancesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeInstancesOutput, error)
}

func createOpts(opts []string) []string {
initialOpts := []string{backOpt}
return append(initialOpts, opts...)
type ECSClient interface {
ListClusters(ctx context.Context, params *ecs.ListClustersInput, optFns ...func(*ecs.Options)) (*ecs.ListClustersOutput, error)
ListServices(ctx context.Context, params *ecs.ListServicesInput, optFns ...func(*ecs.Options)) (*ecs.ListServicesOutput, error)
ListTasks(ctx context.Context, params *ecs.ListTasksInput, optFns ...func(*ecs.Options)) (*ecs.ListTasksOutput, error)
DescribeTasks(ctx context.Context, params *ecs.DescribeTasksInput, optFns ...func(*ecs.Options)) (*ecs.DescribeTasksOutput, error)
DescribeTaskDefinition(ctx context.Context, params *ecs.DescribeTaskDefinitionInput, optFns ...func(*ecs.Options)) (*ecs.DescribeTaskDefinitionOutput, error)
DescribeContainerInstances(ctx context.Context, params *ecs.DescribeContainerInstancesInput, optFns ...func(*ecs.Options)) (*ecs.DescribeContainerInstancesOutput, error)
ExecuteCommand(ctx context.Context, params *ecs.ExecuteCommandInput, optFns ...func(*ecs.Options)) (*ecs.ExecuteCommandOutput, error)
}

func createEcsClient() *ecs.Client {
Expand All @@ -61,7 +52,7 @@ func createEcsClient() *ecs.Client {
return client
}

func createEc2Client() *ec2.Client {
func createEC2Client() *ec2.Client {
region := viper.GetString("region")
getCustomAWSEndpoint := func(o *ec2.Options) {
endpointUrl := viper.GetString("aws-endpoint-url")
Expand Down Expand Up @@ -121,37 +112,6 @@ func getContainerInstanceOS(ecsClient ECSClient, ec2Client EC2Client, cluster st
return operatingSystem, nil
}

// runCommand executes a command with args
func runCommand(process string, args ...string) error {
if flag.Lookup("test.v") != nil {
// emulate successful return for testing purposes
return nil
}

// Capture any SIGINTs and discard them
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, os.Interrupt, syscall.SIGINT)
go func() {
for {
select {
case <-sigs:
}
}
}()
defer close(sigs)

cmd := exec.Command(process, args...)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin

if err := cmd.Run(); err != nil {
return err
}

return nil
}

func getContainerPort(client ECSClient, taskDefinitionArn string, containerName string) (*int32, error) {
res, err := client.DescribeTaskDefinition(context.TODO(), &ecs.DescribeTaskDefinitionInput{
TaskDefinition: aws.String(taskDefinitionArn),
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions internal/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
"github.com/spf13/viper"
)

// executeCommand takes all of our previous values and builds a session for us
// and then calls runCommand to execute the session input via session-manager-plugin
// executeCommand takes the app state and builds an execute-command session for us
// which is then passed to the session-manager-plugin for execution
func (e *App) executeCommand() error {
var command string
if viper.GetString("cmd") != "" {
Expand Down
5 changes: 2 additions & 3 deletions internal/forward.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (
"github.com/spf13/viper"
)

// executeInput takes all of our previous values and builds a session for us
// and then calls runCommand to execute the session input via session-manager-plugin
// executeForward takes the app state and builds a port-forward session for us
// which is then passed to the session-manager-plugin for execution
func (e *App) executeForward() error {
taskArnSplit := strings.Split(*e.task.TaskArn, "/")
taskID := taskArnSplit[len(taskArnSplit)-1]
Expand Down Expand Up @@ -79,5 +79,4 @@ func (e *App) executeForward() error {
err = runCommand("session-manager-plugin", string(sessJson), e.region, "StartSession", "", string(paramsJson))
e.err <- err
return err

}
10 changes: 9 additions & 1 deletion internal/select.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* select.go contains the logic for the Select/Survey views in the TUI app */

package app

import (
Expand All @@ -7,7 +9,7 @@ import (

"github.com/AlecAivazis/survey/v2"
"github.com/aws/aws-sdk-go-v2/aws"
// "github.com/aws/aws-sdk-go-v2/service/ecs"

ecsTypes "github.com/aws/aws-sdk-go-v2/service/ecs/types"
)

Expand All @@ -27,6 +29,12 @@ func init() {
{{- end}}`
}

// createOpts builds the initial options for the survey prompts
func createOpts(opts []string) []string {
initialOpts := []string{backOpt}
return append(initialOpts, opts...)
}

// selectCluster provides the prompt for choosing a cluster
func selectCluster(clusterNames []string) (string, error) {
if flag.Lookup("test.v") != nil {
Expand Down
Loading