qontract-reconcile 0.10.1rc806__py3-none-any.whl → 0.10.1rc808__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.1
2
2
  Name: qontract-reconcile
3
- Version: 0.10.1rc806
3
+ Version: 0.10.1rc808
4
4
  Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
5
5
  Home-page: https://github.com/app-sre/qontract-reconcile
6
6
  Author: Red Hat App-SRE Team
@@ -10,7 +10,7 @@ reconcile/aws_iam_password_reset.py,sha256=NwErtrqgBiXr7eGCAHdtGGOx0S7-4JnSc29Ie
10
10
  reconcile/aws_support_cases_sos.py,sha256=Jk6_XjDeJSYxgRGqcEAOcynt9qJF2r5HPIPcSKmoBv8,2974
11
11
  reconcile/blackbox_exporter_endpoint_monitoring.py,sha256=W_VJagnsJR1v5oqjlI3RJJE0_nhtJ0m81RS8zWA5u5c,3538
12
12
  reconcile/checkpoint.py,sha256=R2WFXUXLTB4sWMi4GeA4eegsuf_1-Q4vH8M0Toh3Ij4,5036
13
- reconcile/cli.py,sha256=pBX9_8GU6g4m8Y3-KeX8wOCv9datyVqxvbkXTmgdvNQ,100833
13
+ reconcile/cli.py,sha256=n64KqkdnqF_H2WHoqlSxQ2PP0uYuY9THPGeyiLP9zJA,101154
14
14
  reconcile/closedbox_endpoint_monitoring_base.py,sha256=SMhkcQqprWvThrIJa3U_3uh5w1h-alleW1QnCJFY4Qw,4909
15
15
  reconcile/cluster_deployment_mapper.py,sha256=2Ah-nu-Mdig0pjuiZl_XLrmVAjYzFjORR3dMlCgkmw0,2352
16
16
  reconcile/dashdotdb_base.py,sha256=a5aPLVxyqPSbjdB0Ty-uliOtxwvEbbEljHJKxdK3-Zk,4813
@@ -104,7 +104,7 @@ reconcile/sendgrid_teammates.py,sha256=oO8QbLb4s1o8A6CGiCagN9CmS05BSS_WLztuY0Ym9
104
104
  reconcile/service_dependencies.py,sha256=PMKP9vc6oL-78rzyF_RE8DzLSQMSqN8vCqt9sWpBLAM,4470
105
105
  reconcile/signalfx_endpoint_monitoring.py,sha256=D1m8iq0EAKie0OD59FOcVCtpWWZ7xlo6lwBS9urwMIk,2894
106
106
  reconcile/slack_base.py,sha256=K3fSYx46G1djoPb07_C9j6ChhMCt5LgV5l6v2TFkNZk,3479
107
- reconcile/slack_usergroups.py,sha256=sp1QSPRUgTj3-hXpAWx1qOeR6okmVmlHcTUvUMTOLDI,27855
107
+ reconcile/slack_usergroups.py,sha256=vYecHCeJMZhxy1l0bIahTRN6ja0vxTSTXN2UfOkYXOo,29727
108
108
  reconcile/sql_query.py,sha256=FAQI9EIHsokZBbGwvGU4vnjg1fHemxpYQE20UtCB1qo,25941
109
109
  reconcile/status.py,sha256=cY4IJFXemhxptRJqR4qaaOWqei9e4jgLXuVSGajMsjg,544
110
110
  reconcile/status_board.py,sha256=nA74_133jukxVShjPKJpkXOA3vggDTTEhYTegoXbN1M,8632
@@ -794,8 +794,8 @@ tools/saas_metrics_exporter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
794
794
  tools/saas_metrics_exporter/main.py,sha256=piocx6meMdJxoxeNz52gQGUjt5n7Fma4kgqYamszPrM,3180
795
795
  tools/saas_metrics_exporter/commit_distance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
796
796
  tools/saas_metrics_exporter/commit_distance/channel.py,sha256=XEAh3eL8TmgMe7V2BsyxuXYWgvBBVdSJETd6Ec7cI04,2171
