clear-skies-cortex 2.0.4__py3-none-any.whl → 2.0.6__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clear-skies-cortex
3
- Version: 2.0.4
3
+ Version: 2.0.6
4
4
  Summary: Cortex module for Clearskies
5
5
  Project-URL: Docs, https://https://clearskies.info/modules/clear-skies-cortex
6
6
  Project-URL: Repository, https://github.com/clearskies-py/cortex
@@ -9,7 +9,7 @@ clearskies_cortex/defaults/__init__.py,sha256=tulZSvFgp4YUKj_bnArIevmlpC8z_AQKO0
9
9
  clearskies_cortex/defaults/default_cortex_auth.py,sha256=sWlWgXIoCXk0FkwK3Kz33TVohsaVpIOS9qj2Ef5_YN8,2135
10
10
  clearskies_cortex/defaults/default_cortex_url.py,sha256=sKBDQVPJWc4ozBquZ7fKryTbUOXYfrH6hUcQuUtMXEU,1576
11
11
  clearskies_cortex/models/__init__.py,sha256=zckJ4-KOjIcmtN7h7lXOESUu3d6JBsZZJq-s2MJ0NLQ,1145
12
- clearskies_cortex/models/cortex_catalog_entity.py,sha256=nWKApnvcr3pmSijEJgZ4cuZgG9ck6d8ey3AyVb8vfXQ,6632
12
+ clearskies_cortex/models/cortex_catalog_entity.py,sha256=MqEe-Kb3JDzhmEckBZZr4Ms3Zv1Ul6Rom_1-XF5Moi0,12461
13
13
  clearskies_cortex/models/cortex_catalog_entity_domain.py,sha256=AOa07Fq-SWc8zkg6g-fBi5x1GnGg42GhPM2GozrgC2c,2327
14
14
  clearskies_cortex/models/cortex_catalog_entity_group.py,sha256=D5Je_kX4dBW8jkhmZBca02mFYT3cqK1walleMXTlcdg,1295
15
15
  clearskies_cortex/models/cortex_catalog_entity_scorecard.py,sha256=XT08_865AzsiMGsybIhQPQ8jTR1HrCfAtRAME7MdDo0,2372
@@ -22,7 +22,7 @@ clearskies_cortex/models/cortex_scorecard.py,sha256=aiM8_MkdMT_n-a6teG8y6zWSLmHu
22
22
  clearskies_cortex/models/cortex_team.py,sha256=UUS1KHufPqhO29h4eKIfeZzUz75KjwkqaW5ItmdAKS4,4356
23
23
  clearskies_cortex/models/cortex_team_category_tree.py,sha256=PRCIGeZrBoGiH1a7Q8ZsYYzSfj4cZF9tIRcBWEKAX60,1898
24
24
  clearskies_cortex/models/cortex_team_department.py,sha256=_0Go97ZFr_GCd_ol0iBw7Px5F_gE94WtAWFGnzQ9y-M,1582
25
- clear_skies_cortex-2.0.4.dist-info/METADATA,sha256=rhPhCyHqZqZ7yks_PDAaZX1aJ-MBL0kaG_oYh-NS_Bo,2117
26
- clear_skies_cortex-2.0.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
27
- clear_skies_cortex-2.0.4.dist-info/licenses/LICENSE,sha256=MkEX8JF8kZxdyBpTTcB0YTd-xZpWnHvbRlw-pQh8u58,1069
28
- clear_skies_cortex-2.0.4.dist-info/RECORD,,
25
+ clear_skies_cortex-2.0.6.dist-info/METADATA,sha256=Vp6Y9IyPqXd7GY_XTibg-WytYIgydZTON-sMHLMoIvI,2117
26
+ clear_skies_cortex-2.0.6.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
27
+ clear_skies_cortex-2.0.6.dist-info/licenses/LICENSE,sha256=MkEX8JF8kZxdyBpTTcB0YTd-xZpWnHvbRlw-pQh8u58,1069
28
+ clear_skies_cortex-2.0.6.dist-info/RECORD,,
@@ -225,6 +225,8 @@ class CortexCatalogEntity(Model):
225
225
 
226
226
  def parse_hierarchy(self) -> dataclasses.ServiceEntityHierarchy:
227
227
  """Parse the hierarchy column into a dictionary."""
228
+ if self.hierarchy is None:
229
+ return dataclasses.ServiceEntityHierarchy(parents=[], children=[])
228
230
  return from_dict(dataclasses.ServiceEntityHierarchy, data=self.hierarchy)
229
231
 
230
232
  def parse_groups(self) -> dict[str, str]:
@@ -243,5 +245,169 @@ class CortexCatalogEntity(Model):
243
245
  return parsed
244
246
 
245
247
  def parse_owners(self) -> dataclasses.EntityTeamOwner:
246
- """Parse the owners column into a dictionary."""
248
+ """Parse the owners column into a dictionary.
249
+
250
+ Returns an empty EntityTeamOwner if owners is None.
251
+ """
252
+ if self.owners is None:
253
+ return dataclasses.EntityTeamOwner(teams=[], individuals=[])
247
254
  return from_dict(dataclasses.EntityTeamOwner, data=self.owners)
