illumio-pylo 0.2.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- illumio_pylo/API/APIConnector.py +1308 -0
- illumio_pylo/API/AuditLog.py +42 -0
- illumio_pylo/API/ClusterHealth.py +136 -0
- illumio_pylo/API/CredentialsManager.py +286 -0
- illumio_pylo/API/Explorer.py +1077 -0
- illumio_pylo/API/JsonPayloadTypes.py +240 -0
- illumio_pylo/API/RuleSearchQuery.py +128 -0
- illumio_pylo/API/__init__.py +0 -0
- illumio_pylo/AgentStore.py +139 -0
- illumio_pylo/Exception.py +44 -0
- illumio_pylo/Helpers/__init__.py +3 -0
- illumio_pylo/Helpers/exports.py +508 -0
- illumio_pylo/Helpers/functions.py +166 -0
- illumio_pylo/IPList.py +135 -0
- illumio_pylo/IPMap.py +285 -0
- illumio_pylo/Label.py +25 -0
- illumio_pylo/LabelCommon.py +48 -0
- illumio_pylo/LabelGroup.py +68 -0
- illumio_pylo/LabelStore.py +403 -0
- illumio_pylo/LabeledObject.py +25 -0
- illumio_pylo/Organization.py +258 -0
- illumio_pylo/Query.py +331 -0
- illumio_pylo/ReferenceTracker.py +41 -0
- illumio_pylo/Rule.py +671 -0
- illumio_pylo/Ruleset.py +306 -0
- illumio_pylo/RulesetStore.py +101 -0
- illumio_pylo/SecurityPrincipal.py +62 -0
- illumio_pylo/Service.py +256 -0
- illumio_pylo/SoftwareVersion.py +125 -0
- illumio_pylo/VirtualService.py +17 -0
- illumio_pylo/VirtualServiceStore.py +75 -0
- illumio_pylo/Workload.py +506 -0
- illumio_pylo/WorkloadStore.py +289 -0
- illumio_pylo/__init__.py +82 -0
- illumio_pylo/cli/NativeParsers.py +96 -0
- illumio_pylo/cli/__init__.py +134 -0
- illumio_pylo/cli/__main__.py +10 -0
- illumio_pylo/cli/commands/__init__.py +32 -0
- illumio_pylo/cli/commands/credential_manager.py +168 -0
- illumio_pylo/cli/commands/iplist_import_from_file.py +185 -0
- illumio_pylo/cli/commands/misc.py +7 -0
- illumio_pylo/cli/commands/ruleset_export.py +129 -0
- illumio_pylo/cli/commands/update_pce_objects_cache.py +44 -0
- illumio_pylo/cli/commands/ven_duplicate_remover.py +366 -0
- illumio_pylo/cli/commands/ven_idle_to_visibility.py +287 -0
- illumio_pylo/cli/commands/ven_upgrader.py +226 -0
- illumio_pylo/cli/commands/workload_export.py +251 -0
- illumio_pylo/cli/commands/workload_import.py +423 -0
- illumio_pylo/cli/commands/workload_relabeler.py +510 -0
- illumio_pylo/cli/commands/workload_reset_names_to_null.py +83 -0
- illumio_pylo/cli/commands/workload_used_in_rule_finder.py +80 -0
- illumio_pylo/docs/Doxygen +1757 -0
- illumio_pylo/tmp.py +104 -0
- illumio_pylo/utilities/__init__.py +0 -0
- illumio_pylo/utilities/cli.py +10 -0
- illumio_pylo/utilities/credentials.example.json +20 -0
- illumio_pylo/utilities/explorer_report_exporter.py +86 -0
- illumio_pylo/utilities/health_monitoring.py +102 -0
- illumio_pylo/utilities/iplist_analyzer.py +148 -0
- illumio_pylo/utilities/iplists_stats_duplicates_unused_finder.py +75 -0
- illumio_pylo/utilities/resources/iplists-import-example.csv +3 -0
- illumio_pylo/utilities/resources/iplists-import-example.xlsx +0 -0
- illumio_pylo/utilities/resources/workload-exporter-filter-example.csv +3 -0
- illumio_pylo/utilities/resources/workloads-import-example.csv +2 -0
- illumio_pylo/utilities/resources/workloads-import-example.xlsx +0 -0
- illumio_pylo/utilities/ven_compatibility_report_export.py +240 -0
- illumio_pylo/utilities/ven_idle_to_illumination.py +344 -0
- illumio_pylo/utilities/ven_reassign_pce.py +183 -0
- illumio_pylo-0.2.5.dist-info/LICENSE +176 -0
- illumio_pylo-0.2.5.dist-info/METADATA +197 -0
- illumio_pylo-0.2.5.dist-info/RECORD +73 -0
- illumio_pylo-0.2.5.dist-info/WHEEL +5 -0
- illumio_pylo-0.2.5.dist-info/top_level.txt +1 -0
illumio_pylo/Service.py
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import illumio_pylo as pylo
|
|
2
|
+
from .API.JsonPayloadTypes import ServiceHrefRef
|
|
3
|
+
from illumio_pylo import log
|
|
4
|
+
from .Helpers import *
|
|
5
|
+
from typing import *
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PortMap:
|
|
9
|
+
def __init__(self):
|
|
10
|
+
self._tcp_map = []
|
|
11
|
+
self._udp_map = []
|
|
12
|
+
self._protocol_map = {}
|
|
13
|
+
|
|
14
|
+
def add(self, protocol, start_port: int, end_port: int = None, skip_recalculation=False):
|
|
15
|
+
|
|
16
|
+
proto = None
|
|
17
|
+
|
|
18
|
+
if type(protocol) is str:
|
|
19
|
+
lower = protocol.lower()
|
|
20
|
+
if lower == 'tcp':
|
|
21
|
+
proto = 6
|
|
22
|
+
elif lower == 'udp':
|
|
23
|
+
proto = 17
|
|
24
|
+
else:
|
|
25
|
+
raise pylo.PyloEx("Unsupported protocol name '{}'".format(protocol))
|
|
26
|
+
else:
|
|
27
|
+
proto = protocol
|
|
28
|
+
|
|
29
|
+
if proto != 6 and proto != 17:
|
|
30
|
+
self._protocol_map[proto] = True
|
|
31
|
+
return
|
|
32
|
+
|
|
33
|
+
if start_port is None:
|
|
34
|
+
end_port = start_port
|
|
35
|
+
|
|
36
|
+
new_entry = [start_port, end_port]
|
|
37
|
+
|
|
38
|
+
if not skip_recalculation:
|
|
39
|
+
self.merge_overlapping_maps()
|
|
40
|
+
|
|
41
|
+
def merge_overlapping_maps(self):
|
|
42
|
+
self._sort_maps()
|
|
43
|
+
|
|
44
|
+
new_map = []
|
|
45
|
+
|
|
46
|
+
cur_entry = None
|
|
47
|
+
|
|
48
|
+
for original_entry in self._tcp_map:
|
|
49
|
+
if cur_entry is None:
|
|
50
|
+
cur_entry = original_entry
|
|
51
|
+
continue
|
|
52
|
+
|
|
53
|
+
cur_start = cur_entry[0]
|
|
54
|
+
cur_end = cur_entry[1]
|
|
55
|
+
new_start = original_entry[0]
|
|
56
|
+
new_end = original_entry[1]
|
|
57
|
+
|
|
58
|
+
if new_start > cur_end + 1:
|
|
59
|
+
new_map.append(cur_entry)
|
|
60
|
+
continue
|
|
61
|
+
|
|
62
|
+
if new_end > cur_end:
|
|
63
|
+
cur_entry[1] = new_end
|
|
64
|
+
|
|
65
|
+
if cur_entry is not None:
|
|
66
|
+
self._tcp_map = []
|
|
67
|
+
else:
|
|
68
|
+
new_map.append(cur_entry)
|
|
69
|
+
self._tcp_map = new_map
|
|
70
|
+
|
|
71
|
+
new_map = []
|
|
72
|
+
|
|
73
|
+
for original_entry in self._udp_map:
|
|
74
|
+
if cur_entry is None:
|
|
75
|
+
cur_entry = original_entry
|
|
76
|
+
continue
|
|
77
|
+
|
|
78
|
+
cur_start = cur_entry[0]
|
|
79
|
+
cur_end = cur_entry[1]
|
|
80
|
+
new_start = original_entry[0]
|
|
81
|
+
new_end = original_entry[1]
|
|
82
|
+
|
|
83
|
+
if new_start > cur_end + 1:
|
|
84
|
+
new_map.append(cur_entry)
|
|
85
|
+
continue
|
|
86
|
+
|
|
87
|
+
if new_end > cur_end:
|
|
88
|
+
cur_entry[1] = new_end
|
|
89
|
+
|
|
90
|
+
if cur_entry is not None:
|
|
91
|
+
self._udp_map = []
|
|
92
|
+
else:
|
|
93
|
+
new_map.append(cur_entry)
|
|
94
|
+
self._udp_map = new_map
|
|
95
|
+
|
|
96
|
+
def _sort_maps(self):
|
|
97
|
+
def first_entry(my_list):
|
|
98
|
+
return my_list[0]
|
|
99
|
+
|
|
100
|
+
self._tcp_map.sort(key=first_entry)
|
|
101
|
+
self._udp_map.sort(key=first_entry)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class ServiceEntry:
|
|
105
|
+
def __init__(self, protocol: int, port: int = None, to_port: Optional[int] = None, icmp_code: Optional[int] = None,
|
|
106
|
+
icmp_type: Optional[int] = None):
|
|
107
|
+
self.protocol = protocol
|
|
108
|
+
self.port: int = port
|
|
109
|
+
self.to_port: Optional[int] = to_port
|
|
110
|
+
self.icmp_type: Optional[int] = icmp_type
|
|
111
|
+
self.icmp_code: Optional[int] = icmp_code
|
|
112
|
+
|
|
113
|
+
@staticmethod
|
|
114
|
+
def create_from_json(data: Dict):
|
|
115
|
+
protocol = data['proto']
|
|
116
|
+
if protocol == 1:
|
|
117
|
+
icmp_code = data['icmp_code']
|
|
118
|
+
icmp_type = data['icmp_type']
|
|
119
|
+
entry = ServiceEntry(protocol, icmp_code=icmp_code, icmp_type=icmp_type)
|
|
120
|
+
elif protocol == 17 or protocol == 6:
|
|
121
|
+
port = data['port']
|
|
122
|
+
to_port = data.get('to_port')
|
|
123
|
+
entry = ServiceEntry(protocol, port=port, to_port=to_port)
|
|
124
|
+
else:
|
|
125
|
+
entry = ServiceEntry(protocol)
|
|
126
|
+
|
|
127
|
+
return entry
|
|
128
|
+
|
|
129
|
+
def is_tcp(self) -> bool:
|
|
130
|
+
return self.protocol == 6
|
|
131
|
+
|
|
132
|
+
def is_udp(self) -> bool:
|
|
133
|
+
return self.protocol == 17
|
|
134
|
+
|
|
135
|
+
def to_string_standard(self, protocol_first=True) -> str:
|
|
136
|
+
|
|
137
|
+
if self.protocol == -1:
|
|
138
|
+
return 'All Services'
|
|
139
|
+
|
|
140
|
+
if protocol_first:
|
|
141
|
+
if self.protocol == 17:
|
|
142
|
+
if self.to_port is None:
|
|
143
|
+
return 'udp/' + str(self.port)
|
|
144
|
+
return 'udp/' + str(self.port) + '-' + str(self.to_port)
|
|
145
|
+
elif self.protocol == 6:
|
|
146
|
+
if self.to_port is None:
|
|
147
|
+
return 'tcp/' + str(self.port)
|
|
148
|
+
return 'tcp/' + str(self.port) + '-' + str(self.to_port)
|
|
149
|
+
|
|
150
|
+
return 'proto/' + str(self.protocol)
|
|
151
|
+
|
|
152
|
+
if self.protocol == 17:
|
|
153
|
+
if self.to_port is None:
|
|
154
|
+
return str(self.port) + '/udp'
|
|
155
|
+
return str(self.port) + '-' + str(self.to_port) + '/udp'
|
|
156
|
+
elif self.protocol == 6:
|
|
157
|
+
if self.to_port is None:
|
|
158
|
+
return str(self.port) + '/tcp'
|
|
159
|
+
return str(self.port) + '-' + str(self.to_port) + '/tcp'
|
|
160
|
+
|
|
161
|
+
return str(self.protocol) + '/proto'
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class Service(pylo.ReferenceTracker):
|
|
165
|
+
|
|
166
|
+
def __init__(self, name: str, href: str, owner: 'pylo.ServiceStore'):
|
|
167
|
+
pylo.ReferenceTracker.__init__(self)
|
|
168
|
+
|
|
169
|
+
self.owner: 'pylo.ServiceStore' = owner
|
|
170
|
+
self.name: str = name
|
|
171
|
+
self.href: str = href
|
|
172
|
+
|
|
173
|
+
self.entries: List['pylo.ServiceEntry'] = []
|
|
174
|
+
|
|
175
|
+
self.description: Optional[str] = None
|
|
176
|
+
self.processName: Optional[str] = None
|
|
177
|
+
|
|
178
|
+
self.deleted: bool = False
|
|
179
|
+
|
|
180
|
+
self.raw_json = None
|
|
181
|
+
|
|
182
|
+
def load_from_json(self, data):
|
|
183
|
+
self.raw_json = data
|
|
184
|
+
self.description = data['description']
|
|
185
|
+
|
|
186
|
+
self.processName = data['process_name']
|
|
187
|
+
|
|
188
|
+
service_ports = data.get('service_ports')
|
|
189
|
+
if service_ports is not None:
|
|
190
|
+
for entry_data in data['service_ports']:
|
|
191
|
+
entry = ServiceEntry.create_from_json(entry_data)
|
|
192
|
+
self.entries.append(entry)
|
|
193
|
+
|
|
194
|
+
if data['deleted_at'] is not None:
|
|
195
|
+
self.deleted = True
|
|
196
|
+
|
|
197
|
+
def get_api_reference_json(self) -> ServiceHrefRef:
|
|
198
|
+
return {'service': {'href': self.href}}
|
|
199
|
+
|
|
200
|
+
def get_entries_str_list(self, protocol_first=True) -> List[str]:
|
|
201
|
+
result: List[str] = []
|
|
202
|
+
for entry in self.entries:
|
|
203
|
+
result.append(entry.to_string_standard(protocol_first=protocol_first))
|
|
204
|
+
return result
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class ServiceStore(pylo.Referencer):
|
|
208
|
+
itemsByName: Dict[str, Service]
|
|
209
|
+
itemsByHRef: Dict[str, Service]
|
|
210
|
+
|
|
211
|
+
def __init__(self, owner):
|
|
212
|
+
""":type owner: pylo.Organization"""
|
|
213
|
+
pylo.Referencer.__init__(self)
|
|
214
|
+
self.owner = owner
|
|
215
|
+
self.itemsByHRef = {}
|
|
216
|
+
self.itemsByName = {}
|
|
217
|
+
|
|
218
|
+
self.special_allservices = pylo.Service('All Services', '/api/v1/orgs/1/sec_policy/draft/services/1', self)
|
|
219
|
+
|
|
220
|
+
def load_services_from_json(self, json_list):
|
|
221
|
+
for json_item in json_list:
|
|
222
|
+
if 'name' not in json_item or 'href' not in json_item:
|
|
223
|
+
raise Exception("Cannot find 'value'/name or href for service in JSON:\n" + nice_json(json_item))
|
|
224
|
+
new_item_name = json_item['name']
|
|
225
|
+
new_item_href = json_item['href']
|
|
226
|
+
|
|
227
|
+
new_item = pylo.Service(new_item_name, new_item_href, self)
|
|
228
|
+
new_item.load_from_json(json_item)
|
|
229
|
+
|
|
230
|
+
if new_item_href in self.itemsByHRef:
|
|
231
|
+
raise Exception("A service with href '%s' already exists in the table", new_item_href)
|
|
232
|
+
|
|
233
|
+
self.itemsByHRef[new_item_href] = new_item
|
|
234
|
+
self.itemsByName[new_item_name] = new_item
|
|
235
|
+
|
|
236
|
+
log.debug("Found service '%s' with href '%s'", new_item_name, new_item_href)
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def services(self) -> List[Service]:
|
|
240
|
+
return list(self.itemsByHRef.values())
|
|
241
|
+
|
|
242
|
+
def services_dict_by_href(self) -> Dict[str, Service]:
|
|
243
|
+
return self.itemsByHRef.copy()
|
|
244
|
+
|
|
245
|
+
def find_by_name(self, name: str, case_sensitive=True) -> Optional[Service]:
|
|
246
|
+
if not case_sensitive:
|
|
247
|
+
name = name.lower()
|
|
248
|
+
for item in self.itemsByName:
|
|
249
|
+
if item.lower() == name:
|
|
250
|
+
return self.itemsByName[item]
|
|
251
|
+
return None
|
|
252
|
+
else:
|
|
253
|
+
return self.itemsByName.get(name)
|
|
254
|
+
|
|
255
|
+
def find_by_href(self, href: str) -> Optional[Service]:
|
|
256
|
+
return self.itemsByHRef.get(href)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
from .Helpers import *
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
version_regex = re.compile(r"^(?P<major>[0-9]+)\.(?P<middle>[0-9]+)\.(?P<minor>[0-9]+)(-(?P<build>[0-9]+))?(.*)?$")
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SoftwareVersion:
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
:type version_string: str
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def __init__(self, version_string: str):
|
|
14
|
+
self.version_string = version_string
|
|
15
|
+
|
|
16
|
+
self.is_unknown = False
|
|
17
|
+
self.major = 0
|
|
18
|
+
self.middle = 0
|
|
19
|
+
self.minor = 0
|
|
20
|
+
self.build = 0
|
|
21
|
+
|
|
22
|
+
if version_string.lower() == 'unknown':
|
|
23
|
+
self.is_unknown = True
|
|
24
|
+
return
|
|
25
|
+
|
|
26
|
+
match = version_regex.match(version_string)
|
|
27
|
+
|
|
28
|
+
if match is None:
|
|
29
|
+
raise pylo.PyloEx("version_string has invalid version format: {}".format(version_string))
|
|
30
|
+
|
|
31
|
+
self.major = int(match.group("major"))
|
|
32
|
+
self.middle = int(match.group("middle"))
|
|
33
|
+
self.minor = int(match.group("minor"))
|
|
34
|
+
build = match.group("build")
|
|
35
|
+
if build is None:
|
|
36
|
+
self.build = 0
|
|
37
|
+
else:
|
|
38
|
+
self.build = int(match.group("build"))
|
|
39
|
+
|
|
40
|
+
def is_greater_than(self, target_version: 'pylo.SoftwareVersion'):
|
|
41
|
+
if self.major > target_version.major:
|
|
42
|
+
return True
|
|
43
|
+
if target_version.major == self.major:
|
|
44
|
+
if self.middle > target_version.middle:
|
|
45
|
+
return True
|
|
46
|
+
if target_version.middle == self.middle:
|
|
47
|
+
if self.minor > target_version.minor:
|
|
48
|
+
return True
|
|
49
|
+
if target_version.minor == self.minor:
|
|
50
|
+
if self.build > target_version.build:
|
|
51
|
+
return True
|
|
52
|
+
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
def is_greater_or_equal_than(self, target_version: 'pylo.SoftwareVersion'):
|
|
56
|
+
if self.major > target_version.major:
|
|
57
|
+
return True
|
|
58
|
+
if target_version.major == self.major:
|
|
59
|
+
if self.middle > target_version.middle:
|
|
60
|
+
return True
|
|
61
|
+
if target_version.middle == self.middle:
|
|
62
|
+
if self.minor > target_version.minor:
|
|
63
|
+
return True
|
|
64
|
+
if target_version.minor == self.minor:
|
|
65
|
+
if self.build >= target_version.build:
|
|
66
|
+
return True
|
|
67
|
+
|
|
68
|
+
return False
|
|
69
|
+
|
|
70
|
+
def is_lower_than(self, target_version: 'pylo.SoftwareVersion'):
|
|
71
|
+
if self.major < target_version.major:
|
|
72
|
+
return True
|
|
73
|
+
if target_version.major == self.major:
|
|
74
|
+
if self.middle < target_version.middle:
|
|
75
|
+
return True
|
|
76
|
+
if target_version.middle == self.middle:
|
|
77
|
+
if self.minor < target_version.minor:
|
|
78
|
+
return True
|
|
79
|
+
if target_version.minor == self.minor:
|
|
80
|
+
if self.build < target_version.build:
|
|
81
|
+
return True
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
def is_lower_or_equal_than(self, target_version: 'pylo.SoftwareVersion'):
|
|
85
|
+
if self.major < target_version.major:
|
|
86
|
+
return True
|
|
87
|
+
if target_version.major == self.major:
|
|
88
|
+
if self.middle < target_version.middle:
|
|
89
|
+
return True
|
|
90
|
+
if target_version.middle == self.middle:
|
|
91
|
+
if self.minor < target_version.minor:
|
|
92
|
+
return True
|
|
93
|
+
if target_version.minor == self.minor:
|
|
94
|
+
if self.build <= target_version.build:
|
|
95
|
+
return True
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
def equals(self, target_version: 'pylo.SoftwareVersion'):
|
|
99
|
+
if target_version.major == self.major and target_version.middle == self.middle and \
|
|
100
|
+
target_version.minor == self.minor and target_version.build == self.build:
|
|
101
|
+
return True
|
|
102
|
+
return False
|
|
103
|
+
|
|
104
|
+
def __lt__(self, other):
|
|
105
|
+
return self.is_lower_than(other)
|
|
106
|
+
|
|
107
|
+
def __le__(self, other):
|
|
108
|
+
return self.is_lower_or_equal_than(other)
|
|
109
|
+
|
|
110
|
+
def __gt__(self, other):
|
|
111
|
+
return self.is_greater_than(other)
|
|
112
|
+
|
|
113
|
+
def __ge__(self, other):
|
|
114
|
+
return self.is_greater_or_equal_than(other)
|
|
115
|
+
|
|
116
|
+
def __eq__(self, target_version):
|
|
117
|
+
if target_version.major == self.major and target_version.middle == self.middle and \
|
|
118
|
+
target_version.minor == self.minor and target_version.build == self.build:
|
|
119
|
+
return True
|
|
120
|
+
return False
|
|
121
|
+
|
|
122
|
+
def generate_str_from_numbers(self):
|
|
123
|
+
return "{}.{}.{}-{}".format(self.major, self.middle, self.minor, self.build)
|
|
124
|
+
|
|
125
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from .API.JsonPayloadTypes import VirtualServiceObjectJsonStructure
|
|
3
|
+
import illumio_pylo as pylo
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class VirtualService(pylo.ReferenceTracker):
|
|
7
|
+
def __init__(self, name: str, href: str, owner: 'pylo.VirtualServiceStore'):
|
|
8
|
+
pylo.ReferenceTracker.__init__(self)
|
|
9
|
+
self.owner = owner
|
|
10
|
+
self.name: str = name
|
|
11
|
+
self.href: str = href
|
|
12
|
+
|
|
13
|
+
self.raw_json: Optional[VirtualServiceObjectJsonStructure] = None
|
|
14
|
+
|
|
15
|
+
def load_from_json(self, data: VirtualServiceObjectJsonStructure):
|
|
16
|
+
self.raw_json = data
|
|
17
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from typing import Dict, List, Optional
|
|
2
|
+
import illumio_pylo as pylo
|
|
3
|
+
from illumio_pylo import log
|
|
4
|
+
from .API.JsonPayloadTypes import VirtualServiceObjectJsonStructure
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class VirtualServiceStore:
|
|
8
|
+
|
|
9
|
+
def __init__(self, owner: 'pylo.Organization'):
|
|
10
|
+
self.owner: 'pylo.Organization' = owner
|
|
11
|
+
self.items_by_href: Dict[str, 'pylo.VirtualService'] = {}
|
|
12
|
+
self.itemsByName: Dict[str, 'pylo.VirtualService'] = {}
|
|
13
|
+
|
|
14
|
+
def load_virtualservices_from_json(self, json_list: List[VirtualServiceObjectJsonStructure]):
|
|
15
|
+
for json_item in json_list:
|
|
16
|
+
if 'name' not in json_item or 'href' not in json_item:
|
|
17
|
+
raise pylo.PyloEx(
|
|
18
|
+
"Cannot find 'value'/name or href for VirtualService in JSON:\n" + pylo.nice_json(json_item))
|
|
19
|
+
|
|
20
|
+
new_item_name = json_item['name']
|
|
21
|
+
new_item_href = json_item['href']
|
|
22
|
+
|
|
23
|
+
new_item = pylo.VirtualService(new_item_name, new_item_href, self)
|
|
24
|
+
new_item.load_from_json(json_item)
|
|
25
|
+
|
|
26
|
+
if new_item_href in self.items_by_href:
|
|
27
|
+
raise pylo.PyloEx("A VirtualService with href '%s' already exists in the table", new_item_href)
|
|
28
|
+
|
|
29
|
+
if new_item_name in self.itemsByName:
|
|
30
|
+
raise pylo.PyloEx(
|
|
31
|
+
"A VirtualService with name '%s' already exists in the table. This UID:%s vs other UID:%s" % (
|
|
32
|
+
new_item_name, new_item_href, self.itemsByName[new_item_name].href)
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
self.items_by_href[new_item_href] = new_item
|
|
36
|
+
self.itemsByName[new_item_name] = new_item
|
|
37
|
+
|
|
38
|
+
log.debug("Found VirtualService '%s' with href '%s'", new_item_name, new_item_href)
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def virtual_services(self) -> List['pylo.VirtualService']:
|
|
42
|
+
return list(self.items_by_href.values())
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def virtual_services_by_href(self) -> Dict[str, 'pylo.VirtualService']:
|
|
46
|
+
return self.items_by_href.copy()
|
|
47
|
+
|
|
48
|
+
def find_by_href(self, href: str) -> Optional['pylo.VirtualService']:
|
|
49
|
+
return self.items_by_href.get(href)
|
|
50
|
+
|
|
51
|
+
def find_by_name(self, name: str, case_sensitive: bool = True) -> Optional['pylo.VirtualService']:
|
|
52
|
+
if case_sensitive:
|
|
53
|
+
return self.itemsByName.get(name)
|
|
54
|
+
else:
|
|
55
|
+
for item in self.itemsByName.values():
|
|
56
|
+
if item.name.lower() == name.lower():
|
|
57
|
+
return item
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
def find_by_href_or_create_tmp(self, href: str, tmp_name: str) -> 'pylo.VirtualService':
|
|
61
|
+
"""
|
|
62
|
+
Mostly used for deleted objects/developers speficic use cases when load imcomplete or partial PCE objects
|
|
63
|
+
"""
|
|
64
|
+
find_object = self.find_by_href(href)
|
|
65
|
+
if find_object is not None:
|
|
66
|
+
return find_object
|
|
67
|
+
|
|
68
|
+
new_tmp_item = pylo.VirtualService(tmp_name, href, self)
|
|
69
|
+
new_tmp_item.deleted = True
|
|
70
|
+
new_tmp_item.temporary = True
|
|
71
|
+
|
|
72
|
+
self.items_by_href[href] = new_tmp_item
|
|
73
|
+
self.itemsByName[tmp_name] = new_tmp_item
|
|
74
|
+
|
|
75
|
+
return new_tmp_item
|