Skip to content

Commit

Permalink
Added ecs-locate
Browse files Browse the repository at this point in the history
  • Loading branch information
hamstah committed Oct 1, 2018
1 parent eacc96f commit 41ce49a
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Collection of tools to make working with AWS a bit easier without having to depe
* `ec2-ip-from-name`: Given an EC2 name, list up to `-max-results` IPs associated with instances with that name (default is 1).
* `ecr-get-login`: Prints out the command to run to auth with docker ECR. Check output flag for other options
* `ecs-dashboard`: Shows ECS services and their version across multiple AWS accounts. [details](ecs/dashboard)
* `ecs-locate`: Returns `ip:port` for containers of an ECS service
* `ecs-deploy`: Update the container images of a task and update services to use it
* `ecs-run-task`: Run a task definition
* `elb-resolve-elb-external-url`: ELB classic only (no ALB). Given a name returns the zone53 record associated with the ELB, including scheme (https returned if both available) and port.
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.8.1
5.9.0
120 changes: 120 additions & 0 deletions ecs/locate/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package main

import (
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/hamstah/awstools/common"

kingpin "gopkg.in/alecthomas/kingpin.v2"
)

var (
flags = common.KingpinSessionFlags()
infoFlags = common.KingpinInfoFlags()
containerName = kingpin.Flag("container-name", "ECS container name").Required().String()
containerPort = kingpin.Flag("container-port", "ECS container port").Required().Int64()
cluster = kingpin.Flag("cluster", "ECS cluster").Required().String()
service = kingpin.Flag("service", "ECS service").Required().String()
)

func main() {
kingpin.CommandLine.Name = "ecs-locate"
kingpin.CommandLine.Help = "Find an instance/port for a service"
kingpin.Parse()
common.HandleInfoFlags(infoFlags)

session, conf := common.OpenSession(flags)

ecsClient := ecs.New(session, conf)

tasksResult, err := ecsClient.ListTasks(&ecs.ListTasksInput{
Cluster: cluster,
DesiredStatus: aws.String("RUNNING"),
ServiceName: service,
})
common.FatalOnError(err)

describeTasks, err := ecsClient.DescribeTasks(&ecs.DescribeTasksInput{
Cluster: cluster,
Tasks: tasksResult.TaskArns,
})
common.FatalOnError(err)

containerInstances := map[string]bool{}

bindings := map[string]int64{}
for _, task := range describeTasks.Tasks {
found := false
for _, container := range task.Containers {
if *container.Name != *containerName {
continue
}

for _, binding := range container.NetworkBindings {
if *binding.ContainerPort != *containerPort {
continue
}

bindings[*task.ContainerInstanceArn] = *binding.HostPort
containerInstances[*task.ContainerInstanceArn] = true
found = true
}
}
if !found {
common.Fatalln(fmt.Sprintf("Could not find container in task %s", *task.TaskArn))
}
}

containerInstancesArns := make([]*string, 0, len(containerInstances))
for key := range containerInstances {
containerInstancesArns = append(containerInstancesArns, aws.String(key))
}

containerInstancesResult, err := ecsClient.DescribeContainerInstances(&ecs.DescribeContainerInstancesInput{
Cluster: cluster,
ContainerInstances: containerInstancesArns,
})
common.FatalOnError(err)

containerInstanceToEC2 := map[string]string{}
ec2InstanceIDs := make([]*string, 0, len(containerInstancesResult.ContainerInstances))
for _, containerInstance := range containerInstancesResult.ContainerInstances {
ec2InstanceIDs = append(ec2InstanceIDs, containerInstance.Ec2InstanceId)
containerInstanceToEC2[*containerInstance.ContainerInstanceArn] = *containerInstance.Ec2InstanceId
}

ec2Client := ec2.New(session, conf)

ec2Result, err := ec2Client.DescribeInstances(&ec2.DescribeInstancesInput{
InstanceIds: ec2InstanceIDs,
})
common.FatalOnError(err)

ec2ToIPs := map[string]string{}
for _, reservation := range ec2Result.Reservations {
for _, ec2Instance := range reservation.Instances {
if ec2Instance.PublicIpAddress != nil {
ec2ToIPs[*ec2Instance.InstanceId] = *ec2Instance.PublicIpAddress
} else {
ec2ToIPs[*ec2Instance.InstanceId] = *ec2Instance.PrivateIpAddress
}
}
}

for containerInstanceId, port := range bindings {
ec2ID, ok := containerInstanceToEC2[containerInstanceId]
if !ok {
common.Fatalln("Could not resolve the container instance to EC2")
}

ip, ok := ec2ToIPs[ec2ID]
if !ok {
common.Fatalln("Could not get an IP address for EC2")
}
fmt.Println(fmt.Sprintf("%s:%d", ip, port))
}

}

0 comments on commit 41ce49a

Please sign in to comment.