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.
Files changed (73) hide show
  1. illumio_pylo/API/APIConnector.py +1308 -0
  2. illumio_pylo/API/AuditLog.py +42 -0
  3. illumio_pylo/API/ClusterHealth.py +136 -0
  4. illumio_pylo/API/CredentialsManager.py +286 -0
  5. illumio_pylo/API/Explorer.py +1077 -0
  6. illumio_pylo/API/JsonPayloadTypes.py +240 -0
  7. illumio_pylo/API/RuleSearchQuery.py +128 -0
  8. illumio_pylo/API/__init__.py +0 -0
  9. illumio_pylo/AgentStore.py +139 -0
  10. illumio_pylo/Exception.py +44 -0
  11. illumio_pylo/Helpers/__init__.py +3 -0
  12. illumio_pylo/Helpers/exports.py +508 -0
  13. illumio_pylo/Helpers/functions.py +166 -0
  14. illumio_pylo/IPList.py +135 -0
  15. illumio_pylo/IPMap.py +285 -0
  16. illumio_pylo/Label.py +25 -0
  17. illumio_pylo/LabelCommon.py +48 -0
  18. illumio_pylo/LabelGroup.py +68 -0
  19. illumio_pylo/LabelStore.py +403 -0
  20. illumio_pylo/LabeledObject.py +25 -0
  21. illumio_pylo/Organization.py +258 -0
  22. illumio_pylo/Query.py +331 -0
  23. illumio_pylo/ReferenceTracker.py +41 -0
  24. illumio_pylo/Rule.py +671 -0
  25. illumio_pylo/Ruleset.py +306 -0
  26. illumio_pylo/RulesetStore.py +101 -0
  27. illumio_pylo/SecurityPrincipal.py +62 -0
  28. illumio_pylo/Service.py +256 -0
  29. illumio_pylo/SoftwareVersion.py +125 -0
  30. illumio_pylo/VirtualService.py +17 -0
  31. illumio_pylo/VirtualServiceStore.py +75 -0
  32. illumio_pylo/Workload.py +506 -0
  33. illumio_pylo/WorkloadStore.py +289 -0
  34. illumio_pylo/__init__.py +82 -0
  35. illumio_pylo/cli/NativeParsers.py +96 -0
  36. illumio_pylo/cli/__init__.py +134 -0
  37. illumio_pylo/cli/__main__.py +10 -0
  38. illumio_pylo/cli/commands/__init__.py +32 -0
  39. illumio_pylo/cli/commands/credential_manager.py +168 -0
  40. illumio_pylo/cli/commands/iplist_import_from_file.py +185 -0
  41. illumio_pylo/cli/commands/misc.py +7 -0
  42. illumio_pylo/cli/commands/ruleset_export.py +129 -0
  43. illumio_pylo/cli/commands/update_pce_objects_cache.py +44 -0
  44. illumio_pylo/cli/commands/ven_duplicate_remover.py +366 -0
  45. illumio_pylo/cli/commands/ven_idle_to_visibility.py +287 -0
  46. illumio_pylo/cli/commands/ven_upgrader.py +226 -0
  47. illumio_pylo/cli/commands/workload_export.py +251 -0
  48. illumio_pylo/cli/commands/workload_import.py +423 -0
  49. illumio_pylo/cli/commands/workload_relabeler.py +510 -0
  50. illumio_pylo/cli/commands/workload_reset_names_to_null.py +83 -0
  51. illumio_pylo/cli/commands/workload_used_in_rule_finder.py +80 -0
  52. illumio_pylo/docs/Doxygen +1757 -0
  53. illumio_pylo/tmp.py +104 -0
  54. illumio_pylo/utilities/__init__.py +0 -0
  55. illumio_pylo/utilities/cli.py +10 -0
  56. illumio_pylo/utilities/credentials.example.json +20 -0
  57. illumio_pylo/utilities/explorer_report_exporter.py +86 -0
  58. illumio_pylo/utilities/health_monitoring.py +102 -0
  59. illumio_pylo/utilities/iplist_analyzer.py +148 -0
  60. illumio_pylo/utilities/iplists_stats_duplicates_unused_finder.py +75 -0
  61. illumio_pylo/utilities/resources/iplists-import-example.csv +3 -0
  62. illumio_pylo/utilities/resources/iplists-import-example.xlsx +0 -0
  63. illumio_pylo/utilities/resources/workload-exporter-filter-example.csv +3 -0
  64. illumio_pylo/utilities/resources/workloads-import-example.csv +2 -0
  65. illumio_pylo/utilities/resources/workloads-import-example.xlsx +0 -0
  66. illumio_pylo/utilities/ven_compatibility_report_export.py +240 -0
  67. illumio_pylo/utilities/ven_idle_to_illumination.py +344 -0
  68. illumio_pylo/utilities/ven_reassign_pce.py +183 -0
  69. illumio_pylo-0.2.5.dist-info/LICENSE +176 -0
  70. illumio_pylo-0.2.5.dist-info/METADATA +197 -0
  71. illumio_pylo-0.2.5.dist-info/RECORD +73 -0
  72. illumio_pylo-0.2.5.dist-info/WHEEL +5 -0
  73. illumio_pylo-0.2.5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,403 @@
