Skip to content

Commit 852ef25

Browse files
authored
Feature/fargate (#35)
* fargate support * fargate support * start working on exec * exec command * exec command * exec fixed * bump go * go version for releaser * public subnets support for Runfargate * Readme update * temp commit with exex improvements * exec linting commit * gh actions fix * Refactor exec command and improve code quality - Refactor ExecFargate for KISS/DRY compliance: * Extract helper functions (trySSMParent, tryDirectExecution, etc.) * Replace boolean flags with execResult struct * Reduce ExecFargate from ~180 lines to ~20 lines * Improve error handling and readability - Fix container name handling in exec command: * Add validation when container_name flag is not provided * Ensure command is not empty after container name extraction * Provide clear error messages for invalid usage - Remove debug print statement from cmd/run.go - Fix redundant string wrapping in lib/runFargate.go: * Remove unnecessary aws.String()/aws.StringValue() wrapping * Use strings directly in log fields - Add documentation comment about public IP usage in Fargate * Note that IPv6 implementation will change this behavior - Fix linter warnings and improve code consistency
1 parent 921c685 commit 852ef25

File tree

13 files changed

+1113
-41
lines changed

13 files changed

+1113
-41
lines changed

.github/workflows/build_test.yml

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,20 @@ jobs:
99
name: test if ecs-tool can be built
1010
runs-on: ubuntu-latest
1111
steps:
12-
-
13-
name: checkout
14-
uses: actions/checkout@v2
15-
-
16-
name: set up Go
17-
uses: actions/setup-go@v1
12+
- name: checkout
13+
uses: actions/checkout@v4
14+
- name: set up Go
15+
uses: actions/setup-go@v5
1816
with:
19-
go-version: 1.15.x
20-
-
21-
name: cache modules
22-
uses: actions/cache@v2
17+
go-version: 1.21.x
18+
- name: cache modules
19+
uses: actions/cache@v4
2320
with:
2421
path: ~/go/pkg/mod
2522
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
2623
restore-keys: |
2724
${{ runner.os }}-go-
28-
-
29-
name: download dependencies
25+
- name: download dependencies
3026
run: go mod download
31-
-
32-
name: build the app
27+
- name: build the app
3328
run: go build

.github/workflows/release.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ jobs:
1010
steps:
1111
-
1212
name: checkout
13-
uses: actions/checkout@v2
13+
uses: actions/checkout@v4
1414
with:
1515
fetch-depth: 0 # needed for tags
1616
-
1717
name: set up Go
18-
uses: actions/setup-go@v1
18+
uses: actions/setup-go@v5
1919
with:
20-
go-version: 1.17.x
20+
go-version: 1.21.x
2121
-
2222
name: run GoReleaser
2323
uses: goreleaser/goreleaser-action@v1

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,27 @@ So that `--cluster` can be set by `ECS_CLUSTER` environmental variable, or `--ta
5555

5656
Also, `ecs-tool` exit code is the same as the container exit code.
5757

58+
### runFargate
59+
60+
The runFargate function is a command that is integrated into the ecs-tool utility. This tool simplifies running commands on an AWS ECS (Elastic Container Service) cluster with Fargate.
61+
62+
That normany use subnet with 'private' 'Tier' tag but if there is zero proivate subnets that will use 'public'
63+
64+
```
65+
ecs-tool runFargate -e "preview" -- env
66+
```
67+
68+
### EXEC
69+
70+
ecs-tool exec Executes a specified command in a running container on an ECS Fargate cluster and get the output.
71+
That function use existing container, so it's faster than runFargate
72+
This command also could connect to fargate existing task:
73+
74+
```
75+
ecs-tool exec -e "preview" /bin/sh
76+
```
77+
78+
5879
### SSH
5980

6081
'SSH' access availabe to developers using `ecs-tool ssh`

cmd/exec.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
"strings"
6+
7+
"github.com/apex/log"
8+
"github.com/spf13/cobra"
9+
"github.com/spf13/viper"
10+
"github.com/springload/ecs-tool/lib"
11+
)
12+
13+
var execCmd = &cobra.Command{
14+
Use: "exec",
15+
Short: "Executes a command in an existing ECS Fargate container",
16+
17+
Long: `Executes a specified command in a running container on an ECS Fargate cluster.`,
18+
Args: cobra.MinimumNArgs(1),
19+
Run: func(cmd *cobra.Command, args []string) {
20+
viper.SetDefault("run.launch_type", "FARGATE")
21+
var containerName string
22+
var commandArgs []string
23+
if name := viper.GetString("container_name"); name == "" {
24+
// If container_name not provided via flag, use first arg as container name
25+
if len(args) < 2 {
26+
log.Error("When --container_name is not provided, at least 2 arguments are required: <container_name> <command>")
27+
os.Exit(1)
28+
}
29+
containerName = args[0]
30+
commandArgs = args[1:]
31+
} else {
32+
containerName = name
33+
commandArgs = args
34+
}
35+
36+
// Validate that we have a command to execute
37+
if len(commandArgs) == 0 {
38+
log.Error("No command provided to execute")
39+
os.Exit(1)
40+
}
41+
42+
// Join the commandArgs to form a single command string
43+
commandString := strings.Join(commandArgs, " ")
44+
45+
err := lib.ExecFargate(lib.ExecConfig{
46+
Profile: viper.GetString("profile"),
47+
Cluster: viper.GetString("cluster"),
48+
Command: commandString,
49+
TaskID: viper.GetString("task_id"),
50+
TaskDefinitionName: viper.GetString("task_definition"),
51+
ContainerName: containerName,
52+
})
53+
if err != nil {
54+
log.WithError(err).Error("Can't execute command in Fargate mode")
55+
os.Exit(1)
56+
}
57+
},
58+
}
59+
60+
func init() {
61+
rootCmd.AddCommand(execCmd)
62+
execCmd.PersistentFlags().StringP("task_id", "", "", "Task ID to use (will auto-extract task definition)")
63+
viper.BindPFlag("task_id", execCmd.PersistentFlags().Lookup("task_id"))
64+
}

cmd/root.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,17 @@ func init() {
5151
rootCmd.PersistentFlags().StringP("workdir", "w", "", "Set working directory")
5252
rootCmd.PersistentFlags().StringP("image_tag", "", "", "Overrides the docker image tag in all container definitions. Overrides \"--image-tags\" flag.")
5353
rootCmd.PersistentFlags().StringSliceP("image_tags", "", []string{}, "Modifies the docker image tags in container definitions. Can be specified several times, one for each container definition. Also takes comma-separated values in one tag. I.e. if there are 2 containers and --image-tags is set once to \"new\", then the image tag of the first container will be modified, leaving the second one untouched. Gets overridden by \"--image-tag\". If you have 3 container definitions and want to modify tags for the 1st and the 3rd, but leave the 2nd unchanged, specify it as \"--image_tags first_tag,,last_tag\".")
54+
rootCmd.PersistentFlags().StringP("task_definition", "t", "", "Name of the ECS task definition to use (required)")
55+
56+
5457

5558
viper.BindPFlag("profile", rootCmd.PersistentFlags().Lookup("profile"))
5659
viper.BindPFlag("cluster", rootCmd.PersistentFlags().Lookup("cluster"))
5760
viper.BindPFlag("workdir", rootCmd.PersistentFlags().Lookup("workdir"))
5861
viper.BindPFlag("image_tag", rootCmd.PersistentFlags().Lookup("image_tag"))
5962
viper.BindPFlag("image_tags", rootCmd.PersistentFlags().Lookup("image_tags"))
63+
viper.BindPFlag("task_definition", rootCmd.PersistentFlags().Lookup("task_definition"))
64+
6065

6166
}
6267

cmd/run.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ It can modify the container command.
1818
`,
1919
Args: cobra.MinimumNArgs(1),
2020
Run: func(cmd *cobra.Command, args []string) {
21+
viper.SetDefault("run.launch_type", "EC2")
2122
var containerName string
2223
var commandArgs []string
2324
if name := viper.GetString("container_name"); name == "" {
@@ -52,9 +53,7 @@ func init() {
5253
rootCmd.AddCommand(runCmd)
5354
runCmd.PersistentFlags().StringP("log_group", "l", "", "Name of the log group to get output")
5455
runCmd.PersistentFlags().StringP("container_name", "", "", "Name of the container to modify parameters for")
55-
runCmd.PersistentFlags().StringP("task_definition", "t", "", "name of task definition to use (required)")
5656
viper.BindPFlag("log_group", runCmd.PersistentFlags().Lookup("log_group"))
5757
viper.BindPFlag("container_name", runCmd.PersistentFlags().Lookup("container_name"))
58-
viper.BindPFlag("task_definition", runCmd.PersistentFlags().Lookup("task_definition"))
59-
viper.SetDefault("run.launch_type", "EC2")
58+
//viper.BindPFlag("task_definition", runCmd.PersistentFlags().Lookup("task_definition"))
6059
}

cmd/runFargate.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
6+
"github.com/apex/log"
7+
"github.com/spf13/cobra"
8+
"github.com/spf13/viper"
9+
"github.com/springload/ecs-tool/lib"
10+
)
11+
12+
var runFargateCmd = &cobra.Command{
13+
Use: "runFargate",
14+
Short: "Runs a command in Fargate mode",
15+
Long: `Runs the specified command on an ECS cluster, optionally catching its output.
16+
17+
This command is specifically tailored for future Fargate-specific functionality.`,
18+
Args: cobra.MinimumNArgs(1),
19+
Run: func(cmd *cobra.Command, args []string) {
20+
viper.SetDefault("run.launch_type", "FARGATE")
21+
viper.SetDefault("run.security_group_filter", "ec2")
22+
var containerName string
23+
var commandArgs []string
24+
if name := viper.GetString("container_name"); name == "" {
25+
containerName = args[0]
26+
commandArgs = args[1:]
27+
} else {
28+
containerName = name
29+
commandArgs = args
30+
}
31+
32+
exitCode, err := lib.RunFargate(
33+
viper.GetString("profile"),
34+
viper.GetString("cluster"),
35+
viper.GetString("run.service"),
36+
viper.GetString("task_definition"),
37+
viper.GetString("image_tag"),
38+
viper.GetStringSlice("image_tags"),
39+
viper.GetString("workdir"),
40+
containerName,
41+
viper.GetString("log_group"),
42+
viper.GetString("run.launch_type"),
43+
viper.GetString("run.security_group_filter"),
44+
commandArgs,
45+
)
46+
if err != nil {
47+
log.WithError(err).Error("Can't run task in Fargate mode")
48+
}
49+
os.Exit(exitCode)
50+
},
51+
}
52+
53+
func init() {
54+
rootCmd.AddCommand(runFargateCmd)
55+
}

go.mod

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,69 @@
11
module github.com/springload/ecs-tool
22

3-
go 1.17
3+
go 1.21
44

55
require (
66
github.com/Shopify/ejson v1.2.1
77
github.com/apex/log v1.0.0
8-
github.com/aws/aws-sdk-go v1.55.5
8+
github.com/aws/aws-sdk-go v1.43.24
9+
github.com/aws/aws-sdk-go-v2 v1.26.1
10+
github.com/aws/aws-sdk-go-v2/config v1.26.3
11+
github.com/aws/aws-sdk-go-v2/service/ecs v1.41.7
12+
github.com/fujiwara/ecsta v0.4.5
913
github.com/imdario/mergo v0.3.11
1014
github.com/spf13/cobra v0.0.3
1115
github.com/spf13/viper v1.0.2
12-
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
16+
golang.org/x/crypto v0.14.0
1317
)
1418

1519
require (
1620
github.com/BurntSushi/toml v0.3.1 // indirect
17-
github.com/davecgh/go-spew v1.1.1 // indirect
21+
github.com/Songmu/flextime v0.1.0 // indirect
22+
github.com/Songmu/prompter v0.5.1 // indirect
23+
github.com/alecthomas/kong v0.7.0 // indirect
24+
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 // indirect
25+
github.com/aws/aws-sdk-go-v2/credentials v1.16.14 // indirect
26+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 // indirect
27+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect
28+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect
29+
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 // indirect
30+
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.31.0 // indirect
31+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect
32+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 // indirect
33+
github.com/aws/aws-sdk-go-v2/service/sns v1.26.7 // indirect
34+
github.com/aws/aws-sdk-go-v2/service/ssm v1.44.7 // indirect
35+
github.com/aws/aws-sdk-go-v2/service/sso v1.18.6 // indirect
36+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.6 // indirect
37+
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 // indirect
38+
github.com/aws/smithy-go v1.20.2 // indirect
39+
github.com/creack/pty v1.1.20 // indirect
1840
github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad // indirect
1941
github.com/fsnotify/fsnotify v1.4.7 // indirect
42+
github.com/fujiwara/tracer v1.0.2 // indirect
2043
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce // indirect
2144
github.com/inconshreveable/mousetrap v1.0.0 // indirect
45+
github.com/itchyny/gojq v0.12.11 // indirect
46+
github.com/itchyny/timefmt-go v0.1.5 // indirect
2247
github.com/jmespath/go-jmespath v0.4.0 // indirect
2348
github.com/magiconair/properties v1.8.0 // indirect
49+
github.com/mattn/go-isatty v0.0.16 // indirect
50+
github.com/mattn/go-runewidth v0.0.14 // indirect
2451
github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675 // indirect
52+
github.com/olekukonko/tablewriter v0.0.5 // indirect
2553
github.com/pelletier/go-toml v1.2.0 // indirect
2654
github.com/pkg/errors v0.9.1 // indirect
55+
github.com/rivo/uniseg v0.3.4 // indirect
56+
github.com/samber/lo v1.36.0 // indirect
2757
github.com/smartystreets/goconvey v1.6.4 // indirect
2858
github.com/spf13/afero v1.1.1 // indirect
2959
github.com/spf13/cast v1.2.0 // indirect
3060
github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec // indirect
3161
github.com/spf13/pflag v1.0.1 // indirect
32-
github.com/stretchr/testify v1.5.1 // indirect
33-
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
34-
golang.org/x/text v0.3.7 // indirect
35-
gopkg.in/yaml.v2 v2.3.0 // indirect
62+
github.com/tkuchiki/go-timezone v0.2.2 // indirect
63+
github.com/tkuchiki/parsetime v0.3.0 // indirect
64+
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
65+
golang.org/x/sys v0.13.0 // indirect
66+
golang.org/x/term v0.13.0 // indirect
67+
golang.org/x/text v0.13.0 // indirect
68+
gopkg.in/yaml.v2 v2.4.0 // indirect
3669
)

0 commit comments

Comments
 (0)