255
+
256
+ def get_group_tags(self) -> list[str]:
257
+ """Get groups as simple tags.
258
+
259
+ Returns groups that don't have a key:value format.
260
+
261
+ Returns:
262
+ List of group names that are simple tags without key:value format.
263
+
264
+ Example:
265
+ >>> entity.groups = ["my-tag", "team:platform", "production"]
266
+ >>> entity.get_group_tags()
267
+ ["my-tag", "production"]
268
+ """
269
+ tags: list[str] = []
270
+ if self.groups:
271
+ for group in self.groups:
272
+ if ":" not in group:
273
+ tags.append(group)
274
+ return tags
275
+
276
+ def get_group_value(self, key: str) -> str | None:
277
+ """Get the value for a specific group key.
278
+
279
+ Groups can be formatted as "key:value" pairs. This method extracts
280
+ the value for a given key.
281
+
282
+ Args:
283
+ key: The group key to look up.
284
+
285
+ Returns:
286
+ The value associated with the key, or None if not found.
287
+
288
+ Example:
289
+ >>> entity.groups = ["team:platform", "env:production"]
290
+ >>> entity.get_group_value("team")
291
+ "platform"
292
+ """
293
+ if self.groups:
294
+ for group in self.groups:
295
+ if group.startswith(f"{key}:"):
296
+ return group.split(":", 1)[1]
297
+ return None
298
+
299
+ def get_git_repository_url(self) -> str | None:
300
+ """Get the Git repository URL.
301
+
302
+ Returns:
303
+ The repository URL, or None if not configured.
304
+
305
+ Example:
306
+ >>> entity.git = {"repository": "https://github.com/org/repo"}
307
+ >>> entity.get_git_repository_url()
308
+ "https://github.com/org/repo"
309
+ """
310
+ if not self.git:
311
+ return None
312
+ return self.git.get("repository") or self.git.get("repositoryUrl")
313
+
314
+ def get_git_provider(self) -> str | None:
315
+ """Get the Git provider name.
316
+
317
+ Returns:
318
+ The provider name (e.g., "github", "gitlab", "bitbucket", "azure-devops"),
319
+ or None if not configured.
320
+
321
+ Example:
322
+ >>> entity.git = {"provider": "github", "repository": "..."}
323
+ >>> entity.get_git_provider()
324
+ "github"
325
+ """
326
+ if not self.git:
327
+ return None
328
+ return self.git.get("provider")
329
+
330
+ def get_git_project_id(self) -> str | None:
331
+ """Extract the project/repository identifier from the Git configuration.
332
+
333
+ Cortex supports multiple SCM providers (GitHub, GitLab, Bitbucket, Azure DevOps).
334
+ This method extracts the project identifier in a provider-agnostic way.
335
+
336
+ For GitLab, this returns the numeric project ID if available in the URL.
337
+ For GitHub/Bitbucket, this returns the "owner/repo" format.
338
+ For Azure DevOps, this returns the project/repo path.
339
+
340
+ Returns:
341
+ The project identifier as a string, or None if not found.
342
+
343
+ Example:
344
+ >>> entity.git = {"repository": "https://github.com/org/repo"}
345
+ >>> entity.get_git_project_id()
346
+ "org/repo"
347
+
348
+ >>> entity.git = {"repository": "https://gitlab.com/projects/12345"}
349
+ >>> entity.get_git_project_id()
350
+ "12345"
351
+ """
352
+ if not self.git:
353
+ return None
354
+
355
+ repo_url = self.git.get("repository") or self.git.get("repositoryUrl") or ""
356
+
357
+ # GitLab numeric project ID format: https://gitlab.com/projects/12345
358
+ if "/projects/" in repo_url:
359
+ try:
360
+ project_id = repo_url.split("/projects/")[1].split("/")[0]
361
+ return project_id
362
+ except IndexError:
363
+ pass
364
+
365
+ # Standard URL format: https://provider.com/owner/repo or https://provider.com/owner/repo.git
366
+ # Works for GitHub, GitLab (path format), Bitbucket
367
+ for prefix in ["github.com/", "gitlab.com/", "bitbucket.org/"]:
368
+ if prefix in repo_url:
369
+ try:
370
+ path = repo_url.split(prefix)[1]
371
+ # Remove .git suffix if present
372
+ if path.endswith(".git"):
373
+ path = path[:-4]
374
+ # Remove trailing slashes
375
+ path = path.rstrip("/")
376
+ # Return owner/repo format
377
+ parts = path.split("/")
378
+ if len(parts) >= 2:
379
+ return f"{parts[0]}/{parts[1]}"
380
+ except IndexError:
381
+ pass
382
+
383
+ # Azure DevOps format: https://dev.azure.com/org/project/_git/repo
384
+ if "dev.azure.com/" in repo_url:
385
+ try:
386
+ path = repo_url.split("dev.azure.com/")[1]
387
+ parts = path.split("/")
388
+ if len(parts) >= 4 and parts[2] == "_git":
389
+ return f"{parts[0]}/{parts[1]}/{parts[3]}"
390
+ except IndexError:
391
+ pass
392
+
393
+ return None
394
+
395
+ @property
396
+ def is_cloud_resource(self) -> bool:
397
+ """Check if entity represents a cloud resource.
398
+
399
+ Cortex supports pulling in resources from AWS, Azure, and Google Cloud.
400
+ This property checks if the entity type indicates a cloud resource.
401
+
402
+ Returns:
403
+ True if the entity type indicates a cloud resource.
404
+
405
+ Example:
406
+ >>> entity.type = "AWS::Lambda::Function"
407
+ >>> entity.is_cloud_resource
408
+ True
409
+ """
410
+ if not self.type:
411
+ return False
412
+ cloud_prefixes = ("AWS::", "Azure::", "Google::")
413
+ return self.type.startswith(cloud_prefixes)