1
+ from hashlib import md5
2
+ import random
3
+ from typing import Union, Set, Iterable
4
+ # Pylo imports
5
+ from illumio_pylo import log
6
+ from .API.JsonPayloadTypes import LabelObjectJsonStructure, LabelGroupObjectJsonStructure, LabelDimensionObjectStructure
7
+ from .Helpers import *
8
+
9
+ label_type_loc = 'loc'
10
+ label_type_env = 'env'
11
+ label_type_app = 'app'
12
+ label_type_role = 'role'
13
+
14
+
15
+ class LabelStore:
16
+
17
+ class Utils:
18
+ """
19
+ Container meant to provide reusable utility functions for Label objects and their Store
20
+ """
21
+
22
+ @staticmethod
23
+ def list_to_dict_by_href(label_list: List[Union['pylo.Label', 'pylo.LabelGroup']]) -> Dict[str, Union['pylo.Label', 'pylo.LabelGroup']]:
24
+ """Converts a list of labels into a dict, where the href is the key"""
25
+ result: Dict[str, Union['pylo.Label', 'pylo.LabelGroup']] = {}
26
+ for label in label_list:
27
+ result[label.href] = label
28
+ return result
29
+
30
+ @staticmethod
31
+ def list_to_dict_by_type(label_list: Iterable[Union['pylo.Label', 'pylo.LabelGroup']]) -> Dict[str, List[Union['pylo.Label', 'pylo.LabelGroup']]]:
32
+ """Converts a list of labels into a dict, where the type is the key"""
33
+ result: Dict[str, List[Union['pylo.Label', 'pylo.LabelGroup']]] = {}
34
+ for label in label_list:
35
+ if label.type not in result:
36
+ result[label.type] = []
37
+ result[label.type].append(label)
38
+ return result
39
+
40
+ @staticmethod
41
+ def list_sort_by_type(label_list: Iterable[Union['pylo.Label', 'pylo.LabelGroup']], type_order: List[str]) -> List[Union['pylo.Label', 'pylo.LabelGroup']]:
42
+ """Sorts a list of labels by type, using the provided type order"""
43
+ result: List[Union['pylo.Label', 'pylo.LabelGroup']] = []
44
+ for label_type in type_order:
45
+ for label in label_list:
46
+ if label.type == label_type:
47
+ result.append(label)
48
+ return result
49
+
50
+ def __init__(self, owner: 'pylo.Organization'):
51
+ self.owner: "pylo.Organization" = owner
52
+ self._items_by_href: Dict[str, Union[pylo.Label, pylo.LabelGroup]] = {}
53
+ self.label_types: List[str] = []
54
+ self.label_types_as_set: Set[str] = set()
55
+
56
+ self.label_resolution_cache: Optional[Dict[str, Union[pylo.Label, pylo.LabelGroup]]] = None
57
+
58
+ def _add_dimension(self, dimension: str):
59
+ if dimension not in self.label_types_as_set:
60
+ self.label_types_as_set.add(dimension)
61
+ self.label_types.append(dimension)
62
+
63
+ def load_label_dimensions(self, json_list: Optional[List[LabelDimensionObjectStructure]]):
64
+ if json_list is None or len(json_list) == 0:
65
+ # add the default built-in label types
66
+ self._add_dimension(label_type_role)
67
+ self._add_dimension(label_type_app)
68
+ self._add_dimension(label_type_env)
69
+ self._add_dimension(label_type_loc)
70
+ return
71
+
72
+ for dimension in json_list:
73
+ self._add_dimension(dimension['key'])
74
+
75
+ def load_labels_from_json(self, json_list: List[LabelObjectJsonStructure]):
76
+ for json_label in json_list:
77
+ if 'value' not in json_label or 'href' not in json_label or 'key' not in json_label:
78
+ raise Exception("Cannot find 'value'/name or href for Label in JSON:\n" + nice_json(json_label))
79
+ new_label_name = json_label['value']
80
+ new_label_href = json_label['href']
81
+ new_label_type = json_label['key']
82
+
83
+ if new_label_type not in self.label_types_as_set:
84
+ raise pylo.PyloApiEx("Label type '%s' is not a valid type for Label '%s' (href: %s)" % (new_label_type, new_label_name, new_label_href))
85
+
86
+ new_label = pylo.Label(new_label_name, new_label_href, new_label_type, self)
87
+
88
+ if new_label_href in self._items_by_href:
89
+ raise Exception("A Label with href '%s' already exists in the table", new_label_href)
90
+
91
+ self._items_by_href[new_label_href] = new_label
92
+
93
+ log.debug("Found Label '%s' with href '%s' and type '%s'", new_label_name, new_label_href, new_label_type)
94
+
95
+ def load_label_groups_from_json(self, json_list: List[LabelGroupObjectJsonStructure]):
96
+ # groups cannot be loaded straight away : we need to extract of their principal properties (name, href and type)
97
+ #then we can extract their members in case there are nested groups
98
+ created_groups = []
99
+ for json_label in json_list:
100
+ if 'name' not in json_label or 'href' not in json_label or 'key' not in json_label:
101
+ raise Exception("Cannot find 'value'/name or href for Label in JSON:\n" + nice_json(json_label))
102
+ new_label_name = json_label['name']
103
+ new_label_href = json_label['href']
104
+ new_label_type = json_label['key']
105
+
106
+ new_label = pylo.LabelGroup(new_label_name, new_label_href, new_label_type, self)
107
+ created_groups.append(new_label)
108
+
109
+ if new_label_href in self._items_by_href:
110
+ raise Exception("A Label with href '%s' already exists in the table", new_label_href)
111
+
112
+ self._items_by_href[new_label_href] = new_label
113
+
114
+ new_label.raw_json = json_label
115
+
116
+ log.info("Found LabelGroup '%s' with href '%s' and type '%s'", new_label_name, new_label_href, new_label_type)
117
+
118
+ for group in created_groups:
119
+ group.load_from_json()
120
+
121
+ def count_labels(self, label_type: Optional[str] = None) -> int:
122
+ return len(self.get_labels(label_type=label_type))
123
+
124
+ def count_location_labels(self) -> int:
125
+ return len(self.get_labels(label_type=label_type_loc))
126
+
127
+ def count_environment_labels(self) -> int:
128
+ return len(self.get_labels(label_type=label_type_env))
129
+
130
+ def count_application_labels(self) -> int:
131
+ return len(self.get_labels(label_type=label_type_app))
132
+
133
+ def count_role_labels(self) -> int:
134
+ return len(self.get_labels(label_type=label_type_role))
135
+
136
+ def count_label_groups(self, label_type: Optional[str] = None) -> int:
137
+ return len(self.get_label_groups(label_type))
138
+
139
+ def count_location_label_groups(self) -> int:
140
+ return len(self.get_label_groups(label_type=label_type_loc))
141
+
142
+ def count_environment_label_groups(self) -> int:
143
+ return len(self.get_label_groups(label_type=label_type_env))
144
+
145
+ def count_application_label_groups(self) -> int:
146
+ return len(self.get_label_groups(label_type=label_type_app))
147
+
148
+ def count_role_label_groups(self) -> int:
149
+ return len(self.get_label_groups(label_type=label_type_role))
150
+
151
+ def get_labels(self, label_type: Optional[str] = None) -> List['pylo.Label']:
152
+ if label_type is not None: # label_type must be a valid type
153
+ if label_type not in self.label_types_as_set:
154
+ raise pylo.PyloEx("Invalid label type '%s'. Valid types are: %s" % (label_type, self.label_types_as_set))
155
+ data = []
156
+ for label in self._items_by_href.values():
157
+ if label.is_label() and (label_type is None or label.type == label_type):
158
+ data.append(label)
159
+ return data
160
+
161
+ def get_labels_as_dict_by_href(self, label_type: Optional[str] = None) -> Dict[str, 'pylo.Label']:
162
+ label_list = self.get_labels(label_type)
163
+ return self.Utils.list_to_dict_by_href(label_list)
164
+
165
+ def get_label_groups(self, label_type: Optional[str] = None) -> List['pylo.LabelGroup']:
166
+ if label_type is not None: # label_type must be a valid type
167
+ if label_type not in self.label_types_as_set:
168
+ raise pylo.PyloEx("Invalid label type '%s'. Valid types are: %s" % (label_type, self.label_types_as_set))
169
+ data = []
170
+ for label in self._items_by_href.values():
171
+ if label.is_group() and (label_type is None or label.type == label_type):
172
+ data.append(label)
173
+ return data
174
+
175
+
176
+ def get_label_groups_as_dict_by_href(self, label_type: Optional[str] = None) -> Dict[str, 'pylo.LabelGroup']:
177
+ label_list = self.get_label_groups(label_type)
178
+ return self.Utils.list_to_dict_by_href(label_list)
179
+
180
+
181
+ def get_both_labels_and_groups(self, label_type: Optional[str] = None) -> List[Union['pylo.Label','pylo.LabelGroup']]:
182
+ data = []
183
+ if label_type is not None:
184
+ if label_type not in self.label_types_as_set:
185
+ raise pylo.PyloEx("Invalid label type '%s'. Valid types are: %s" % (label_type, self.label_types_as_set))
186
+
187
+ for label in self._items_by_href.values():
188
+ if label_type is None or label.type == label_type:
189
+ data.append(label)
190
+ return data
191
+
192
+ def get_both_labels_and_groups_as_dict_by_href(self, label_type: Optional[str] = None) -> Dict[str, Union['pylo.Label','pylo.LabelGroup']]:
193
+ label_list = self.get_both_labels_and_groups(label_type)
194
+ return self.Utils.list_to_dict_by_href(label_list)
195
+
196
+
197
+ def find_object_by_name(self, name: str|List[str], label_type: Optional[str] = None, case_sensitive: bool = True,
198
+ missing_labels_names: Optional[List[str]] = None,
199
+ allow_label_group: bool = True,
200
+ allow_label: bool = True,
201
+ raise_exception_if_not_found: bool = False) -> Optional[Union['pylo.Label','pylo.LabelGroup',List[Union['pylo.Label','pylo.LabelGroup']]]]:
202
+ """Find a label by its name. If case_sensitive is False, the search is case-insensitive.
203
+ If case_sensitive is False it will return a list of labels with the same name rather than a single object.
204
+ If missing_labels_names is not None, it will be filled with the names of the labels not found.
205
+ If raise_exception_if_not_found is True, an exception will be raised if a label is not found.
206
+ If name is a list, a list of labels will be returned, in the same order as the list of names.
207
+ If a label is not found, None will be returned in the list.
208
+ """
209
+ if not isinstance(name, list):
210
+ if case_sensitive is False:
211
+ return self.find_object_by_name([name], label_type=label_type, case_sensitive=case_sensitive,
212
+ missing_labels_names=missing_labels_names,
213
+ allow_label_group=allow_label_group,
214
+ allow_label=allow_label,
215
+ raise_exception_if_not_found=raise_exception_if_not_found)
216
+ for label in self._items_by_href.values():
217
+ if label_type is not None and label.type != label_type:
218
+ continue
219
+ if label.is_label() and allow_label: # ignore groups
220
+ if case_sensitive:
221
+ if label.name == name:
222
+ return label
223
+ elif allow_label_group:
224
+ if label.name.lower() == name.lower():
225
+ return label
226
+ if raise_exception_if_not_found:
227
+ raise pylo.PyloEx("Label/group '%s' not found", name)
228
+ if missing_labels_names is not None:
229
+ missing_labels_names.append(name)
230
+ return None
231
+ else:
232
+ results = []
233
+ local_notfound_labels = []
234
+ for name_to_find in name:
235
+ result = self.find_object_by_name(name_to_find, label_type=label_type ,case_sensitive=case_sensitive,
236
+ allow_label_group=allow_label_group, allow_label=allow_label)
237
+ if result is None:
238
+ local_notfound_labels.append(name_to_find)
239
+ else:
240
+ results.append(result)
241
+ if raise_exception_if_not_found and len(local_notfound_labels) > 0:
242
+ raise pylo.PyloEx("Some labels not found: {}".format(local_notfound_labels))
243
+ if missing_labels_names is not None:
244
+ missing_labels_names.extend(local_notfound_labels)
245
+ return results
246
+
247
+ def find_label_by_name(self, name: str|List[str], label_type: Optional[str] = None, case_sensitive: bool = True,
248
+ missing_labels_names: Optional[List[str]] = None,
249
+ raise_exception_if_not_found: bool = False) -> Optional['pylo.Label'|List['pylo.Label']]:
250
+ """Find a label by its name.
251
+ If case_sensitive is False it will return a list of labels with the same name rather than a single object.
252
+ If missing_labels_names is not None, it will be filled with the names of the labels not found.
253
+ If raise_exception_if_not_found is True, an exception will be raised if a label is not found.
254
+ If name is a list, a list of labels will be returned, in the same order as the list of names.
255
+ If a label is not found, None will be returned in the list.
256
+ """
257
+ return self.find_object_by_name(name, label_type=label_type, case_sensitive=case_sensitive,
258
+ missing_labels_names=missing_labels_names,
259
+ allow_label_group=False, allow_label=True,
260
+ raise_exception_if_not_found=raise_exception_if_not_found)
261
+
262
+
263
+ def find_label_by_name_whatever_type(self, name: str, case_sensitive: bool = True) -> Optional[Union['pylo.Label', 'pylo.LabelGroup']]:
264
+ pylo.log.warn("find_label_by_name_whatever_type is deprecated, use find_label_by_name instead")
265
+ return self.find_label_by_name(name, case_sensitive=case_sensitive)
266
+
267
+
268
+ def find_label_by_name_and_type(self, name: str, label_type: str, case_sensitive: bool = True) \
269
+ -> Optional[Union['pylo.Label', 'pylo.LabelGroup']]:
270
+ pylo.log.warn("find_label_by_name_and_type is deprecated, use find_label_by_name instead")
271
+ return self.find_label_by_name(name, label_type=label_type, case_sensitive=case_sensitive)
272
+
273
+ cache_label_all_string = '-All-'
274
+ cache_label_all_separator = '|'
275
+
276
+ def generate_label_resolution_cache(self):
277
+ """
278
+ Mostly for internal use. This method will generate a cache of all possible combinations of labels.
279
+ """
280
+ self.label_resolution_cache = {}
281
+
282
+ roles = list(self.get_labels_as_dict_by_href('role').keys())
283
+ roles.append(self.cache_label_all_string)
284
+ for role in roles:
285
+ apps = list(self.get_labels_as_dict_by_href('app').keys())
286
+ apps.append(self.cache_label_all_string)
287
+ for app in apps:
288
+ envs = list(self.get_labels_as_dict_by_href('env').keys())
289
+ envs.append(self.cache_label_all_string)
290
+ for env in envs:
291
+ locs = list(self.get_labels_as_dict_by_href('loc').keys())
292
+ locs.append(self.cache_label_all_string)
293
+ for loc in locs:
294
+ group_name = role + LabelStore.cache_label_all_separator + app + LabelStore.cache_label_all_separator + env + LabelStore.cache_label_all_separator + loc
295
+ self.label_resolution_cache[group_name] = []
296
+
297
+ all_string_and_sep = LabelStore.cache_label_all_string + LabelStore.cache_label_all_separator
298
+
299
+ masks = []
300
+ for i in range(2**4):
301
+ binary = bin(i)[2:].zfill(4)
302
+ mask = [bool(bit) for bit in binary]
303
+ masks.append(mask)
304
+
305
+ for workload in self.owner.WorkloadStore.itemsByHRef.values():
306
+ if workload.deleted:
307
+ continue
308
+
309
+ already_processed = {}
310
+
311
+ for mask in masks:
312
+ if workload.role_label is not None and mask[0]:
313
+ group_name = workload.role_label.name + LabelStore.cache_label_all_separator
314
+ else:
315
+ group_name = all_string_and_sep
316
+ if workload.app_label is not None and mask[1]:
317
+ group_name += workload.app_label.name + LabelStore.cache_label_all_separator
318
+ else:
319
+ group_name += all_string_and_sep
320
+ if workload.env_label is not None and mask[2]:
321
+ group_name += workload.env_label.name + LabelStore.cache_label_all_separator
322
+ else:
323
+ group_name += all_string_and_sep
324
+ if workload.loc_label is not None and mask[3]:
325
+ group_name += workload.loc_label.name
326
+ else:
327
+ group_name += LabelStore.cache_label_all_string
328
+
329
+ if group_name not in already_processed:
330
+ self.label_resolution_cache[group_name].append(workload)
331
+ already_processed[group_name] = True
332
+
333
+ def get_workloads_by_label_scope(self, role: 'pylo.Label', app: 'pylo.Label', env: 'pylo.Label', loc: 'pylo.Label'):
334
+ if self.label_resolution_cache is None:
335
+ self.generate_label_resolution_cache()
336
+
337
+ if role is None:
338
+ role = LabelStore.cache_label_all_string
339
+ else:
340
+ role = role.name
341
+
342
+ if app is None:
343
+ app = LabelStore.cache_label_all_string
344
+ else:
345
+ app = app.name
346
+
347
+ if env is None:
348
+ env = LabelStore.cache_label_all_string
349
+ else:
350
+ env = env.name
351
+
352
+ if loc is None:
353
+ loc = LabelStore.cache_label_all_string
354
+ else:
355
+ loc = loc.name
356
+
357
+ group_name = role + LabelStore.cache_label_all_separator + app + LabelStore.cache_label_all_separator + env + LabelStore.cache_label_all_separator + loc
358
+
359
+ return self.label_resolution_cache[group_name]
360
+
361
+ def create_label(self, name: str, label_type: str) -> 'pylo.Label':
362
+ """Create a label *locally* (not on the server). Mostly for internal use.
363
+ """
364
+
365
+ new_label_name = name
366
+ new_label_type = label_type
367
+ new_label_href = '**fake-label-href**/{}'.format( md5(str(random.random()).encode('utf8')).digest() )
368
+
369
+ new_label = pylo.Label(new_label_name, new_label_href, new_label_type, self)
370
+
371
+ if new_label_href in self._items_by_href:
372
+ raise Exception("A Label with href '%s' already exists in the table", new_label_href)
373
+
374
+ self._items_by_href[new_label_href] = new_label
375
+
376
+ return new_label
377
+
378
+ def api_create_label(self, name: str, label_type: str) -> 'pylo.Label':
379
+
380
+ connector = pylo.find_connector_or_die(self.owner)
381
+ json_label = connector.objects_label_create(name, label_type)
382
+
383
+ if 'value' not in json_label or 'href' not in json_label or 'key' not in json_label:
384
+ raise pylo.PyloEx("Cannot find 'value'/name or href for Label in JSON:\n" + nice_json(json_label))
385
+ new_label_name = json_label['value']
386
+ new_label_href = json_label['href']
387
+ new_label_type = json_label['key']
388
+
389
+ new_label = pylo.Label(new_label_name, new_label_href, new_label_type, self)
390
+
391
+ if new_label_href in self._items_by_href:
392
+ raise Exception("A Label with href '%s' already exists in the table", new_label_href)
393
+
394
+ self._items_by_href[new_label_href] = new_label
395
+
396
+ return new_label
397
+
398
+ def find_label_by_name_lowercase_and_type(self, name: str, label_type: str) -> Optional[Union['pylo.Label', 'pylo.LabelGroup']]:
399
+ pylo.log.warn("find_label_by_name_lowercase_and_type is deprecated, use find_object_by_name instead")
400
+ return self.find_object_by_name(name, label_type)
401
+
402
+ def find_by_href(self, href: str) -> Optional[Union['pylo.Label', 'pylo.LabelGroup']]:
403
+ return self._items_by_href.get(href)
@@ -0,0 +1,25 @@
1
+ from typing import Dict, Optional
2
+ import illumio_pylo as pylo
3
+
4
+
5
+ class LabeledObject:
6
+
7
+ def __init__(self):
8
+ self._labels: Dict[str, 'pylo.Label'] = {}
9
+
10
+ def get_label(self, key: str) -> Optional['pylo.Label']:
11
+ return self._labels.get(key)
12
+
13
+ def get_labels_dict(self):
14
+ return self._labels.copy()
15
+
16
+ def get_labels(self):
17
+ return self._labels.values()
18
+
19
+ def set_label(self, label :'pylo.Label'):
20
+ self._labels[label.type] = label
21
+
22
+ def get_label_name(self, key: str, not_found_return_value = None):
23
+ label = self.get_label(key)
24
+ return label.name if label else not_found_return_value
25
+