-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdocker_signal.py
More file actions
119 lines (84 loc) · 3.54 KB
/
docker_signal.py
File metadata and controls
119 lines (84 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import os
import sys
import time
import random
import logging
import argparse
import docker
from docker.types.services import ServiceMode, RestartPolicy
from docker_helper import get_current_container_id
from config import read_configuration
from notifications import NotificationManager
logger = logging.getLogger('docker-signal')
def send_signal(client, label):
for container in client.containers.list(filters={'label': label}):
signal = container.labels.get(label)
if signal:
logger.info('Signalling %s [%s] - %s' % (container.name, container.id, signal))
container.kill(signal)
class DockerSignalNotification(NotificationManager):
def __init__(self):
super(DockerSignalNotification, self).__init__()
self.client = docker.from_env()
self.label_name = read_configuration(
'DOCKER_SIGNAL_LABEL', '/var/secrets/notifications', 'domain.automation.signal'
)
def ssl_updated(self, subdomain, result):
if not result or not result.startswith('OK'):
return
if len(self.client.swarm.attrs) > 0:
self._send_signal_in_swarm()
else:
send_signal(self.client, self.label_name)
def _send_signal_in_swarm(self):
current_container_id = get_current_container_id()
if not current_container_id:
return
current_container = self.client.containers.get(current_container_id)
if not current_container:
return
image = current_container.attrs['Config'].get('Image')
if not image:
return
command = [
sys.executable, __file__, '--label', self.label_name
]
log_driver = current_container.attrs['HostConfig']['LogConfig']['Type']
log_config = current_container.attrs['HostConfig']['LogConfig']['Config']
sender = self.client.services.create(
image=image, command=command,
name='domain-automation-signal-%d-%d' % (
int(time.time() * 1000), random.randint(100, 999)
),
env=['PYTHONPATH=%s' % os.environ.get('PYTHONPATH', '.')],
log_driver=log_driver, log_driver_options=log_config,
mode=ServiceMode('global'),
restart_policy=RestartPolicy(condition='none', max_attempts=0),
mounts=['/var/run/docker.sock:/var/run/docker.sock:ro']
)
max_wait = 60
start_time = time.time()
while abs(time.time() - start_time) < max_wait:
if all(task['DesiredState'] == 'shutdown' for task in sender.tasks()):
break
time.sleep(1)
states = list(task['Status']['State'] for task in sender.tasks())
logs = ''.join(
item.decode() if hasattr(item, 'decode') else item
for item in sender.logs(stdout=True, stderr=True)
).strip()
sender.remove()
logger.info(
'Signalled containers with label %s - result: %s' %
(self.label_name, ', '.join(map(str, states)))
)
if logs:
logger.info('Signal logs: %s' % logs)
def main(client, args=sys.argv[1:]):
logging.basicConfig(format='%(asctime)s [%(levelname)s] %(module)s.%(funcName)s - %(message)s')
parser = argparse.ArgumentParser(description='Docker signal sender')
parser.add_argument('--label', required=True, help='The target container label name')
arguments = parser.parse_args(args)
send_signal(client, arguments.label)
if __name__ == '__main__':
main(docker.from_env())