My program is designed to get a bunch of different objects from an API and manipulate them, then via loops (or some other method) and verify that some expected conditions exist and report when they do not.
More specifically, I'm checking that for each container in a docker swarm, the ports are open as per the service definition, on each worker on which the container runs.
I won't supply the whole program, but here are examples of the objects (cut down in size for posterity). Also be aware I've anonomised the data so there won't be matches where there ordinarily would be:
nodes_simple:
(A list of docker worker nodes)
[
{
"NodeID": "aaaaaaaaaaaaaaaaa_worker3",
"Hostname": "worker03"
},
{
"NodeID": "bbbbbbbbbbbbbbbbb_worker2",
"Hostname": "worker02"
},
]
services_simple:
(A list of Docker swarm services)
[
{
"ServiceID": "asdfadsfadsfsdafadssadf",
"Name": "service1",
"Ports": [
{
"Port": 31900,
"Protocol": "tcp"
},
{
"Port": 31901,
"Protocol": "tcp"
}
]
},
{
"ServiceID": "dfadsasffafgergerg",
"Name": "service2",
"Ports": [
{
"Port": 30961,
"Protocol": "tcp"
},
{
"Port": 30965,
"Protocol": "tcp"
}
]
}
]
tasks_simple:
(A list of Docker swarm "tasks" - running containers, basically)
[
{
"ID": "afsdfsdfadsfasdfdsfdsa",
"ServiceID": "sdafasdfdsfsadfasdfa",
"NodeID": "asdfadsfasdfadsfadsfasdf",
"ContainerID": "gfsgadfgadffgdfgkdfhgikldjfijdajgiodaerjopijgjerjgidfjijgfioajdfg"
},
{
"ID": "afgadsfrgdfgadfgafdgadf",
"ServiceID": "asdggdfdgfdgfdgagdfgaga",
"NodeID": "ghjhdgyjhyjtyjtyjdtyj",
"ContainerID": "rgaegergaer876g8a7r6g897er6er6g76ar7e6ga786gre78a6rg786aeergaegre"
},
{
"ID": "agrggregrarggegergegr",
"ServiceID": "agdragregergagergergger",
"NodeID": "agregergrenrthjkfkhukujhku",
"ContainerID": "fd6fds7a6g7ds78fgvfdf7a6g6df87g678afd6g7f6adf876g7dfsa6786g87a6g7a"
}
]
worker_iptables:
(A list of dicts representing open ports on each Docker swarm node - taken from iptables)
[{'host': 'worker01',
'ports': [{'Port': '32555', 'Protocol': 'tcp'},
{'Port': '32505', 'Protocol': 'tcp'},
{'Port': '32555', 'Protocol': 'tcp'},
{'Port': '32505', 'Protocol': 'tcp'},
{'Port': '32235', 'Protocol': 'tcp'},
{'Port': '32235', 'Protocol': 'tcp'},
{'Port': '32655', 'Protocol': 'tcp'},
{'Port': '32655', 'Protocol': 'tcp'}]},
{'host': 'worker02',
'ports': [{'Port': '34553', 'Protocol': 'tcp'},
{'Port': '34503', 'Protocol': 'tcp'},
{'Port': '34553', 'Protocol': 'tcp'},
{'Port': '34503', 'Protocol': 'tcp'},
{'Port': '34233', 'Protocol': 'tcp'},
{'Port': '34233', 'Protocol': 'tcp'},
{'Port': '34653', 'Protocol': 'tcp'},
{'Port': '34653', 'Protocol': 'tcp'}]}]
I first manipulate the tasks_simple object and run a print line to help me make sense of it:
# Loop through each task.
# Replace NodeID with Node Name
# Replace ServiceID with Service Name
# Add in ports as per service to each task
for task in tasks_simple:
for node in nodes_simple:
if task['NodeID'] == node['NodeID']:
task['NodeID'] = node['Hostname']
for service in services_simple:
if task['ServiceID'] == service['ServiceID']:
task['ServiceID'] = service['Name']
task['Ports'] = service['Ports']
# If the task has ports
if 'Ports' in task:
print(f"Task {task['TaskID']} of Service {task['ServiceID']} should have Ports {task['Ports']} open on Worker {task['NodeID']}")
This manipulates the tasks_simple to look like:
[{'ContainerID': 'ew4f68we46we46f54we654f65we4f65we45ergsergdrgrdzgzdrgdgzdrgdrgdrg',
'NodeID': 'worker02',
'Ports': [{'Port': 30230, 'Protocol': 'tcp'},
{'Port': 30231, 'Protocol': 'tcp'}],
'ServiceID': 'service1',
'TaskID': 'sdfgdfgsdfgdsfgdsghgsfghfg'},
{'ContainerID': 'fdvgb87df6876a8d7sf68df6gv6df7g67fda67g6df7g6adf6g7a867fd6g7df6fg7',
'NodeID': 'worker02',
'Ports': [{'Port': 30650, 'Protocol': 'tcp'},
{'Port': 30651, 'Protocol': 'tcp'}],
'ServiceID': 'service2',
'TaskID': 'fgadfgdfgdfgsdgdsfgsfdg'},
{'ContainerID': 'adrfgdfg78df87g6df87g6d78f6ga876df78g6a7df6g78d6d78f6g7dfd7g7fd6gfd',
'NodeID': 'worker02',
'Ports': [{'Port': 31010, 'Protocol': 'tcp'},
{'Port': 31011, 'Protocol': 'tcp'}],
'ServiceID': 'service3',
'TaskID': 'sgfhftghfghfghgfghshgfshfgh'},
{'ContainerID': '3d341ab586a072cc1034cc85b97c8a45154f0a18ba1c16ba02db36954400b7c3',
'NodeID': 'worker03',
'ServiceID': 'service4',
'TaskID': '62kza6a2ylyf3sm2v3wb8ieey'},
{'ContainerID': 'fa8b6e2cb22049ed498bae27907fbb03ac096aee8c21c7005d28b2aa3bad69d0',
'NodeID': 'worker02',
'Ports': [{'Port': 30910, 'Protocol': 'tcp'},
{'Port': 30911, 'Protocol': 'tcp'}],
'ServiceID': 'service5',
'TaskID': '6vq6ck2fb106xs8nv3kdhf2d3'},
{'ContainerID': 'sthfthfthtfhfhfsthshtfshftrfhtfstrtttstgf78fd6g77fg6d7fg787fdf78d',
'NodeID': 'worker02',
'Ports': [{'Port': 31090, 'Protocol': 'tcp'}],
'ServiceID': 'helloworld-http',
'TaskID': '9t2fhl99o1e92p86hyhs1rjl6'}]
And prints output such as the following:
Task 4btbm94dd4xqad72ftpi9herv of Service service1 should have Ports [{'Port': 30230, 'Protocol': 'tcp'}, {'Port': 30231, 'Protocol': 'tcp'}] open on Worker worker02
Task 4qadgitrhranrs52zqujb0jdt of Service service2 should have Ports [{'Port': 30650, 'Protocol': 'tcp'}, {'Port': 30651, 'Protocol': 'tcp'}] open on Worker worker02
Task 5yzf2if8bf0qnsiomho3h4qtj of Service service3 should have Ports [{'Port': 31010, 'Protocol': 'tcp'}, {'Port': 31011, 'Protocol': 'tcp'}] open on Worker worker02
Task 6vq6ck2fb106xs8nv3kdhf2d3 of Service service4 should have Ports [{'Port': 30910, 'Protocol': 'tcp'}, {'Port': 30911, 'Protocol': 'tcp'}] open on Worker worker02
Task 9t2fhl99o1e92p86hyhs1rjl6 of Service helloworld-http should have Ports [{'Port': 31090, 'Protocol': 'tcp'}] open on Worker worker02
Task c3w7dkey89nb4s1lfjlkm8rad of Service service5 should have Ports [{'Port': 31500, 'Protocol': 'tcp'}] open on Worker worker03
At this point, I'm a bit lost and my comment
# Check that each port for the task is open on the worker which the task is running on
Is as far as I can get, having tried some super confusing loops and failed horribly. How can I "simply" check each port for a service is open on the worker(s) for which the container(s) are running on?
This is to get a handle on a pretty nasty Docker UCP/MKE bug where swarm ports that should be open on workers where containers are running suddenly aren't, so we can redeploy those services, which seems to fix the problem.