797
- tools/saas_metrics_exporter/commit_distance/commit_distance.py,sha256=snkcHKS7zxSIomS7psEQ13efN-j9MxKZHe0nLw55dAk,4042
798
- tools/saas_metrics_exporter/commit_distance/metrics.py,sha256=rQTcinrv3uGLnHFumS37NN3QyVv1z6HGqy8MtfOwcxM,544
797
+ tools/saas_metrics_exporter/commit_distance/commit_distance.py,sha256=nyw9N1ESrcxweWfESI-zlldDdSQGLtiuC6x7DXIjtDw,3074
798
+ tools/saas_metrics_exporter/commit_distance/metrics.py,sha256=5-y6n-sGACAS3eJ5ndY-2BFxcd0fxLfhvZmmBHu4JuA,426
799
799
  tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
800
800
  tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
801
801
  tools/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -804,8 +804,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
804
804
  tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jrss,4941
805
805
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
806
806
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
807
- qontract_reconcile-0.10.1rc806.dist-info/METADATA,sha256=n5MHe0IaW3GE0yf5Yy3vSdT-jrs4U3al9qbv4LUPWQ8,2314
808
- qontract_reconcile-0.10.1rc806.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
809
- qontract_reconcile-0.10.1rc806.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
810
- qontract_reconcile-0.10.1rc806.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
811
- qontract_reconcile-0.10.1rc806.dist-info/RECORD,,
807
+ qontract_reconcile-0.10.1rc808.dist-info/METADATA,sha256=avC3f2n3tg5yBABcDSjLjyLvPd7Axtxg7AYNThYdak4,2314
808
+ qontract_reconcile-0.10.1rc808.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
809
+ qontract_reconcile-0.10.1rc808.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
810
+ qontract_reconcile-0.10.1rc808.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
811
+ qontract_reconcile-0.10.1rc808.dist-info/RECORD,,
reconcile/cli.py CHANGED
@@ -1200,8 +1200,18 @@ def openshift_upgrade_watcher(ctx, thread_pool_size, internal, use_jump_host):
1200
1200
  @integration.command(short_help="Manage Slack User Groups (channels and users).")
1201
1201
  @workspace_name
1202
1202
  @usergroup_name
1203
+ @enable_extended_early_exit
1204
+ @extended_early_exit_cache_ttl_seconds
1205
+ @log_cached_log_output
1203
1206
  @click.pass_context
1204
- def slack_usergroups(ctx, workspace_name, usergroup_name):
1207
+ def slack_usergroups(
1208
+ ctx,
1209
+ workspace_name,
1210
+ usergroup_name,
1211
+ enable_extended_early_exit,
1212
+ extended_early_exit_cache_ttl_seconds,
1213
+ log_cached_log_output,
1214
+ ):
1205
1215
  import reconcile.slack_usergroups
1206
1216
 
1207
1217
  run_integration(
@@ -1209,6 +1219,9 @@ def slack_usergroups(ctx, workspace_name, usergroup_name):
1209
1219
  ctx.obj,
1210
1220
  workspace_name,
1211
1221
  usergroup_name,
1222
+ enable_extended_early_exit,
1223
+ extended_early_exit_cache_ttl_seconds,
1224
+ log_cached_log_output,
1212
1225
  )
1213
1226
 
1214
1227
 
@@ -9,6 +9,7 @@ from typing import (
9
9
  Any,
10
10
  Optional,
11
11
  Sequence,
12
+ TypedDict,
12
13
  Union,
13
14
  )
14
15
  from urllib.parse import urlparse
@@ -47,6 +48,10 @@ from reconcile.utils.exceptions import (
47
48
  AppInterfaceSettingsError,
48
49
  UnknownError,
49
50
  )
51
+ from reconcile.utils.extended_early_exit import (
52
+ ExtendedEarlyExitRunnerResult,
53
+ extended_early_exit_run,
54
+ )
50
55
  from reconcile.utils.github_api import GithubRepositoryApi
51
56
  from reconcile.utils.gitlab_api import GitLabApi
