tgwrap 0.10.0__py3-none-any.whl → 0.10.2__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.
tgwrap/cli.py CHANGED
@@ -750,6 +750,11 @@ def check_deployments(manifest_file, verbose, working_dir, out):
750
750
  help='Whether or not external dependencies must be ignored',
751
751
  show_default=True
752
752
  )
753
+ @click.option('--analyze', '-a',
754
+ is_flag=True, default=False,
755
+ help='Show analysis of the graph',
756
+ show_default=True
757
+ )
753
758
  @click.option('--include-dir', '-I',
754
759
  multiple=True, default=[],
755
760
  help=r'A glob of a directory that needs to be included, this option can be used multiple times. For example: -I "integrations/\*/\*"',
@@ -765,7 +770,7 @@ def check_deployments(manifest_file, verbose, working_dir, out):
765
770
  )
766
771
  @click.argument('terragrunt-args', nargs=-1, type=click.UNPROCESSED)
767
772
  @click.version_option(version=__version__)
768
- def show_graph(verbose, backwards, exclude_external_dependencies, working_dir, include_dir, exclude_dir, terragrunt_args):
773
+ def show_graph(verbose, backwards, exclude_external_dependencies, analyze, working_dir, include_dir, exclude_dir, terragrunt_args):
769
774
  """ Shows the dependencies of a project """
770
775
 
771
776
  check_latest_version(verbose)
