Docker container that lists running containers and stores information on them in etcd
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

report.py 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #!/usr/bin/env python3
  2. from collections import defaultdict
  3. import argparse
  4. import docker
  5. import etcd
  6. import sys
  7. def etcd_put(client, prefix, obj):
  8. for key, value in obj.items():
  9. new_prefix = "%s/%s" % (prefix, key)
  10. if isinstance(value, dict):
  11. etcd_put(client, new_prefix, value)
  12. else:
  13. client.write(new_prefix, str(value))
  14. def get_addresses(container):
  15. return {k: v['IPAddress'] for k, v in container['NetworkSettings']['Networks'].items()}
  16. def get_ports(container):
  17. ports = defaultdict(dict)
  18. for port in container['Ports']:
  19. ports[port['Type']][port['PrivatePort']] = port['PublicPort'] if 'PublicPort' in port else 0
  20. return ports
  21. def add_containers(infos):
  22. global containers, host_index, label_index, network_index
  23. for info in infos:
  24. container = {
  25. 'host': host,
  26. 'image': info['Image'],
  27. 'labels': info['Labels'],
  28. 'net': {
  29. 'addr': get_addresses(info),
  30. 'ports': get_ports(info)
  31. }
  32. }
  33. name = info['Names'][0][1:]
  34. containers[name] = container
  35. for k, v in container['labels'].items():
  36. label_index[k][name] = v
  37. for k, v in container['net']['addr'].items():
  38. network_index[k][name] = v
  39. host_index[host][name] = name
  40. def write_all():
  41. etcd_put(etcd_client, prefix + '/containers', containers)
  42. etcd_put(etcd_client, prefix + '/labels', label_index)
  43. etcd_put(etcd_client, prefix + '/networks', network_index)
  44. etcd_put(etcd_client, prefix + '/hosts', host_index)
  45. parser = argparse.ArgumentParser()
  46. parser.add_argument('--name', help='Name of this docker host', default='unknown')
  47. parser.add_argument('--etcd-port', type=int, help='Port to connect to etcd on', default=2379)
  48. parser.add_argument('--etcd-host', help='Host to connect to etcd on', default='etcd')
  49. parser.add_argument('--etcd-prefix', help='Prefix to use when adding keys to etcd', default='/docker')
  50. args = parser.parse_args()
  51. docker_client = docker.Client(base_url='unix://var/run/docker.sock')
  52. etcd_client = etcd.Client(host=args.etcd_host, port=args.etcd_port)
  53. prefix = args.etcd_prefix
  54. host = args.name
  55. event_gen = docker_client.events(decode=True, filters={'type': 'container', 'event': ['die', 'start']})
  56. containers = {}
  57. label_index = defaultdict(dict)
  58. network_index = defaultdict(dict)
  59. host_index = defaultdict(dict)
  60. add_containers(docker_client.containers())
  61. try:
  62. etcd_client.delete(prefix, recursive=True)
  63. except etcd.EtcdKeyNotFound:
  64. pass
  65. write_all()
  66. for event in event_gen:
  67. if event['Action'] == 'start':
  68. print('New container %s' % event['id'])
  69. add_containers(docker_client.containers(filters={'id': event['id']}))
  70. write_all()
  71. elif event['Action'] == 'die':
  72. print('Dead container %s' % event['id'])
  73. else:
  74. print('Unexpected event %s' % event['Action'])