52
57
  from reconcile.utils.pagerduty_api import (
@@ -67,6 +72,8 @@ from reconcile.utils.slack_api import (
67
72
 
68
73
  DATE_FORMAT = "%Y-%m-%d %H:%M"
69
74
  QONTRACT_INTEGRATION = "slack-usergroups"
75
+ INTEGRATION_VERSION = "0.1.0"
76
+
70
77
  error_occurred = False
71
78
 
72
79
 
@@ -511,14 +518,14 @@ def _create_usergroups(
511
518
  desired_ug_state: State,
512
519
  slack_client: SlackApi,
513
520
  dry_run: bool = True,
514
- ) -> None:
521
+ ) -> int:
515
522
  """Create Slack usergroups."""
516
523
  global error_occurred # noqa: PLW0603
517
524
  if current_ug_state:
518
525
  logging.debug(
519
526
  f"[{desired_ug_state.workspace}] Usergroup exists and will not be created {desired_ug_state.usergroup}"
520
527
  )
521
- return
528
+ return 0
522
529
 
523
530
  logging.info([
524
531
  "create_usergroup",
@@ -531,6 +538,7 @@ def _create_usergroups(
531
538
  except SlackApiError as error:
532
539
  logging.error(error)
533
540
  error_occurred = True
541
+ return 1
534
542
 
535
543
 
536
544
  def _update_usergroup_users_from_state(
@@ -538,14 +546,14 @@ def _update_usergroup_users_from_state(
538
546
  desired_ug_state: State,
539
547
  slack_client: SlackApi,
540
548
  dry_run: bool = True,
541
- ) -> None:
549
+ ) -> int:
542
550
  """Update the users in a Slack usergroup."""
543
551
  global error_occurred # noqa: PLW0603
544
552
  if current_ug_state.user_names == desired_ug_state.user_names:
545
553
  logging.debug(
546
554
  f"No usergroup user changes detected for {desired_ug_state.usergroup}"
547
555
  )
548
- return
556
+ return 0
549
557
 
550
558
  slack_user_objects = [
551
559
  SlackObject(pk=pk, name=name)
@@ -559,7 +567,7 @@ def _update_usergroup_users_from_state(
559
567
  f"Following usernames are incorrect for usergroup {desired_ug_state.usergroup} and could not be matched with slack users {desired_ug_state.user_names - set(s.name for s in slack_user_objects)}"
560
568
  )
561
569
  error_occurred = True
562
- return
570
+ return 0
563
571
 
564
572
  for user in desired_ug_state.user_names - current_ug_state.user_names:
565
573
  logging.info([
@@ -584,7 +592,7 @@ def _update_usergroup_users_from_state(
584
592
  logging.info(
585
593
  f"Usergroup {desired_ug_state.usergroup} does not exist yet. Skipping for now."
586
594
  )
587
- return
595
+ return 0
588
596
  slack_client.update_usergroup_users(
589
597
  id=ugid,
590
598
  users_list=sorted([s.pk for s in slack_user_objects]),
@@ -596,6 +604,7 @@ def _update_usergroup_users_from_state(
596
604
  # sensitive updates.
597
605
  logging.error(error)
598
606
  error_occurred = True
607
+ return 1
599
608
 
600
609
 
601
610
  def _update_usergroup_from_state(
@@ -603,9 +612,10 @@ def _update_usergroup_from_state(
603
612
  desired_ug_state: State,
604
613
  slack_client: SlackApi,
605
614
  dry_run: bool = True,
606
- ) -> None:
615
+ ) -> int:
607
616
  """Update a Slack usergroup."""
608
617
  global error_occurred # noqa: PLW0603
618
+ change_detected = False
609
619
  if (
610
620
  current_ug_state.channel_names == desired_ug_state.channel_names
611
621
  and current_ug_state.description == desired_ug_state.description
@@ -613,7 +623,7 @@ def _update_usergroup_from_state(
613
623
  logging.debug(
614
624
  f"No usergroup channel/description changes detected for {desired_ug_state.usergroup}",
615
625
  )
616
- return
626
+ return 0
617
627
 
618
628
  slack_channel_objects = [
619
629
  SlackObject(pk=pk, name=name)
@@ -635,6 +645,7 @@ def _update_usergroup_from_state(
635
645
  # return
636
646
 
637
647
  for channel in desired_channel_names - current_ug_state.channel_names:
648
+ change_detected = True
638
649
  logging.info([
639
650
  "add_channel_to_usergroup",
640
651
  desired_ug_state.workspace,
@@ -643,6 +654,7 @@ def _update_usergroup_from_state(
643
654
  ])
644
655
 
645
656
  for channel in current_ug_state.channel_names - desired_channel_names:
657
+ change_detected = True
646
658
  logging.info([
647
659
  "del_channel_from_usergroup",
648
660
  desired_ug_state.workspace,
@@ -651,6 +663,7 @@ def _update_usergroup_from_state(
651
663
  ])
652
664
 
653
665
  if current_ug_state.description != desired_ug_state.description:
666
+ change_detected = True
654
667
  logging.info([
655
668
  "update_usergroup_description",
656
669
  desired_ug_state.workspace,
@@ -658,14 +671,14 @@ def _update_usergroup_from_state(
658
671
  desired_ug_state.description,
659
672
  ])
660
673
 
661
- if not dry_run:
674
+ if not dry_run and change_detected:
662
675
  try:
663
676
  ugid = slack_client.get_usergroup_id(desired_ug_state.usergroup)
664
677
  if not ugid:
665
678
  logging.info(
666
679
  f"Usergroup {desired_ug_state.usergroup} does not exist yet. Skipping for now."
667
680
  )
668
- return
681
+ return 0
669
682
  slack_client.update_usergroup(
670
683
  id=ugid,
671
684
  channels_list=sorted(s.pk for s in slack_channel_objects),
@@ -674,6 +687,8 @@ def _update_usergroup_from_state(
674
687
  except SlackApiError as error:
675
688
  logging.error(error)
676
689
  error_occurred = True
690
+ return 1
691
+ return 0
677
692
 
678
693
 
679
694
  def act(
@@ -681,35 +696,37 @@ def act(
681
696
  desired_state: SlackState,
682
697
  slack_map: SlackMap,
683
698
  dry_run: bool = True,
684
- ) -> None:
699
+ ) -> int:
685
700
  """Reconcile the differences between the desired and current state for
686
701
  Slack usergroups."""
702
+ apply_count = 0
687
703
  for workspace, desired_ws_state in desired_state.items():
688
704
  for usergroup, desired_ug_state in desired_ws_state.items():
689
705
  current_ug_state: State = current_state.get(workspace, {}).get(
690
706
  usergroup, State()
691
707
  )
692
708
 
693
- _create_usergroups(
709
+ apply_count += _create_usergroups(
694
710
  current_ug_state,
695
711
  desired_ug_state,
696
712
  slack_client=slack_map[workspace].slack,
697
713
  dry_run=dry_run,
698
714
  )
699
715
 
700
- _update_usergroup_users_from_state(
716
+ apply_count += _update_usergroup_users_from_state(
701
717
  current_ug_state,
702
718
  desired_ug_state,
703
719
  slack_client=slack_map[workspace].slack,
704
720
  dry_run=dry_run,
705
721
  )
706
722
 
707
- _update_usergroup_from_state(
723
+ apply_count += _update_usergroup_from_state(
708
724
  current_ug_state,
709
725
  desired_ug_state,
710
726
  slack_client=slack_map[workspace].slack,
711
727
  dry_run=dry_run,
712
728
  )
729
+ return apply_count
713
730
 
714
731
 
715
732
  def get_permissions(query_func: Callable) -> list[PermissionSlackUsergroupV1]:
@@ -731,10 +748,22 @@ def get_clusters(query_func: Callable) -> list[ClusterV1]:
731
748
  return clusters_query(query_func=query_func).clusters or []
732
749
 
733
750
 
751
+ class RunnerParams(TypedDict):
752
+ dry_run: bool
753
+ slack_map: SlackMap
754
+ desired_state: SlackState
755
+ clusters: list[ClusterV1]
756
+ workspace_name: Optional[str]
757
+ usergroup_name: Optional[str]
758
+
759
+
734
760
  def run(
735
761
  dry_run: bool,
736
762
  workspace_name: Optional[str] = None,
737
763
  usergroup_name: Optional[str] = None,
764
+ enable_extended_early_exit: bool = False,
765
+ extended_early_exit_cache_ttl_seconds: int = 3600,
766
+ log_cached_log_output: bool = False,
738
767
  ) -> None:
739
768
  global error_occurred # noqa: PLW0603
740
769
  error_occurred = False
@@ -777,6 +806,45 @@ def run(
777
806
  # merge the two desired states recursively
778
807
  desired_state = deep_update(desired_state, desired_state_cluster_usergroups)
779
808
 
809
+ runner_params: RunnerParams = dict(
810
+ dry_run=dry_run,
811
+ slack_map=slack_map,
812
+ desired_state=desired_state,
813
+ clusters=clusters,
814
+ workspace_name=workspace_name,
815
+ usergroup_name=usergroup_name,
816
+ )
817
+
818
+ if enable_extended_early_exit:
819
+ extended_early_exit_run(
820
+ QONTRACT_INTEGRATION,
821
+ INTEGRATION_VERSION,
822
+ dry_run,
823
+ desired_state,
824
+ "",
825
+ extended_early_exit_cache_ttl_seconds,
826
+ logging.getLogger(),
827
+ runner,
828
+ runner_params=runner_params,
829
+ log_cached_log_output=log_cached_log_output,
830
+ secret_reader=secret_reader,
831
+ )
832
+ else:
833
+ runner(**runner_params)
834
+
835
+ if error_occurred:
836
+ logging.error("Error(s) occurred.")
837
+ sys.exit(1)
838
+
839
+
840
+ def runner(
841
+ dry_run: bool,
842
+ slack_map: SlackMap,
843
+ desired_state: SlackState,
844
+ clusters: list[ClusterV1],
845
+ workspace_name: Optional[str] = None,
846
+ usergroup_name: Optional[str] = None,
847
+ ) -> ExtendedEarlyExitRunnerResult:
780
848
  current_state = get_current_state(
781
849
  slack_map=slack_map,
782
850
  desired_workspace_name=workspace_name,
@@ -787,15 +855,13 @@ def run(
787
855
  if integration_is_enabled(QONTRACT_INTEGRATION, cluster)
788
856
  ],
789
857
  )
790
- act(
858
+ apply_count = act(
791
859
  current_state=current_state,
792
860
  desired_state=desired_state,
793
861
  slack_map=slack_map,
794
862
  dry_run=dry_run,
795
863
  )
796
- if error_occurred:
797
- logging.error("Error(s) occurred.")
798
- sys.exit(1)
864
+ return ExtendedEarlyExitRunnerResult(payload={}, applied_count=apply_count)
799
865
 
800
866
 
801
867
  def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
@@ -7,124 +7,97 @@ from reconcile.typed_queries.saas_files import SaasFile
7
7
  from reconcile.utils.secret_reader import HasSecret
8
8
  from reconcile.utils.vcs import VCS
9
9
  from tools.saas_metrics_exporter.commit_distance.channel import (
10
- Channel,
11
10
  SaasTarget,
12
11
  build_channels,
13
12
  )
14
13
  from tools.saas_metrics_exporter.commit_distance.metrics import SaasCommitDistanceGauge
15
14
 
16
15
 
17
- @dataclass
18
- class Distance:
19
- publisher: SaasTarget
20
- subscriber: SaasTarget
21
- channel: Channel
22
- distance: int = 0
23
-
24
-
25
16
  @dataclass
26
17
  class CommitDistanceMetric:
27
18
  value: float
28
19
  metric: SaasCommitDistanceGauge
29
20
 
30
21
 
31
- @dataclass
32
- class ThreadData:
22
+ @dataclass(frozen=True)
23
+ class DistanceKey:
33
24
  repo_url: str
34
25
  auth_code: HasSecret | None
35
26
  ref_from: str
36
27
  ref_to: str
37
- distance: int = 0
38
-
39
- def __hash__(self) -> int:
40
- return hash((self.repo_url, self.ref_from, self.ref_to))
41
28
 
42
29
 
43
30
  class CommitDistanceFetcher:
44
31
  def __init__(self, vcs: VCS):
45
32
  self._vcs = vcs
46
33
 
47
- def _data_key(self, repo_url: str, ref_from: str, ref_to: str) -> str:
48
- return f"{repo_url}/{ref_from}/{ref_to}"
49
-
50
- def _calculate_commit_distance(self, data: ThreadData) -> None:
51
- if data.ref_from == data.ref_to:
52
- data.distance = 0
53
- return
34
+ def _calculate_commit_distance(self, key: DistanceKey) -> tuple[DistanceKey, int]:
35
+ if key.ref_from == key.ref_to:
36
+ return key, 0
54
37
 
55
38
  commits = self._vcs.get_commits_between(
56
- repo_url=data.repo_url,
57
- auth_code=data.auth_code,
58
- commit_from=data.ref_from,
59
- commit_to=data.ref_to,
39
+ repo_url=key.repo_url,
40
+ auth_code=key.auth_code,
41
+ commit_from=key.ref_from,
42
+ commit_to=key.ref_to,
43
+ )
44
+ return key, len(commits)
45
+
46
+ @staticmethod
47
+ def _build_distance_key(
48
+ publisher: SaasTarget, subscriber: SaasTarget
49
+ ) -> DistanceKey:
50
+ return DistanceKey(
51
+ repo_url=publisher.repo_url,
52
+ auth_code=publisher.auth_code,
53
+ ref_from=subscriber.ref,
54
+ ref_to=publisher.ref,
60
55
  )
61
- data.distance = len(commits)
62
-
63
- def _populate_distances(
64
- self, distances: Iterable[Distance], thread_data: Iterable[ThreadData]
65
- ) -> None:
66
- m = {
67
- self._data_key(
68
- repo_url=d.repo_url, ref_from=d.ref_from, ref_to=d.ref_to
69
- ): d.distance
70
- for d in thread_data
71
- }
72
- for distance in distances:
73
- distance.distance = m[
74
- self._data_key(
75
- repo_url=distance.publisher.repo_url,
76
- ref_from=distance.subscriber.ref,
77
- ref_to=distance.publisher.ref,
78
- )
79
- ]
80
56
 
81
57
  def fetch(
82
- self, saas_files: Iterable[SaasFile], thread_pool_size: int
58
+ self,
59
+ saas_files: Iterable[SaasFile],
60
+ thread_pool_size: int,
83
61
  ) -> list[CommitDistanceMetric]:
84
62
  channels = build_channels(saas_files=saas_files)
85
- distances: list[Distance] = []
86
- thread_data: set[ThreadData] = set()
87
-
88
- for channel in channels:
89
- for subscriber in channel.subscribers:
90
- for publisher in channel.publishers:
91
- thread_data.add(
92
- ThreadData(
93
- repo_url=publisher.repo_url,
94
- auth_code=publisher.auth_code,
95
- ref_from=subscriber.ref,
96
- ref_to=publisher.ref,
97
- )
98
- )
99
- distances.append(
100
- Distance(
101
- publisher=publisher,
102
- subscriber=subscriber,
103
- channel=channel,
104
- )
105
- )
106
63
 
107
- threaded.run(
108
- self._calculate_commit_distance,
109
- thread_data,
110
- thread_pool_size=thread_pool_size,
111
- )
64
+ distance_keys = {
65
+ self._build_distance_key(publisher=publisher, subscriber=subscriber)
66
+ for channel in channels
67
+ for subscriber in channel.subscribers
68
+ for publisher in channel.publishers
69
+ }
112
70
 
113
- self._populate_distances(distances=distances, thread_data=thread_data)
71
+ distance_by_key = dict(
72
+ threaded.run(
73
+ self._calculate_commit_distance,
74
+ distance_keys,
75
+ thread_pool_size=thread_pool_size,
76
+ )
77
+ )
114
78
 
115
79
  commit_distance_metrics = [
116
80
  CommitDistanceMetric(
117
- value=float(distance.distance),
81
+ value=float(
82
+ distance_by_key[
83
+ self._build_distance_key(
84
+ publisher=publisher,
85
+ subscriber=subscriber,
86
+ )
87
+ ]
88
+ ),
118
89
  metric=SaasCommitDistanceGauge(
119
- channel=distance.channel.name,
120
- app=distance.publisher.app_name,
121
- publisher=distance.publisher.target_name,
122
- publisher_namespace=distance.publisher.namespace_name,
123
- subscriber=distance.subscriber.target_name,
124
- subscriber_namespace=distance.subscriber.namespace_name,
90
+ channel=channel.name,
91
+ app=publisher.app_name,
92
+ publisher=publisher.target_name,
93
+ publisher_namespace=publisher.namespace_name,
94
+ subscriber=subscriber.target_name,
95
+ subscriber_namespace=subscriber.namespace_name,
125
96
  ),
126
97
  )
127
- for distance in distances
98
+ for channel in channels
99
+ for subscriber in channel.subscribers
100
+ for publisher in channel.publishers
128
101
  ]
129
102
 
130
103
  return commit_distance_metrics
@@ -1,19 +1,12 @@
1
- from pydantic import BaseModel
2
-
3
1
  from reconcile.utils.metrics import (
4
2
  GaugeMetric,
5
3
  )
6
4
 
7
5
 
8
- class SaasBaseMetric(BaseModel):
9
- "Base class for Saas metrics"
10
-
11
- integration: str = "saas_metrics_exporter"
12
-
13
-
14
- class SaasCommitDistanceGauge(SaasBaseMetric, GaugeMetric):
6
+ class SaasCommitDistanceGauge(GaugeMetric):
15
7
  "Gauge for the commit distance between saas targets in a channel"
16
8
 
9
+ integration: str = "saas_metrics_exporter"
17
10
  channel: str
18
11
  publisher: str
19
12
  publisher_namespace: str