-
Notifications
You must be signed in to change notification settings - Fork 1
/
_operations_docker.py
155 lines (120 loc) · 5.09 KB
/
_operations_docker.py
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# coding=utf-8
"""This module, _operations_docker.py, is used to run health checks on Docker features such as networks and volumes."""
from libraries.universal_code.system_abstraction import bash_interactive as bi
from libraries.universal_code.system_abstraction.python_shell_script import PythonShellScript
from libraries.universal_code.system_abstraction import bash_interactive as bash
from libraries.universal_code import output_coloring as oc
from libraries.universal_code.common_traits.trait_name import TraitName
import sys
ARG_OPERATION_ENSURE_NETWORK = 'n'
ARG_OPERATION_ENSURE_VOLUME = 'v'
ARG_OPERATION_CONNECT_TO_CONTAINER = 'c'
class DockerFeature(TraitName):
"""Represents the state of a Docker feature (such as networks and volumes)."""
def __init__(self, name, feature_type):
TraitName.__init__(self, name)
self.feature_type = feature_type
self.alive = None
def run(self):
"""Runs the health check on this Docker feature."""
self.alive = self.is_feature_alive()
if self.alive:
oc.print_data_with_red_dashes_at_start('The ' + self.feature_type + '{' + self.name + '} exists!')
else:
oc.print_data_with_red_dashes_at_start('Created ' + self.feature_type + '{' + self.name + '}!')
self.create_new_feature_instance()
def is_feature_alive(self):
"""Checks if the feature is alive."""
success, details = bash.BashCommandRunner('docker ' + self.feature_type + ' inspect ' + self.name, require_input=True).run()
return success
def create_new_feature_instance(self):
"""Implemented by discrete object types."""
pass
class DockerFeatureNetwork(DockerFeature):
"""Checks the Docker network."""
def __init__(self, name):
super().__init__(name, 'network')
def create_new_feature_instance(self):
"""Creates this particular feature."""
bash.BashCommandRunner('docker network create -d bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 ' + self.name).run()
class DockerFeatureVolume(DockerFeature):
"""Checks the Docker volume."""
def __init__(self, name):
super().__init__(name, 'volume')
def create_new_feature_instance(self):
"""Creates this particular feature."""
bash.BashCommandRunner('docker volume create --name ' + self.name).run()
class DockerConnectToRunningContainer(object):
"""Connects to a Docker container. Does not actually use SSH."""
def __init__(self):
self._running_containers = []
self._image_names_to_container_ids = {}
def _get_start_positions_of_cols(self, line):
"""Utility function."""
start_positions = [0]
in_word = True
index = 0
for c in line:
if c != ' ':
if not in_word:
in_word = True
start_positions.append(index)
else:
if in_word:
in_word = False
index += 1
# TODO: FIX THIS REALLY BAD SOLUTION! ('CONTAINER ID has a space').
start_positions.remove(10)
return start_positions
def _parse_output(self, o):
"""Utility function."""
cols = []
col_starts = self._get_start_positions_of_cols(o[0])
lines = o[1:]
for l in lines:
elements = []
for i, p in enumerate(col_starts):
if i == len(col_starts) - 1:
elements.append((l[col_starts[i]:len(l)]).rstrip())
else:
elements.append((l[col_starts[i]:col_starts[i + 1]]).rstrip())
cols.append(elements)
return cols
def run(self):
"""TODO:"""
output = bash.BashCommandRunner(['docker', 'ps', '--no-trunc']).run(cwd=None, raise_exception=True, get_as_lines=True)
cols = self._parse_output(output)
if len(cols) == 0:
oc.print_data_with_red_dashes_at_start('There are currently no Docker containers running.')
else:
sys.stdout.flush()
container_list = bi.BashPromptListSelection('container_choice', 'choose a running container to ssh into')
sys.stdout.flush()
for c in cols:
container_id = c[0]
image_name = c[1]
#self._prompt_choices.append([image_name, container_id])
self._image_names_to_container_ids[image_name] = container_id
container_list.add_selection_choice(image_name, 'connect')
selection = container_list.run()
image_name = selection[0]
#print('CHOSEN IMAGE {' + image_name + '}')
#print('CHOSEN CONTAINER ID {' + self._image_names_to_container_ids[image_name] + '}')
#sys.stdout.flush()
#sys.stderr.write(self._image_names_to_container_ids[image_name])
# docker exec -it ${CONTAINER_ID} /bin/bash
sys.stderr.write('docker exec -it ' + self._image_names_to_container_ids[image_name] + ' /bin/bash')
class DockerFeatureChecker(PythonShellScript):
"""Used to ensure a specific Docker feature is up and running."""
def __init__(self):
super().__init__()
network = DockerFeatureNetwork('nexus_network')
volume = DockerFeatureVolume('nexus_volume')
connect = DockerConnectToRunningContainer()
self.add_argument(ARG_OPERATION_ENSURE_NETWORK, 'Ensure default external network exists.', network.run)
self.add_argument(ARG_OPERATION_ENSURE_VOLUME, 'Ensure default external volume exists.', volume.run)
self.add_argument(ARG_OPERATION_CONNECT_TO_CONTAINER, 'Connect to a running Docker container.', connect.run)
self.at_least_one_argument_required = True
if __name__ == "__main__":
script = DockerFeatureChecker()
script.run()