Skip to content

Commit

Permalink
Add ECS tags for docker check, add docker-py as a req
Browse files Browse the repository at this point in the history
  • Loading branch information
hkaj authored and Remi Hakim committed Sep 3, 2015
1 parent 81531f4 commit fb48929
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 2 deletions.
41 changes: 41 additions & 0 deletions checks.d/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import httplib
import os
import re
import requests
import socket
import time
import urllib
Expand All @@ -13,6 +14,7 @@
from checks import AgentCheck
from config import _is_affirmative
from util import json
from utils.platform import Platform

EVENT_TYPE = SOURCE_TYPE_NAME = 'docker'

Expand Down Expand Up @@ -175,8 +177,16 @@ def _get_and_count_containers(self, instance):

running_containers_ids = set([container['Id'] for container in running_containers])

# Dict of container ids and a list of their Amazon ECS task tags
if Platform.is_ecs_instance() and instance.get('ecs_tags', True):
ecs_tags = self._get_ecs_tags(instance, running_containers)
else:
ecs_tags = None

for container in all_containers:
container_tags = list(tags)
if ecs_tags:
container_tags += ecs_tags.get(container['Id'], [])
for key in DOCKER_TAGS:
tag = self._make_tag(key, container[key], instance)
if tag:
Expand Down Expand Up @@ -229,11 +239,18 @@ def _report_containers_metrics(self, containers, instance):
collect_uncommon_metrics = _is_affirmative(instance.get("collect_all_metrics", False))
tags = instance.get("tags", [])

if Platform.is_ecs_instance() and instance.get('ecs_tags', True):
ecs_tags = self._get_ecs_tags(instance, containers)
else:
ecs_tags = None

# Pre-compile regex to include/exclude containers
use_filters = self._prepare_filters(instance)

for container in containers:
container_tags = list(tags)
if ecs_tags:
container_tags += ecs_tags.get(container['Id'], [])
for name in container["Names"]:
container_tags.append(self._make_tag("name", name.lstrip("/"), instance))
for key in DOCKER_TAGS:
Expand Down Expand Up @@ -277,6 +294,26 @@ def _new_tags_conversion(self, tag):
# Prefix tags to avoid conflict with AWS tags
return NEW_TAGS_MAP.get(tag, tag)

def _get_ecs_tags(self, instance, containers):
ecs_id = None
for co in containers:
if '/ecs-agent' in co.get('Names', []):
ecs_id = co.get('Id')
if ecs_id is None:
return []
ecs_config = self._inspect_container(instance, ecs_id)
net_conf = ecs_config['NetworkSettings'].get('Ports', {})
net_conf = net_conf.get(net_conf.keys()[0], [])
container_tags = {}
if net_conf:
net_conf = net_conf[0] if isinstance(net_conf, list) else net_conf
ip, port = ecs_config.get('NetworkSettings', {})['IPAddress'], net_conf.get('HostPort')
tasks = requests.get('http://%s:%s/v1/tasks' % (ip, port)).json()
for task in tasks.get('Tasks', []):
for container in task.get('Containers', []):
tags = ['task_name:%s' % task['Family'], 'task_version:%s' % task['Version']]
container_tags[container['DockerId']] = tags
return container_tags

# Events

Expand Down Expand Up @@ -354,6 +391,10 @@ def _get_containers(self, instance, with_size=False, get_all=False):
"""Gets the list of running/all containers in Docker."""
return self._get_json("%(url)s/containers/json" % instance, params={'size': with_size, 'all': get_all})

def _inspect_container(self, instance, container_id):
"""Get the list of running/all containers in Docker."""
return self._get_json("%s/containers/%s/json" % (instance['url'], container_id))

def _get_images(self, instance, with_size=True, get_all=False):
"""Gets the list of images in Docker."""
return self._get_json("%(url)s/images/json" % instance, params={'all': get_all})
Expand Down
5 changes: 5 additions & 0 deletions conf.d/docker.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ instances:
# Example:
# tags: ["extra_tag", "env:example"]

# If the agent is running in an Amazon ECS task, tags container metrics with the ECS task name and version.
# Default: true
#
# ecs_tags: false

# Exclude containers based on their tags
# An excluded container will ne longer report performance metrics or events. However,
# we still count the number of running and stopped of all containers.
Expand Down
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,6 @@ pyvmomi==5.5.0.2014.1.1

# checks.d/hdfs.py
snakebite==1.3.11

# utils/platform.py
docker-py==1.3.1
2 changes: 1 addition & 1 deletion util.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def _get_hostname_unix():
hostname = unix_hostname

# if we have an ec2 default hostname, see if there's an instance-id available
if hostname is not None and True in [hostname.lower().startswith(p) for p in [u'ip-', u'domu']]:
if (Platform.is_ecs_instance()) or (hostname is not None and True in [hostname.lower().startswith(p) for p in [u'ip-', u'domu']]):
instanceid = EC2.get_instance_id(config)
if instanceid:
hostname = instanceid
Expand Down
12 changes: 11 additions & 1 deletion utils/platform.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import sys

import docker

class Platform(object):
"""
Expand Down Expand Up @@ -53,3 +53,13 @@ def is_win32(name=None):
@staticmethod
def is_windows(name=None):
return Platform.is_win32(name)

@staticmethod
def is_ecs_instance():
"""Return True if the agent is running in an ECS instance, False otherwise."""
cl = docker.Client(version='auto')
containers = cl.containers()
for co in containers:
if '/ecs-agent' in co.get('Names', ''):
return True
return False

0 comments on commit fb48929

Please sign in to comment.