Skip to content

Commit d802f3b

Browse files
committed
add support for specifying AWS region, which also removes the dependency
on talking to a local ECS agent. useful for external monitoring systems.
1 parent cf54cfc commit d802f3b

File tree

2 files changed

+53
-21
lines changed

2 files changed

+53
-21
lines changed

main.go

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ func getContainerInstanceArnsForService(ecs_obj *ecs.ECS, cluster string, servic
122122
}
123123

124124
if len(list_tasks_resp.TaskArns) <= 0 {
125-
fmt.Println("No ECS tasks found with specified filter - cluster:", cluster, ",service:", service)
125+
fmt.Println("No ECS tasks found with specified filter - cluster: ", cluster, ", service:", service)
126126
os.Exit(1)
127127
}
128128

@@ -239,21 +239,29 @@ func getEc2PrivateIpsFromInstanceIds(ec2_obj *ec2.EC2, instance_ids []string, de
239239
return result
240240
}
241241

242-
func doMain(current_cluster bool, cluster_name string, ecs_service string, debug bool) {
243-
// Get the metadata from the ECS agent on the local Docker host.
244-
local_ecs_agent_metadata := getEcsAgentMetadata()
242+
func doMain(current_cluster bool, aws_region string, cluster_name string, ecs_service string, debug bool) {
243+
var local_ecs_agent_metadata EcsAgentMetadata
244+
if current_cluster == true {
245+
// Get the metadata from the ECS agent on the local Docker host.
246+
local_ecs_agent_metadata = getEcsAgentMetadata()
247+
}
245248

246-
// Discover the region which this instance resides.
247-
metadata := ec2metadata.New(session.New())
248-
region, err := metadata.Region()
249-
if err != nil {
250-
fmt.Println("Cannot retrieve AWS region from EC2 Metadata Service:")
251-
formatAwsError(err)
252-
os.Exit(1)
249+
var region string
250+
if aws_region != "" {
251+
region = aws_region
252+
} else {
253+
// Discover the region which this instance resides.
254+
metadata := ec2metadata.New(session.New())
255+
use_region, err := metadata.Region()
256+
if err != nil {
257+
fmt.Println("Cannot retrieve AWS region from EC2 Metadata Service:")
258+
formatAwsError(err)
259+
os.Exit(1)
260+
}
261+
region = use_region
253262
}
254263

255264
// Reusable config session object for AWS services with current region attached.
256-
// TODOLATER: support other regions via a flag.
257265
aws_config_session := session.New(&aws.Config{Region: aws.String(region)})
258266

259267
// Create an ECS service object.
@@ -279,8 +287,12 @@ func doMain(current_cluster bool, cluster_name string, ecs_service string, debug
279287
// readme states ports are outside the scope for now.
280288

281289
// Get all tasks for the given service, in this ECS cluster. We exclude the current container instance in the result,
282-
// as we only need to know about all other instances.
283-
container_instances := getContainerInstanceArnsForService(ecs_obj, ecs_cluster, ecs_service, local_ecs_agent_metadata.ContainerInstanceArn, debug)
290+
// as we only need to know about all other instances. The exclusion only occurs when we are working on the current cluster.
291+
current_container_instance_arn := "NONE"
292+
if current_cluster == true {
293+
current_container_instance_arn = local_ecs_agent_metadata.ContainerInstanceArn
294+
}
295+
container_instances := getContainerInstanceArnsForService(ecs_obj, ecs_cluster, ecs_service, current_container_instance_arn, debug)
284296
if debug == true {
285297
fmt.Println("container_instances:", strings.Join(container_instances, ","))
286298
}
@@ -300,30 +312,38 @@ func doMain(current_cluster bool, cluster_name string, ecs_service string, debug
300312
fmt.Println(strings.Join(instance_private_ips, ","))
301313
}
302314

303-
func parseFlags(c *cli.Context) (bool, string, string, bool) {
315+
// current_cluster, aws_region, cluster, service, debug
316+
func parseFlags(c *cli.Context) (bool, string, string, string, bool) {
304317
current_cluster := false
305318
cluster := ""
319+
aws_region := ""
306320
if c.String("c") == "" {
307321
current_cluster = true
308322
} else {
309323
cluster = c.String("c")
324+
if c.String("r") == "" {
325+
fmt.Printf("Error: If Cluster (-c) is specified, AWS Region (-r) is also required. Cannot proceed.\n\n")
326+
cli.ShowAppHelp(c)
327+
os.Exit(1)
328+
}
329+
aws_region = c.String("r")
310330
}
311331
if c.String("s") == "" {
312332
fmt.Printf("Error: Service (-s) must not be empty. Cannot proceed.\n\n")
313333
cli.ShowAppHelp(c)
314334
os.Exit(1)
315335
}
316-
return current_cluster, cluster, c.String("s"), c.Bool("d")
336+
return current_cluster, aws_region, cluster, c.String("s"), c.Bool("d")
317337
}
318338

319339
func main() {
320340
app := cli.NewApp()
321341
app.Name = "ecs-discoverer"
322-
app.Version = "0.3.1"
342+
app.Version = "0.3.2"
323343
app.Usage = "Discovery tool for Private IPs of ECS EC2 Container Instances for a given Service/Cluster"
324344
app.Action = func(c *cli.Context) {
325-
current_cluster, cluster, service, debug := parseFlags(c)
326-
doMain(current_cluster, cluster, service, debug)
345+
current_cluster, aws_region, cluster, service, debug := parseFlags(c)
346+
doMain(current_cluster, aws_region, cluster, service, debug)
327347
}
328348
app.Flags = []cli.Flag{
329349
cli.StringFlag{
@@ -335,6 +355,11 @@ func main() {
335355
Name: "d",
336356
Usage: "Debug Mode",
337357
},
358+
cli.StringFlag{
359+
Name: "r",
360+
Value: "",
361+
Usage: "AWS Region (Optional - defaults to the location of this ECS Cluster instance)",
362+
},
338363
cli.StringFlag{
339364
Name: "s",
340365
Value: "",

main_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,19 @@ import (
99
func TestParseFlags(t *testing.T) {
1010
set1 := flag.NewFlagSet("test1", 0)
1111
set1.String("c", "somecluster", "doc")
12+
set1.String("r", "someregion", "doc")
1213
set1.String("s", "someservice", "doc")
1314
context1 := cli.NewContext(nil, set1, nil)
14-
current_cluster1, cluster1, service1, debug1 := parseFlags(context1)
15+
current_cluster1, aws_region1, cluster1, service1, debug1 := parseFlags(context1)
1516
if current_cluster1 != false {
1617
t.Error("Expected current_cluster1 to be false, got", current_cluster1)
1718
}
1819
if cluster1 != "somecluster" {
1920
t.Error("Expected cluster1 to be somecluster, got", cluster1)
2021
}
22+
if aws_region1 != "someregion" {
23+
t.Error("Expected aws_region1 to be someregion, got", aws_region1)
24+
}
2125
if service1 != "someservice" {
2226
t.Error("Expected service1 to be someservice, got", service1)
2327
}
@@ -29,13 +33,16 @@ func TestParseFlags(t *testing.T) {
2933
set2.String("s", "someotherservice", "doc")
3034
set2.Bool("d", true, "doc")
3135
context2 := cli.NewContext(nil, set2, nil)
32-
current_cluster2, cluster2, service2, debug2 := parseFlags(context2)
36+
current_cluster2, aws_region2, cluster2, service2, debug2 := parseFlags(context2)
3337
if current_cluster2 != true {
3438
t.Error("Expected current_cluster1 to be true, got", current_cluster1)
3539
}
3640
if cluster2 != "" {
3741
t.Error("Expected cluster2 to be empty '', got", cluster2)
3842
}
43+
if aws_region2 != "" {
44+
t.Error("Expected aws_region2 to be empty '', got", aws_region2)
45+
}
3946
if service2 != "someotherservice" {
4047
t.Error("Expected service2 to be someservice, got", service2)
4148
}

0 commit comments

Comments
 (0)