illumio-pylo 0.3.8__tar.gz → 0.3.10__tar.gz
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-0.3.8 → illumio_pylo-0.3.10}/.github/workflows/doxygen-publish.yml +1 -1
- {illumio_pylo-0.3.8/illumio_pylo.egg-info → illumio_pylo-0.3.10}/PKG-INFO +2 -2
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/API/APIConnector.py +90 -54
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/API/JsonPayloadTypes.py +10 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/Helpers/functions.py +8 -13
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/IPList.py +5 -9
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/IPMap.py +3 -3
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/Label.py +0 -1
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/LabelCommon.py +1 -1
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/LabelStore.py +24 -25
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/LabeledObject.py +4 -5
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/Organization.py +1 -3
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/ReferenceTracker.py +0 -3
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/Rule.py +2 -2
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/Ruleset.py +7 -7
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/RulesetStore.py +1 -1
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/SecurityPrincipal.py +0 -5
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/Workload.py +4 -13
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/WorkloadStoreSubClasses.py +7 -10
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/__init__.py +1 -1
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/__init__.py +0 -2
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/credential_manager.py +7 -18
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/iplist_analyzer.py +3 -9
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/iplist_import_from_file.py +1 -2
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/ruleset_export.py +16 -20
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/update_pce_objects_cache.py +0 -1
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/utils/LabelCreation.py +2 -2
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/utils/misc.py +1 -2
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/ven_compatibility_report_export.py +4 -14
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/ven_duplicate_remover.py +26 -32
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/ven_idle_to_visibility.py +2 -4
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/ven_upgrader.py +1 -2
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/workload_import.py +12 -14
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/workload_reset_names_to_null.py +12 -14
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/workload_update.py +25 -30
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/workload_used_in_rule_finder.py +5 -5
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/tmp.py +1 -0
- illumio_pylo-0.3.10/illumio_pylo/utilities/resources/workloads-import-example.csv +2 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/utilities/resources/workloads-import-example.xlsx +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10/illumio_pylo.egg-info}/PKG-INFO +2 -2
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo.egg-info/requires.txt +1 -1
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/requirements.txt +1 -1
- illumio_pylo-0.3.8/illumio_pylo/utilities/resources/workloads-import-example.csv +0 -2
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/.devcontainer/Dockerfile +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/.devcontainer/devcontainer.json +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/.gitattributes +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/.github/workflows/make-binaries.yml +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/.github/workflows/python-publish.yml +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/.gitignore +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/LICENSE +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/README.md +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/check_unique_hostnames.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/check_unique_services.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/delete_all_workloads.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/delete_unused_services.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/explorer_report_exporter.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/export_rules_to_firewall.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/generate-random-workloads.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/healthcheck_log.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/import-labels.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/import_workloads_placeholders.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/iplists_stats_duplicates_unused_finder.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/recalculate_explorer_logs.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/recalculate_explorer_logs_multithreaded.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/rules_exporter.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/rules_exporter_special.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/test.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/test_change_workload_desc.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/test_query.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/test_query2.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/test_securityprincipals.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/ven_idle_to_illumination.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/dev_playground/ven_reassign_pce.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/examples/explorer_query.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/examples/extend_cli.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/API/AuditLog.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/API/ClusterHealth.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/API/CredentialsManager.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/API/Explorer.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/API/RuleSearchQuery.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/API/__init__.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/AgentStore.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/Exception.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/Helpers/__init__.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/Helpers/exports.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/LabelGroup.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/Query.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/Service.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/SoftwareVersion.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/VirtualService.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/VirtualServiceStore.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/WorkloadStore.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/NativeParsers.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/__main__.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/__init__.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/utils/__init__.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/cli/commands/workload_export.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/docs/Doxygen +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/utilities/__init__.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/utilities/cli.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/utilities/credentials.example.json +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/utilities/health_monitoring.py +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/utilities/resources/iplists-import-example.csv +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/utilities/resources/iplists-import-example.xlsx +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo/utilities/resources/workload-exporter-filter-example.csv +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo.egg-info/SOURCES.txt +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo.egg-info/dependency_links.txt +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/illumio_pylo.egg-info/top_level.txt +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/pyproject.toml +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/setup.cfg +0 -0
- {illumio_pylo-0.3.8 → illumio_pylo-0.3.10}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: illumio_pylo
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.10
|
|
4
4
|
Summary: A set of tools and library for working with Illumio PCE
|
|
5
5
|
Home-page: https://github.com/cpainchaud/pylo
|
|
6
6
|
Author: Christophe Painchaud
|
|
@@ -187,7 +187,7 @@ Requires-Python: >=3.11
|
|
|
187
187
|
License-File: LICENSE
|
|
188
188
|
Requires-Dist: click==8.1.7
|
|
189
189
|
Requires-Dist: colorama~=0.4.4
|
|
190
|
-
Requires-Dist: cryptography==
|
|
190
|
+
Requires-Dist: cryptography==43.0.1
|
|
191
191
|
Requires-Dist: openpyxl~=3.1.3
|
|
192
192
|
Requires-Dist: paramiko~=3.4.0
|
|
193
193
|
Requires-Dist: prettytable~=3.10.0
|
|
@@ -12,7 +12,8 @@ from .JsonPayloadTypes import LabelGroupObjectJsonStructure, LabelObjectCreation
|
|
|
12
12
|
LabelDimensionObjectStructure, AuditLogApiReplyEventJsonStructure, WorkloadsGetQueryLabelFilterJsonStructure, \
|
|
13
13
|
NetworkDeviceObjectJsonStructure, NetworkDeviceEndpointObjectJsonStructure, HrefReference, \
|
|
14
14
|
WorkloadObjectCreateJsonStructure, WorkloadObjectMultiCreateJsonRequestPayload, \
|
|
15
|
-
WorkloadBulkUpdateEntryJsonStructure, WorkloadBulkUpdateResponseEntry, VenObjectJsonStructure
|
|
15
|
+
WorkloadBulkUpdateEntryJsonStructure, WorkloadBulkUpdateResponseEntry, VenObjectJsonStructure, \
|
|
16
|
+
VENUnpairApiResponseObjectJsonStructure
|
|
16
17
|
|
|
17
18
|
try:
|
|
18
19
|
import requests as requests
|
|
@@ -44,19 +45,19 @@ def get_field_or_die(field_name: str, data):
|
|
|
44
45
|
|
|
45
46
|
|
|
46
47
|
ObjectTypes = Literal['iplists', 'workloads', 'virtual_services', 'labels', 'labelgroups', 'services', 'rulesets',
|
|
47
|
-
|
|
48
|
+
'security_principals', 'label_dimensions']
|
|
48
49
|
|
|
49
50
|
all_object_types: Dict[ObjectTypes, ObjectTypes] = {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
'iplists': 'iplists',
|
|
52
|
+
'workloads': 'workloads',
|
|
53
|
+
'virtual_services': 'virtual_services',
|
|
54
|
+
'labels': 'labels',
|
|
55
|
+
'labelgroups': 'labelgroups',
|
|
56
|
+
'services': 'services',
|
|
57
|
+
'rulesets': 'rulesets',
|
|
58
|
+
'security_principals': 'security_principals',
|
|
59
|
+
'label_dimensions': 'label_dimensions'
|
|
60
|
+
}
|
|
60
61
|
|
|
61
62
|
|
|
62
63
|
class APIConnector:
|
|
@@ -69,7 +70,7 @@ class APIConnector:
|
|
|
69
70
|
port = str(port)
|
|
70
71
|
self.port: int = port
|
|
71
72
|
self._api_key: str = api_key
|
|
72
|
-
self._decrypted_api_key: str = None
|
|
73
|
+
self._decrypted_api_key: Optional[str] = None
|
|
73
74
|
self.api_user: str = api_user
|
|
74
75
|
self.org_id: int = org_id
|
|
75
76
|
self.skipSSLCertCheck: bool = skip_ssl_cert_check
|
|
@@ -86,7 +87,6 @@ class APIConnector:
|
|
|
86
87
|
return self._decrypted_api_key
|
|
87
88
|
return self._api_key
|
|
88
89
|
|
|
89
|
-
|
|
90
90
|
@staticmethod
|
|
91
91
|
def get_all_object_types_names_except(exception_list: List[ObjectTypes]):
|
|
92
92
|
|
|
@@ -138,7 +138,7 @@ class APIConnector:
|
|
|
138
138
|
connector = pylo.APIConnector(fqdn_or_profile_name, port, user, password, skip_ssl_cert_check=True, name=name)
|
|
139
139
|
return connector
|
|
140
140
|
|
|
141
|
-
def _make_base_url(self, path: str='') -> str:
|
|
141
|
+
def _make_base_url(self, path: str = '') -> str:
|
|
142
142
|
# remove leading '/' from path if exists
|
|
143
143
|
if len(path) > 0 and path[0] == '/':
|
|
144
144
|
path = path[1:]
|
|
@@ -222,7 +222,7 @@ class APIConnector:
|
|
|
222
222
|
raise pylo.PyloApiEx("PCE connectivity or low level issue: {}".format(e))
|
|
223
223
|
|
|
224
224
|
answer_size = len(req.content) / 1024
|
|
225
|
-
log.info("URL downloaded (size "+str(
|
|
225
|
+
log.info("URL downloaded (size "+str(int(answer_size))+"KB) Reply headers:\n" +
|
|
226
226
|
"HTTP " + method + " " + url + " STATUS " + str(req.status_code) + " " + req.reason)
|
|
227
227
|
log.info(req.headers)
|
|
228
228
|
# log.info("Request Body:" + pylo.nice_json(json_arguments))
|
|
@@ -247,7 +247,9 @@ class APIConnector:
|
|
|
247
247
|
retry_loop_times = 0
|
|
248
248
|
|
|
249
249
|
while True:
|
|
250
|
-
log.info(
|
|
250
|
+
log.info(
|
|
251
|
+
"Sleeping " + str(retry_interval) + " seconds before polling for job status, elapsed " + str(
|
|
252
|
+
retry_interval * retry_loop_times) + " seconds so far")
|
|
251
253
|
retry_loop_times += 1
|
|
252
254
|
time.sleep(retry_interval)
|
|
253
255
|
job_poll = self.do_get_call(job_location, include_org_id=False)
|
|
@@ -304,17 +306,18 @@ class APIConnector:
|
|
|
304
306
|
continue
|
|
305
307
|
|
|
306
308
|
if req.status_code == 403:
|
|
307
|
-
raise pylo.PyloApiRequestForbiddenEx(
|
|
308
|
-
|
|
309
|
+
raise pylo.PyloApiRequestForbiddenEx(
|
|
310
|
+
'API returned error status "' + str(req.status_code) + ' ' + req.reason
|
|
311
|
+
+ '" and error message: ' + req.text)
|
|
309
312
|
|
|
310
313
|
raise pylo.PyloApiEx('API returned error status "' + str(req.status_code) + ' ' + req.reason
|
|
311
|
-
|
|
314
|
+
+ '" and error message: ' + req.text)
|
|
312
315
|
|
|
313
316
|
if return_headers:
|
|
314
317
|
return req.headers
|
|
315
318
|
|
|
316
319
|
if json_output_expected:
|
|
317
|
-
log.info("Parsing API answer to JSON (with a size of " + str(
|
|
320
|
+
log.info("Parsing API answer to JSON (with a size of " + str(int(answer_size)) + "KB)")
|
|
318
321
|
json_out = req.json()
|
|
319
322
|
log.info("Done!")
|
|
320
323
|
if answer_size < 5:
|
|
@@ -387,7 +390,6 @@ class APIConnector:
|
|
|
387
390
|
if 'label_dimensions' in objects_to_load:
|
|
388
391
|
del objects_to_load['label_dimensions']
|
|
389
392
|
|
|
390
|
-
|
|
391
393
|
threads_count = 4
|
|
392
394
|
data: PCEObjectsJsonStructure = pylo.Organization.create_fake_empty_config()
|
|
393
395
|
errors = []
|
|
@@ -660,7 +662,7 @@ class APIConnector:
|
|
|
660
662
|
def objects_workload_get(self,
|
|
661
663
|
include_deleted=False,
|
|
662
664
|
filter_by_ip: str = None,
|
|
663
|
-
filter_by_label: WorkloadsGetQueryLabelFilterJsonStructure=None,
|
|
665
|
+
filter_by_label: WorkloadsGetQueryLabelFilterJsonStructure = None,
|
|
664
666
|
filter_by_name: str = None,
|
|
665
667
|
filter_by_managed: bool = None,
|
|
666
668
|
filer_by_policy_health: Literal['active', 'warning', 'error'] = None,
|
|
@@ -787,12 +789,11 @@ class APIConnector:
|
|
|
787
789
|
|
|
788
790
|
try:
|
|
789
791
|
result = self.connector.objects_workload_delete_multi(list(self._hrefs.keys()))
|
|
790
|
-
except Exception as ex: #global exception means something really bad happened we log errors for all workloads
|
|
792
|
+
except Exception as ex: # global exception means something really bad happened we log errors for all workloads
|
|
791
793
|
for href in self._hrefs.keys():
|
|
792
794
|
self._errors[href] = str(ex)
|
|
793
795
|
return
|
|
794
796
|
|
|
795
|
-
|
|
796
797
|
# print(pylo.nice_json(result))
|
|
797
798
|
if not type(result) is list:
|
|
798
799
|
raise pylo.PyloApiEx("API didnt return expected JSON format", result)
|
|
@@ -816,28 +817,65 @@ class APIConnector:
|
|
|
816
817
|
if len(agents_to_unpair) > 0:
|
|
817
818
|
self._unpair_agents(agents_to_unpair)
|
|
818
819
|
|
|
820
|
+
def _mark_error(self, href: str, error_msg: str):
|
|
821
|
+
# does href contains "/ven' ?
|
|
822
|
+
if href.find("/vens/") > -1:
|
|
823
|
+
# replace '/vens/' with '/workloads/'
|
|
824
|
+
other_href = href.replace('/vens/', '/workloads/')
|
|
825
|
+
else:
|
|
826
|
+
# replace '/workloads/' with '/vens/'
|
|
827
|
+
other_href = href.replace('/workloads/', '/vens/')
|
|
828
|
+
|
|
829
|
+
# is href in self._hrefs ?
|
|
830
|
+
if href in self._hrefs:
|
|
831
|
+
self._errors[href] = error_msg
|
|
832
|
+
return
|
|
833
|
+
|
|
834
|
+
# is other_href in self._hrefs ?
|
|
835
|
+
if other_href in self._hrefs:
|
|
836
|
+
self._errors[other_href] = error_msg
|
|
837
|
+
return
|
|
838
|
+
|
|
839
|
+
# may be it's in self._workloads
|
|
840
|
+
if href in self._workloads:
|
|
841
|
+
self._errors[href] = error_msg
|
|
842
|
+
return
|
|
843
|
+
|
|
844
|
+
if other_href in self._workloads:
|
|
845
|
+
self._errors[other_href] = error_msg
|
|
846
|
+
return
|
|
847
|
+
|
|
848
|
+
raise pylo.PyloEx("Error for unknown href '{}'".format(href))
|
|
849
|
+
|
|
819
850
|
def _unpair_agents(self, workloads_hrefs: [str]):
|
|
820
|
-
|
|
851
|
+
|
|
852
|
+
# split in batches of 500 href
|
|
853
|
+
workloads_hrefs_batches = [workloads_hrefs[i:i + 500] for i in range(0, len(workloads_hrefs), 500)]
|
|
854
|
+
|
|
855
|
+
for workloads_hrefs_batch in workloads_hrefs_batches:
|
|
821
856
|
retry_count = 5
|
|
822
|
-
api_result = None
|
|
823
857
|
|
|
824
858
|
while retry_count >= 0:
|
|
825
859
|
retry_count -= 1
|
|
826
860
|
try:
|
|
827
|
-
api_result = self.connector.objects_workload_unpair_multi(
|
|
861
|
+
api_result = self.connector.objects_workload_unpair_multi(workloads_hrefs_batch)
|
|
862
|
+
for error in api_result['errors']:
|
|
863
|
+
for errored_href in error['hrefs']:
|
|
864
|
+
self._mark_error(errored_href, error['token'])
|
|
828
865
|
break
|
|
829
866
|
|
|
830
867
|
except pylo.PyloApiTooManyRequestsEx as ex:
|
|
831
868
|
if retry_count <= 0:
|
|
832
|
-
|
|
869
|
+
for href in workloads_hrefs_batch:
|
|
870
|
+
self._mark_error(href, str(ex))
|
|
833
871
|
break
|
|
834
872
|
time.sleep(6)
|
|
835
873
|
|
|
836
874
|
except pylo.PyloApiEx as ex:
|
|
837
|
-
|
|
875
|
+
for href in workloads_hrefs_batch:
|
|
876
|
+
self._mark_error(href, str(ex))
|
|
838
877
|
break
|
|
839
878
|
|
|
840
|
-
|
|
841
879
|
def count_entries(self):
|
|
842
880
|
return len(self._hrefs)
|
|
843
881
|
|
|
@@ -847,7 +885,7 @@ class APIConnector:
|
|
|
847
885
|
def new_tracker_workload_multi_delete(self):
|
|
848
886
|
return APIConnector.WorkloadMultiDeleteTracker(self)
|
|
849
887
|
|
|
850
|
-
def objects_workload_delete_multi(self, href_or_workload_array: Union[List['pylo.Workload'],List[str]]):
|
|
888
|
+
def objects_workload_delete_multi(self, href_or_workload_array: Union[List['pylo.Workload'], List[str]]):
|
|
851
889
|
if len(href_or_workload_array) < 1:
|
|
852
890
|
return
|
|
853
891
|
|
|
@@ -867,33 +905,33 @@ class APIConnector:
|
|
|
867
905
|
|
|
868
906
|
return self.do_put_call(path=path, json_arguments=json_data, json_output_expected=True)
|
|
869
907
|
|
|
870
|
-
def objects_workload_unpair_multi(self, href_or_workload_array):
|
|
871
|
-
"""
|
|
872
|
-
|
|
873
|
-
:type href_or_workload_array: list[str]|list[pylo.Workload]
|
|
874
|
-
"""
|
|
908
|
+
def objects_workload_unpair_multi(self, href_or_workload_array: Union[List['pylo.Workload'], List[str]]) -> VENUnpairApiResponseObjectJsonStructure:
|
|
875
909
|
|
|
876
910
|
if len(href_or_workload_array) < 1:
|
|
877
|
-
|
|
911
|
+
raise pylo.PyloEx("HREF list of workloads/VENs to unpair is empty")
|
|
878
912
|
|
|
879
913
|
json_data = {
|
|
880
|
-
"
|
|
881
|
-
"
|
|
914
|
+
"firewall_restore": "saved",
|
|
915
|
+
"vens": []
|
|
882
916
|
}
|
|
883
917
|
|
|
884
918
|
if type(href_or_workload_array[0]) is str:
|
|
919
|
+
href: str
|
|
885
920
|
for href in href_or_workload_array:
|
|
886
|
-
|
|
921
|
+
# href may contain '/workloads/', we want to replace it with '/vens/'
|
|
922
|
+
new_href = href.replace('/workloads/', '/vens/')
|
|
923
|
+
json_data['vens'].append({"href": new_href})
|
|
887
924
|
else:
|
|
888
|
-
|
|
889
|
-
for
|
|
890
|
-
|
|
925
|
+
workload: 'pylo.Workload'
|
|
926
|
+
for workload in href_or_workload_array:
|
|
927
|
+
new_href = workload.href.replace('/workloads/', '/vens/')
|
|
928
|
+
json_data['vens'].append({"href": new_href})
|
|
891
929
|
|
|
892
930
|
# print(json_data)
|
|
893
931
|
|
|
894
|
-
path = "/
|
|
932
|
+
path = "/vens/unpair"
|
|
895
933
|
|
|
896
|
-
return self.do_put_call(path=path, json_arguments=json_data, json_output_expected=
|
|
934
|
+
return self.do_put_call(path=path, json_arguments=json_data, json_output_expected=True)
|
|
897
935
|
|
|
898
936
|
def objects_workload_create_single_unmanaged(self, json_object: WorkloadObjectCreateJsonStructure):
|
|
899
937
|
path = '/workloads'
|
|
@@ -923,8 +961,7 @@ class APIConnector:
|
|
|
923
961
|
|
|
924
962
|
return self.do_delete_call(path=path, json_output_expected=False, include_org_id=False)
|
|
925
963
|
|
|
926
|
-
def objects_network_device_get(self,
|
|
927
|
-
max_results: int = None) -> List[NetworkDeviceObjectJsonStructure]:
|
|
964
|
+
def objects_network_device_get(self, max_results: int = None) -> List[NetworkDeviceObjectJsonStructure]:
|
|
928
965
|
path = '/network_devices'
|
|
929
966
|
data = {}
|
|
930
967
|
|
|
@@ -1069,7 +1106,7 @@ class APIConnector:
|
|
|
1069
1106
|
'enabled': enabled,
|
|
1070
1107
|
'stateless': stateless,
|
|
1071
1108
|
'consuming_security_principals': consuming_security_principals,
|
|
1072
|
-
'resolve_labels_as': {'providers': resolve_providers, 'consumers': resolve_consumers
|
|
1109
|
+
'resolve_labels_as': {'providers': resolve_providers, 'consumers': resolve_consumers},
|
|
1073
1110
|
'consumers': consumers_json,
|
|
1074
1111
|
'providers': providers_json,
|
|
1075
1112
|
'ingress_services': services_json
|
|
@@ -1270,7 +1307,7 @@ class APIConnector:
|
|
|
1270
1307
|
# get current timestamp to ensure we don't wait too long
|
|
1271
1308
|
start_time = time.time()
|
|
1272
1309
|
|
|
1273
|
-
query_status = None
|
|
1310
|
+
query_status = None # Json response from API for specific query
|
|
1274
1311
|
|
|
1275
1312
|
while True:
|
|
1276
1313
|
# check that we don't wait too long
|
|
@@ -1325,12 +1362,12 @@ class APIConnector:
|
|
|
1325
1362
|
check_for_update_interval_seconds: int = 10) -> 'pylo.ExplorerQuery':
|
|
1326
1363
|
return pylo.ExplorerQuery(self, max_results, max_running_time_seconds, check_for_update_interval_seconds)
|
|
1327
1364
|
|
|
1328
|
-
|
|
1329
1365
|
def new_audit_log_query(self, max_results: int = 10000, max_running_time_seconds: int = 1800,
|
|
1330
1366
|
check_for_update_interval_seconds: int = 10) -> 'pylo.AuditLogQuery':
|
|
1331
|
-
return pylo.AuditLogQuery(self, max_results, max_running_time_seconds
|
|
1367
|
+
return pylo.AuditLogQuery(self, max_results, max_running_time_seconds)
|
|
1332
1368
|
|
|
1333
|
-
def audit_log_query(self, max_results
|
|
1369
|
+
def audit_log_query(self, max_results=1000, event_type: Optional[str] = None) \
|
|
1370
|
+
-> List[AuditLogApiReplyEventJsonStructure]:
|
|
1334
1371
|
url = '/events'
|
|
1335
1372
|
args = {'max_results': max_results}
|
|
1336
1373
|
if event_type is not None:
|
|
@@ -1338,7 +1375,6 @@ class APIConnector:
|
|
|
1338
1375
|
|
|
1339
1376
|
return self.do_get_call(path=url, params=args)
|
|
1340
1377
|
|
|
1341
|
-
|
|
1342
1378
|
def get_pce_ui_workload_url(self, href: str) -> str:
|
|
1343
1379
|
# extract UUID from workload HREF:
|
|
1344
1380
|
uuid = href.split('/')[-1]
|
|
@@ -150,6 +150,14 @@ class VenObjectJsonStructure(TypedDict):
|
|
|
150
150
|
os_platform: Optional[str]
|
|
151
151
|
uid: Optional[str]
|
|
152
152
|
|
|
153
|
+
class VENUnpairApiResponseSingleErrorObjectJsonStructure(TypedDict):
|
|
154
|
+
token: str
|
|
155
|
+
message: str
|
|
156
|
+
hrefs: List[str]
|
|
157
|
+
|
|
158
|
+
class VENUnpairApiResponseObjectJsonStructure(TypedDict):
|
|
159
|
+
errors: List[VENUnpairApiResponseSingleErrorObjectJsonStructure]
|
|
160
|
+
|
|
153
161
|
|
|
154
162
|
class RuleServiceReferenceObjectJsonStructure(TypedDict):
|
|
155
163
|
href: str
|
|
@@ -186,6 +194,7 @@ class RulesetObjectJsonStructure(TypedDict):
|
|
|
186
194
|
scopes: List[List[RulesetScopeEntryLineJsonStructure]]
|
|
187
195
|
updated_at: str
|
|
188
196
|
updated_by: Optional[HrefReferenceWithName]
|
|
197
|
+
enabled: bool
|
|
189
198
|
|
|
190
199
|
|
|
191
200
|
class RulesetObjectUpdateStructure(TypedDict):
|
|
@@ -258,6 +267,7 @@ class PCEObjectsJsonStructure(TypedDict):
|
|
|
258
267
|
virtual_services: List[VirtualServiceObjectJsonStructure]
|
|
259
268
|
workloads: List[WorkloadObjectJsonStructure]
|
|
260
269
|
label_dimensions: List[LabelDimensionObjectStructure]
|
|
270
|
+
pce_version: str
|
|
261
271
|
|
|
262
272
|
|
|
263
273
|
class PCECacheFileJsonStructure(TypedDict):
|
|
@@ -2,6 +2,7 @@ import json
|
|
|
2
2
|
import os
|
|
3
3
|
import re
|
|
4
4
|
import time
|
|
5
|
+
import functools
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
def nice_json(json_obj):
|
|
@@ -133,7 +134,7 @@ ___ipv6_pattern = re.compile(r"""
|
|
|
133
134
|
def is_valid_ipv6(ip):
|
|
134
135
|
"""Validates IPv6 addresses.
|
|
135
136
|
"""
|
|
136
|
-
#print("testing ({})".format(ip))
|
|
137
|
+
# print("testing ({})".format(ip))
|
|
137
138
|
return ___ipv6_pattern.match(ip) is not None
|
|
138
139
|
|
|
139
140
|
|
|
@@ -145,22 +146,16 @@ __clocks_start = {}
|
|
|
145
146
|
__clocks_end = {}
|
|
146
147
|
|
|
147
148
|
|
|
148
|
-
def clock_start(name:str = 'default'):
|
|
149
|
+
def clock_start(name: str = 'default'):
|
|
149
150
|
__clocks_start[name] = time.time()
|
|
150
151
|
|
|
151
152
|
|
|
152
|
-
def clock_stop(name:str = 'default'):
|
|
153
|
+
def clock_stop(name: str = 'default'):
|
|
153
154
|
__clocks_end[name] = time.time()
|
|
154
155
|
|
|
155
156
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
def clock_elapsed_str(name:str = 'default'):
|
|
160
|
-
t = time.time()-__clocks_start[name]
|
|
157
|
+
def clock_elapsed_str(name: str = 'default'):
|
|
158
|
+
t = time.time() - __clocks_start[name]
|
|
161
159
|
return "%d:%02d:%02d.%03d" % \
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return "{}".format(time.time()-__clocks_start[name])
|
|
165
|
-
|
|
166
|
-
|
|
160
|
+
functools.reduce(lambda ll, b: divmod(ll[0], b) + ll[1:],
|
|
161
|
+
[(t * 1000,), 1000, 60, 60])
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
from typing import Dict, Optional
|
|
2
|
-
|
|
3
|
-
import illumio_pylo as pylo
|
|
4
1
|
from .API.JsonPayloadTypes import IPListObjectJsonStructure
|
|
5
2
|
from illumio_pylo import log
|
|
6
3
|
from .Helpers import *
|
|
@@ -59,15 +56,15 @@ class IPList(pylo.ReferenceTracker):
|
|
|
59
56
|
self.raw_entries[entry] = entry
|
|
60
57
|
|
|
61
58
|
def get_ip4map(self) -> pylo.IP4Map:
|
|
62
|
-
|
|
59
|
+
new_map = pylo.IP4Map()
|
|
63
60
|
|
|
64
61
|
for entry in self.raw_entries:
|
|
65
62
|
if entry[0] == '!':
|
|
66
|
-
|
|
63
|
+
new_map.subtract_from_text(entry[1:], ignore_ipv6=True)
|
|
67
64
|
else:
|
|
68
|
-
|
|
65
|
+
new_map.add_from_text(entry, ignore_ipv6=True)
|
|
69
66
|
|
|
70
|
-
return
|
|
67
|
+
return new_map
|
|
71
68
|
|
|
72
69
|
def get_raw_entries_as_string_list(self, separator=',') -> str:
|
|
73
70
|
return pylo.string_list_to_text(self.raw_entries.values(), separator=separator)
|
|
@@ -115,7 +112,7 @@ class IPListStore:
|
|
|
115
112
|
def find_by_href(self, href: str) -> Optional['pylo.IPList']:
|
|
116
113
|
return self.items_by_href.get(href)
|
|
117
114
|
|
|
118
|
-
def find_by_name(self, name: str, case_sensitive: bool = True
|
|
115
|
+
def find_by_name(self, name: str, case_sensitive: bool = True) -> Optional['pylo.IPList']:
|
|
119
116
|
if case_sensitive:
|
|
120
117
|
for iplist in self.items_by_href.values():
|
|
121
118
|
if iplist.name == name:
|
|
@@ -126,4 +123,3 @@ class IPListStore:
|
|
|
126
123
|
if iplist.name.lower() == lower_name:
|
|
127
124
|
return iplist
|
|
128
125
|
return None
|
|
129
|
-
|
|
@@ -2,7 +2,7 @@ from .Exception import PyloEx
|
|
|
2
2
|
from .Helpers.functions import is_valid_ipv6, string_list_to_text
|
|
3
3
|
import ipaddress
|
|
4
4
|
import copy
|
|
5
|
-
from typing import Optional, List
|
|
5
|
+
from typing import Optional, List
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def sort_first(val):
|
|
@@ -232,13 +232,13 @@ class IP4Map:
|
|
|
232
232
|
|
|
233
233
|
for netmask in range(1, 32, 1):
|
|
234
234
|
new_end = net_start | masks[netmask]
|
|
235
|
-
#print("{}/{}/{}/{}".format(ipaddress.IPv4Address(net_start), ipaddress.IPv4Address(net_end), ipaddress.IPv4Address(new_end), 32 - netmask))
|
|
235
|
+
# print("{}/{}/{}/{}".format(ipaddress.IPv4Address(net_start), ipaddress.IPv4Address(net_end), ipaddress.IPv4Address(new_end), 32 - netmask))
|
|
236
236
|
|
|
237
237
|
if new_end > net_end:
|
|
238
238
|
result.append('{}/{}'.format(ipaddress.IPv4Address(net_start), 33 - netmask))
|
|
239
239
|
net_start = previous_loop_end + 1
|
|
240
240
|
previous_loop_end = net_start
|
|
241
|
-
#print("breaking loop with {}/{}".format(ipaddress.IPv4Address(net_start), ipaddress.IPv4Address(previous_loop_end)))
|
|
241
|
+
# print("breaking loop with {}/{}".format(ipaddress.IPv4Address(net_start), ipaddress.IPv4Address(previous_loop_end)))
|
|
242
242
|
break
|
|
243
243
|
|
|
244
244
|
if new_end == net_end:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from hashlib import md5
|
|
2
2
|
import random
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Set
|
|
4
4
|
# Pylo imports
|
|
5
5
|
from illumio_pylo import log
|
|
6
6
|
from .API.JsonPayloadTypes import LabelObjectJsonStructure, LabelGroupObjectJsonStructure, LabelDimensionObjectStructure
|
|
@@ -96,7 +96,7 @@ class LabelStore:
|
|
|
96
96
|
|
|
97
97
|
def load_label_groups_from_json(self, json_list: List[LabelGroupObjectJsonStructure]):
|
|
98
98
|
# groups cannot be loaded straight away : we need to extract of their principal properties (name, href and type)
|
|
99
|
-
#then we can extract their members in case there are nested groups
|
|
99
|
+
# then we can extract their members in case there are nested groups
|
|
100
100
|
created_groups = []
|
|
101
101
|
for json_label in json_list:
|
|
102
102
|
if 'name' not in json_label or 'href' not in json_label or 'key' not in json_label:
|
|
@@ -174,33 +174,34 @@ class LabelStore:
|
|
|
174
174
|
data.append(label)
|
|
175
175
|
return data
|
|
176
176
|
|
|
177
|
-
|
|
178
177
|
def get_label_groups_as_dict_by_href(self, label_type: Optional[str] = None) -> Dict[str, 'pylo.LabelGroup']:
|
|
179
178
|
label_list = self.get_label_groups(label_type)
|
|
180
179
|
return self.Utils.list_to_dict_by_href(label_list)
|
|
181
180
|
|
|
182
|
-
|
|
183
|
-
|
|
181
|
+
def get_both_labels_and_groups(self, label_type: Optional[str] = None) \
|
|
182
|
+
-> List[Union['pylo.Label', 'pylo.LabelGroup']]:
|
|
184
183
|
data = []
|
|
185
184
|
if label_type is not None:
|
|
186
185
|
if label_type not in self.label_types_as_set:
|
|
187
|
-
raise pylo.PyloEx(
|
|
186
|
+
raise pylo.PyloEx(
|
|
187
|
+
"Invalid label type '%s'. Valid types are: %s" % (label_type, self.label_types_as_set))
|
|
188
188
|
|
|
189
189
|
for label in self._items_by_href.values():
|
|
190
190
|
if label_type is None or label.type == label_type:
|
|
191
191
|
data.append(label)
|
|
192
192
|
return data
|
|
193
193
|
|
|
194
|
-
def get_both_labels_and_groups_as_dict_by_href(self, label_type: Optional[str] = None)
|
|
194
|
+
def get_both_labels_and_groups_as_dict_by_href(self, label_type: Optional[str] = None) \
|
|
195
|
+
-> Dict[str, Union['pylo.Label', 'pylo.LabelGroup']]:
|
|
195
196
|
label_list = self.get_both_labels_and_groups(label_type)
|
|
196
197
|
return self.Utils.list_to_dict_by_href(label_list)
|
|
197
198
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
199
|
+
def find_object_by_name(self, name: str | List[str], label_type: Optional[str] = None, case_sensitive: bool = True,
|
|
200
|
+
missing_labels_names: Optional[List[str]] = None,
|
|
201
|
+
allow_label_group: bool = True,
|
|
202
|
+
allow_label: bool = True,
|
|
203
|
+
raise_exception_if_not_found: bool = False) \
|
|
204
|
+
-> Optional[Union['pylo.Label', 'pylo.LabelGroup', List[Union['pylo.Label', 'pylo.LabelGroup']]]]:
|
|
204
205
|
"""Find a label by its name. If case_sensitive is False, the search is case-insensitive.
|
|
205
206
|
If case_sensitive is False it will return a list of labels with the same name rather than a single object.
|
|
206
207
|
If missing_labels_names is not None, it will be filled with the names of the labels not found.
|
|
@@ -218,13 +219,13 @@ class LabelStore:
|
|
|
218
219
|
for label in self._items_by_href.values():
|
|
219
220
|
if label_type is not None and label.type != label_type:
|
|
220
221
|
continue
|
|
221
|
-
if label.is_label() and allow_label:
|
|
222
|
+
if label.is_label() and allow_label: # ignore groups
|
|
222
223
|
if case_sensitive:
|
|
223
224
|
if label.name == name:
|
|
224
225
|
return label
|
|
225
226
|
elif allow_label_group:
|
|
226
|
-
|
|
227
|
-
|
|
227
|
+
if label.name.lower() == name.lower():
|
|
228
|
+
return label
|
|
228
229
|
if raise_exception_if_not_found:
|
|
229
230
|
raise pylo.PyloEx("Label/group '%s' not found", name)
|
|
230
231
|
if missing_labels_names is not None:
|
|
@@ -234,10 +235,10 @@ class LabelStore:
|
|
|
234
235
|
results = []
|
|
235
236
|
local_notfound_labels = []
|
|
236
237
|
for name_to_find in name:
|
|
237
|
-
result = self.find_object_by_name(name_to_find, label_type=label_type
|
|
238
|
-
|
|
238
|
+
result = self.find_object_by_name(name_to_find, label_type=label_type, case_sensitive=case_sensitive,
|
|
239
|
+
allow_label_group=allow_label_group, allow_label=allow_label)
|
|
239
240
|
if result is None:
|
|
240
|
-
|
|
241
|
+
local_notfound_labels.append(name_to_find)
|
|
241
242
|
else:
|
|
242
243
|
results.append(result)
|
|
243
244
|
if raise_exception_if_not_found and len(local_notfound_labels) > 0:
|
|
@@ -246,9 +247,9 @@ class LabelStore:
|
|
|
246
247
|
missing_labels_names.extend(local_notfound_labels)
|
|
247
248
|
return results
|
|
248
249
|
|
|
249
|
-
def find_label_by_name(self, name: str|List[str], label_type: Optional[str] = None, case_sensitive: bool = True,
|
|
250
|
-
|
|
251
|
-
|
|
250
|
+
def find_label_by_name(self, name: str | List[str], label_type: Optional[str] = None, case_sensitive: bool = True,
|
|
251
|
+
missing_labels_names: Optional[List[str]] = None,
|
|
252
|
+
raise_exception_if_not_found: bool = False) -> Optional['pylo.Label' | List['pylo.Label']]:
|
|
252
253
|
"""Find a label by its name.
|
|
253
254
|
If case_sensitive is False it will return a list of labels with the same name rather than a single object.
|
|
254
255
|
If missing_labels_names is not None, it will be filled with the names of the labels not found.
|
|
@@ -261,12 +262,10 @@ class LabelStore:
|
|
|
261
262
|
allow_label_group=False, allow_label=True,
|
|
262
263
|
raise_exception_if_not_found=raise_exception_if_not_found)
|
|
263
264
|
|
|
264
|
-
|
|
265
265
|
def find_label_by_name_whatever_type(self, name: str, case_sensitive: bool = True) -> Optional[Union['pylo.Label', 'pylo.LabelGroup']]:
|
|
266
266
|
pylo.log.warn("find_label_by_name_whatever_type is deprecated, use find_label_by_name instead")
|
|
267
267
|
return self.find_label_by_name(name, case_sensitive=case_sensitive)
|
|
268
268
|
|
|
269
|
-
|
|
270
269
|
def find_label_by_name_and_type(self, name: str, label_type: str, case_sensitive: bool = True) \
|
|
271
270
|
-> Optional[Union['pylo.Label', 'pylo.LabelGroup']]:
|
|
272
271
|
pylo.log.warn("find_label_by_name_and_type is deprecated, use find_label_by_name instead")
|
|
@@ -366,7 +365,7 @@ class LabelStore:
|
|
|
366
365
|
|
|
367
366
|
new_label_name = name
|
|
368
367
|
new_label_type = label_type
|
|
369
|
-
new_label_href = '**fake-label-href**/{}'.format(
|
|
368
|
+
new_label_href = '**fake-label-href**/{}'.format(md5(str(random.random()).encode('utf8')).digest())
|
|
370
369
|
|
|
371
370
|
new_label = pylo.Label(new_label_name, new_label_href, new_label_type, self)
|
|
372
371
|
|
|
@@ -18,10 +18,10 @@ class LabeledObject:
|
|
|
18
18
|
def get_labels(self) -> Iterable['pylo.Label']:
|
|
19
19
|
return self._labels.values()
|
|
20
20
|
|
|
21
|
-
def set_label(self, label
|
|
21
|
+
def set_label(self, label: 'pylo.Label'):
|
|
22
22
|
self._labels[label.type] = label
|
|
23
23
|
|
|
24
|
-
def get_label_name(self, key: str, not_found_return_value
|
|
24
|
+
def get_label_name(self, key: str, not_found_return_value=None):
|
|
25
25
|
label = self.get_label(key)
|
|
26
26
|
return label.name if label else not_found_return_value
|
|
27
27
|
|
|
@@ -53,7 +53,6 @@ class LabeledObject:
|
|
|
53
53
|
|
|
54
54
|
def is_using_label(self, label: Union['pylo.Label', 'pylo.LabelGroup']) -> bool:
|
|
55
55
|
if isinstance(label, pylo.Label):
|
|
56
|
-
return label
|
|
56
|
+
return label in self._labels
|
|
57
57
|
else:
|
|
58
|
-
return any([label
|
|
59
|
-
|
|
58
|
+
return any([label in self._labels for label in label.get_members().values()])
|