Skip to content

Commit

Permalink
fix: #21 lookup os family when task is ec2 launch type, avoid nil poi…
Browse files Browse the repository at this point in the history
…nter ref when ec2 launch type
  • Loading branch information
Ed Smith committed Nov 12, 2022
1 parent f127678 commit 70aec30
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 15 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ You can also view some additional documentation on using ECS Exec [here](https:/

## Usage

| Flag | Description | Default Value |
| ---- | --------------------------------------------------------------------------------------------| --------------------------|
| `-p` | Specify the profile to load the credentials | `default` |
| `-c` | Specify the command to be run on the container (default will change depending on OS family) | `/bin/sh`,`powershell.exe`|
| `-r` | Specify the AWS region to run in | N/A |
| Flag | Description | Default Value |
| ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
| `-p` | Specify the profile to load the credentials | `default` |
| `-c` | Specify the command to be run on the container (default will change depending on OS family). EC2 launch-type tasks do not contain information on the underlying OS, you will need to specify this manually using the `operatingSystemFamily` value in the [RuntimePlatform](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_RuntimePlatform.html) section of the task definition | `/bin/sh`,`powershell.exe` |
| `-r` | Specify the AWS region to run in | N/A |

The tool also supports AWS Config/Environment Variables for configuration. If you aren't familiar with working on AWS via the CLI, you can read more about how to configure your environment [here](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html).

Expand Down
28 changes: 19 additions & 9 deletions internal/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,20 @@ func (e *ExecCommand) getTask() {
e.input <- "getService"
return
}

e.task = selection

// Get associated task definition and determine OS family if not Fargate task
if e.task.PlatformFamily == nil {
taskDefinition, err := e.client.DescribeTaskDefinition(&ecs.DescribeTaskDefinitionInput{
TaskDefinition: aws.String(*e.task.TaskDefinitionArn),
})
if err != nil {
e.err <- err
return
}
e.task.PlatformFamily = taskDefinition.TaskDefinition.RuntimePlatform.OperatingSystemFamily
}

e.input <- "getContainer"
return

Expand Down Expand Up @@ -260,19 +272,17 @@ func (e *ExecCommand) getContainer() {
// 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
func (e *ExecCommand) executeInput() {
// Check if command has been passed to the tool, defaults to /bin/sh
command := "/bin/sh"
var command string
if viper.GetString("cmd") != "" {
command = viper.GetString("cmd")
} else {
// Check PlatformFamily value and change default cmd if required
if e.task.PlatformFamily != nil {
if strings.Contains(*e.task.PlatformFamily, "Windows") {
command = "powershell.exe"
}
if strings.Contains(strings.ToLower(*e.task.PlatformFamily), "windows") {
command = "powershell.exe"
} else {
command = "/bin/sh"
}
}

}
execCommand, err := e.client.ExecuteCommand(&ecs.ExecuteCommandInput{
Cluster: aws.String(e.cluster),
Interactive: aws.Bool(true),
Expand Down
128 changes: 127 additions & 1 deletion test.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ data "aws_ami" "ecs_optimized" {
owners = ["amazon"]
}

data "aws_ami" "windows_ecs_optimized" {
most_recent = true

filter {
name = "name"
values = ["Windows_Server-2022-English-Core-ECS_Optimized-*"]
}

owners = ["amazon"]
}

####################
# IAM
####################
Expand Down Expand Up @@ -67,7 +78,8 @@ data "aws_iam_policy_document" "ecs_instance" {
statement {
actions = [
"ec2:*",
"ecs:*"
"ecs:*",
"kms:*",
]

resources = [
Expand Down Expand Up @@ -222,13 +234,85 @@ resource "aws_autoscaling_group" "ecs" {
}
}

resource "aws_launch_template" "windows_ecs_instance" {
name = "test-ecsgo-windows-instance-lt"
image_id = data.aws_ami.windows_ecs_optimized.image_id
instance_type = "m5.large"
ebs_optimized = true
instance_initiated_shutdown_behavior = "terminate"

block_device_mappings {
device_name = "/dev/sda1"
ebs {
volume_size = 100
}
}

tag_specifications {
resource_type = "instance"

tags = {
Name = "test-ecsgo-windows-instance"
}
}

iam_instance_profile {
name = aws_iam_instance_profile.ecs_instance.id
}

monitoring {
enabled = true
}

network_interfaces {
associate_public_ip_address = true
security_groups = [aws_security_group.ecs_instance.id]
}

user_data = base64encode(<<-EOF
<powershell>
Initialize-ECSAgent -Cluster ${aws_ecs_cluster.windows_test.name} -EnableTaskIAMRole -AwsvpcBlockIMDS -EnableTaskENI -LoggingDrivers '["json-file","awslogs"]'
[Environment]::SetEnvironmentVariable("ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE",$TRUE, "Machine")
</powershell>
EOF
)

instance_market_options {
market_type = "spot"
}
}

resource "aws_autoscaling_group" "windows_ecs" {
name = "test-ecsgo-windows-instance-asg"
vpc_zone_identifier = data.aws_subnets.test.ids
max_size = 1
min_size = 0
desired_capacity = 1

launch_template {
id = aws_launch_template.windows_ecs_instance.id
version = "$Latest"
}

health_check_grace_period = 300
health_check_type = "EC2"

lifecycle {
create_before_destroy = true
}
}

####################
# ECS
####################
resource "aws_ecs_cluster" "test" {
name = "test-ecsgo"
}

resource "aws_ecs_cluster" "windows_test" {
name = "test-windows-ecsgo"
}

resource "aws_ecs_cluster_capacity_providers" "test" {
cluster_name = aws_ecs_cluster.test.name

Expand Down Expand Up @@ -322,6 +406,10 @@ resource "aws_ecs_task_definition" "ec2_launch" {
execution_role_arn = aws_iam_role.ecs_task.arn
requires_compatibilities = ["EC2"]

runtime_platform {
operating_system_family = "LINUX"
}

container_definitions = jsonencode([
{
name = "nginx"
Expand Down Expand Up @@ -385,6 +473,34 @@ resource "aws_ecs_task_definition" "ec2_launch" {

}

resource "aws_ecs_task_definition" "windows_ec2_launch" {
family = "test-ecsgo-windows-ec2-launch"
task_role_arn = aws_iam_role.ecs_task.arn
execution_role_arn = aws_iam_role.ecs_task.arn
requires_compatibilities = ["EC2"]

container_definitions = jsonencode([
{
name = "iis"
image = "mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2022"
cpu = 512
memory = 1024
essential = true
portMappings = [
{
containerPort = 80
}
]
}
])

runtime_platform {
operating_system_family = "WINDOWS_SERVER_2022_CORE"
cpu_architecture = "X86_64"
}

}

resource "aws_ecs_service" "fargate" {
name = "fargate-test"
cluster = aws_ecs_cluster.test.id
Expand Down Expand Up @@ -412,3 +528,13 @@ resource "aws_ecs_service" "ec2_launch" {
enable_execute_command = true
launch_type = "EC2"
}

resource "aws_ecs_service" "windows-ec2_launch" {
name = "ec2-windows-launch-test"
cluster = aws_ecs_cluster.windows_test.id
task_definition = aws_ecs_task_definition.windows_ec2_launch.arn
desired_count = 1
enable_execute_command = true
launch_type = "EC2"
}

0 comments on commit 70aec30

Please sign in to comment.