@@ -774,6 +779,7 @@ def show_graph(verbose, backwards, exclude_external_dependencies, working_dir, i
774
779
  tgwrap.show_graph(
775
780
  backwards=backwards,
776
781
  exclude_external_dependencies=exclude_external_dependencies,
782
+ analyze=analyze,
777
783
  working_dir=working_dir,
778
784
  include_dirs=include_dir,
779
785
  exclude_dirs=exclude_dir,
@@ -43,6 +43,11 @@ databricks_workspace:
43
43
  properties:
44
44
  properties.provisioningState: Succeeded
45
45
  location: "{{location_code}}"
46
+ machine_learning_workspace:
47
+ url: https://management.azure.com/subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.MachineLearningServices/workspaces/{name}?api-version=2023-04-01
48
+ properties:
49
+ properties.provisioningState: Succeeded
50
+ location: "{{location_code}}"
46
51
  data_factory:
47
52
  url: https://management.azure.com/subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.DataFactory/factories/{name}?api-version=2018-06-01
48
53
  properties:
tgwrap/main.py CHANGED
@@ -1764,15 +1764,88 @@ Note:
1764
1764
  except Exception:
1765
1765
  pass
1766
1766
 
1767
- def show_graph(self, backwards, exclude_external_dependencies, working_dir, include_dirs, exclude_dirs, terragrunt_args):
1767
+ def show_graph(self, backwards, exclude_external_dependencies, analyze, working_dir, include_dirs, exclude_dirs, terragrunt_args):
1768
1768
  """ Shows the dependencies of a project """
1769
1769
 
1770
+ def set_json_dumps_default(obj):
1771
+ if isinstance(obj, set):
1772
+ return list(obj)
1773
+ raise TypeError
1774
+
1775
+ def calculate_dependencies(graph):
1776
+ dependencies = {}
1777
+ for node in graph.nodes:
1778
+ out_degree = graph.out_degree(node)
1779
+ in_degree = graph.in_degree(node)
1780
+ total_degree = out_degree + in_degree
1781
+ dependencies[node] = {
1782
+ 'dependencies': out_degree,
1783
+ 'dependent_on_it': in_degree,
1784
+ 'total': total_degree,
1785
+ }
1786
+
1787
+ return dependencies
1788
+
1789
+ def calculate_graph_metrics(graph):
1790
+
1791
+ metrics = {}
1792
+
1793
+ # Degree centrality
1794
+ metric = {
1795
+ 'values': dict(sorted(nx.degree_centrality(graph).items(), key=lambda item: item[1], reverse=True)),
1796
+ 'description': 'Shows the degree of each node relative to the number of nodes in the graph',
1797
+ }
1798
+ sorted_dependencies = sorted(dependencies.items(), key=lambda x: x[1]['total'], reverse=True)
1799
+ metrics['degree_centrality'] = metric
1800
+
1801
+ # Betweenness centrality
1802
+ metric = {
1803
+ 'values': dict(sorted(nx.betweenness_centrality(graph).items(), key=lambda item: item[1], reverse=True)),
1804
+ 'description': 'Indicates nodes that frequently lie on shortest paths between other nodes',
1805
+ }
1806
+ metrics['betweenness_centrality'] = metric
1807
+
1808
+ # Closeness centrality
1809
+ metric = {
1810
+ 'values': dict(sorted(nx.closeness_centrality(graph).items(), key=lambda item: item[1], reverse=True)),
1811
+ 'description': 'Reflects how quickly a node can reach other nodes in the graph',
1812
+ }
1813
+ metrics['closeness_centrality'] = metric
1814
+
1815
+ # Strongly Connected Components (SCC)
1816
+ metric = {
1817
+ 'values': list(nx.strongly_connected_components(graph)),
1818
+ 'description': 'Lists sets of nodes that are mutually reachable',
1819
+ }
1820
+ metrics['strongly_connected_components'] = metric
1821
+
1822
+ # Weakly Connected Components (WCC)
1823
+ metric = {
1824
+ 'values': list(nx.weakly_connected_components(graph)),
1825
+ 'description': 'Lists sets of nodes that are connected disregarding edge directions',
1826
+ }
1827
+ metrics['weakly_connected_components'] = metric
1828
+
1829
+ # Average Path Length (only if the graph is connected)
1830
+ if nx.is_strongly_connected(graph):
1831
+ metric = {
1832
+ 'values': nx.average_shortest_path_length(graph),
1833
+ 'description': 'Shows the average shortest path length, indicating the graph\'s efficiency',
1834
+ }
1835
+ metrics['average_path_length'] = metric
1836
+
1837
+ return metrics
1838
+
1770
1839
  self.printer.verbose(f"Attempting to show dependencies")
1771
1840
  if terragrunt_args:
1772
1841
  self.printer.verbose(f"- with additional parameters: {' '.join(terragrunt_args)}")
1773
1842
 
1774
1843
  "Runs the desired command in the directories as defined in the directed graph"
1775
1844
  graph = self._get_di_graph(backwards=backwards, working_dir=working_dir)
1845
+ try:
1846
+ graph.remove_node(r'\n')
1847
+ except nx.exception.NetworkXError:
1848
+ pass
1776
1849
 
1777
1850
  # first go through the groups and clean up where needed
1778
1851
  groups = self._prepare_groups(
@@ -1792,6 +1865,27 @@ Note:
1792
1865
  for directory in group:
1793
1866
  self.printer.normal(f"- {directory}")
1794
1867
 
1868
+ if analyze:
1869
+ self.printer.header("Graph analysis", print_line_before=True)
1870
+
1871
+ self.printer.bold("Dependencies counts:", print_line_before=True)
1872
+ dependencies = calculate_dependencies(graph)
1873
+ sorted_dependencies = sorted(dependencies.items(), key=lambda x: x[1]['total'], reverse=True)
1874
+ for node, counts in sorted_dependencies:
1875
+ msg = f"""
1876
+ {node} ->
1877
+ \ttotal: {counts['total']}
1878
+ \tdependent on: {counts['dependent_on_it']}
1879
+ \tdependencies: {counts['dependencies']}
1880
+ """
1881
+ self.printer.normal(msg)
1882
+
1883
+ metrics = calculate_graph_metrics(graph)
1884
+ for metric, item in metrics.items():
1885
+ self.printer.bold(f'Metric: {metric}')
1886
+ self.printer.normal(f'Description: {item["description"]}')
1887
+ self.printer.normal(json.dumps(item['values'], indent=2, default=set_json_dumps_default))
1888
+
1795
1889
  def clean(self, working_dir):
1796
1890
  """ Clean the temporary files of a terragrunt/terraform project """
1797
1891
 
@@ -1922,9 +2016,12 @@ Note:
1922
2016
  exit_code = 0
1923
2017
  self.printer.header('Inspection status:', print_line_before=True)
1924
2018
  for k,v in results.items():
1925
- msg = f"{v['type']}: {k}\n\t-> Resource:\t{v.get('inspect_status_code', 'NC')} ({v.get('inspect_message', 'not found')})"
2019
+ msg = f"""{v['type']}: {k}
2020
+ -> Resource: {v.get('inspect_status_code', 'NC')} ({v.get('inspect_message', 'not found')})""" # only since python 3.12 you can use things like \t and \n in an f-string
1926
2021
  if 'rbac_assignment_status_code' in v:
1927
- msg = msg + f'\n\t-> RBAC:\t{v['rbac_assignment_status_code']} ({v.get('rbac_assignment_message')})'
2022
+ msg = msg + f"""
2023
+ -> RBAC: {v['rbac_assignment_status_code']} ({v.get('rbac_assignment_message')})"
2024
+ """ # only since python 3.12 you can use things like \t and \n in an f-string
1928
2025
  if v['inspect_status_code'] != 'OK' or v.get('rbac_assignment_status_code', 'OK') == 'NOK':
1929
2026
  self.printer.error(msg=msg)
1930
2027
  exit_code += 1
@@ -1,17 +1,15 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tgwrap
3
- Version: 0.10.0
3
+ Version: 0.10.2
4
4
  Summary: A (terragrunt) wrapper around a (terraform) wrapper around ....
5
5
  Home-page: https://gitlab.com/lunadata/tgwrap
6
6
  License: MIT
7
7
  Keywords: terraform,terragrunt,terrasafe,python
8
8
  Author: Gerco Grandia
9
9
  Author-email: gerco.grandia@4synergy.nl
10
- Requires-Python: >=3.10,<4.0
10
+ Requires-Python: >=3.12,<4.0
11
11
  Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.10
14
- Classifier: Programming Language :: Python :: 3.11
15
13
  Classifier: Programming Language :: Python :: 3.12
16
14
  Requires-Dist: azure-core (>=1.30.2,<2.0.0)
17
15
  Requires-Dist: azure-identity (>=1.17.1,<2.0.0)
@@ -0,0 +1,13 @@
1
+ tgwrap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ tgwrap/analyze.py,sha256=TJvAKVIbWl8-8oxpTwXVBWU72q_XQKzUTlyMZ25cV2M,8728
3
+ tgwrap/cli.py,sha256=0SFzLJA-deut81Mpt6Giq77WK26vTDcajyFnPIHXR5c,31649
4
+ tgwrap/deploy.py,sha256=-fSk-Ix_HqrXY7KQX_L27TnFzIuhBHYv4xYJW6zRDN4,10243
5
+ tgwrap/inspector-resources-template.yml,sha256=Mos8NDzzZ3VxdXgeiVL9cmQfRcIXIHMLf79_KLwdXu8,3297
6
+ tgwrap/inspector.py,sha256=5pW7Ex1lkKRoXY6hZGbCNmSD2iRzgMSfqi9w7gb-AcY,16990
7
+ tgwrap/main.py,sha256=WKxlREE4QmdZKTHivhWa3K5yI40amGlmjBs4y7oCTqw,88748
8
+ tgwrap/printer.py,sha256=frn1PARd8A28mkRCYR6ybN2x0NBULhNOutn4l2U7REY,2754
9
+ tgwrap-0.10.2.dist-info/LICENSE,sha256=VT-AVxIXt3EQTC-7Hy1uPGnrDNJLqfcgLgJD78fiyx4,1065
10
+ tgwrap-0.10.2.dist-info/METADATA,sha256=TMYitOkytrAQdGcEIeCOeiyKLg5yAFtgnmiupyLiJjo,17476
11
+ tgwrap-0.10.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
12
+ tgwrap-0.10.2.dist-info/entry_points.txt,sha256=H8X0PMPmd4aW7Y9iyChZ0Ug6RWGXqhRUvHH-6f6Mxz0,42
13
+ tgwrap-0.10.2.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- tgwrap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- tgwrap/analyze.py,sha256=TJvAKVIbWl8-8oxpTwXVBWU72q_XQKzUTlyMZ25cV2M,8728
3
- tgwrap/cli.py,sha256=UokTSBp84HZ9IAwn0MlGMUjpjL76SILWm1GNlVHAqr0,31482
4
- tgwrap/deploy.py,sha256=-fSk-Ix_HqrXY7KQX_L27TnFzIuhBHYv4xYJW6zRDN4,10243
5
- tgwrap/inspector-resources-template.yml,sha256=goQaqyaTb_o1fAuCBHl-6xc1Rul63Byqau5RQ4qJvTo,2992
6
- tgwrap/inspector.py,sha256=5pW7Ex1lkKRoXY6hZGbCNmSD2iRzgMSfqi9w7gb-AcY,16990
7
- tgwrap/main.py,sha256=zKddIfI7-KHd1lX9xXh_tqgnIUa8uOxqDSxsVNW-klg,84544
8
- tgwrap/printer.py,sha256=frn1PARd8A28mkRCYR6ybN2x0NBULhNOutn4l2U7REY,2754
9
- tgwrap-0.10.0.dist-info/LICENSE,sha256=VT-AVxIXt3EQTC-7Hy1uPGnrDNJLqfcgLgJD78fiyx4,1065
10
- tgwrap-0.10.0.dist-info/METADATA,sha256=kH2A2ZYjEQPKQ0iGbJKiachqmV1yELC3j1k5g7ZWVyM,17578
11
- tgwrap-0.10.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
12
- tgwrap-0.10.0.dist-info/entry_points.txt,sha256=H8X0PMPmd4aW7Y9iyChZ0Ug6RWGXqhRUvHH-6f6Mxz0,42
13
- tgwrap-0.10.0.dist-info/RECORD,,