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.
- {qontract_reconcile-0.10.1rc806.dist-info → qontract_reconcile-0.10.1rc808.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc806.dist-info → qontract_reconcile-0.10.1rc808.dist-info}/RECORD +9 -9
- reconcile/cli.py +14 -1
- reconcile/slack_usergroups.py +84 -18
- tools/saas_metrics_exporter/commit_distance/commit_distance.py +54 -81
- tools/saas_metrics_exporter/commit_distance/metrics.py +2 -9
- {qontract_reconcile-0.10.1rc806.dist-info → qontract_reconcile-0.10.1rc808.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc806.dist-info → qontract_reconcile-0.10.1rc808.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc806.dist-info → qontract_reconcile-0.10.1rc808.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc806.dist-info → qontract_reconcile-0.10.1rc808.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.
|
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
|
{qontract_reconcile-0.10.1rc806.dist-info → qontract_reconcile-0.10.1rc808.dist-info}/RECORD
RENAMED
@@ -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=
|
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=
|
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=
|
798
|
-
tools/saas_metrics_exporter/commit_distance/metrics.py,sha256=
|
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.
|
808
|
-
qontract_reconcile-0.10.
|
809
|
-
qontract_reconcile-0.10.
|
810
|
-
qontract_reconcile-0.10.
|
811
|
-
qontract_reconcile-0.10.
|
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(
|
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
|
|
reconcile/slack_usergroups.py
CHANGED
@@ -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
|
-
) ->
|
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
|
-
) ->
|
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
|
-
) ->
|
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
|
-
) ->
|
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
|
-
|
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
|
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
|
48
|
-
|
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=
|
57
|
-
auth_code=
|
58
|
-
commit_from=
|
59
|
-
commit_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,
|
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
|
-
|
108
|
-
self.
|
109
|
-
|
110
|
-
|
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
|
-
|
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(
|
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=
|
120
|
-
app=
|
121
|
-
publisher=
|
122
|
-
publisher_namespace=
|
123
|
-
subscriber=
|
124
|
-
subscriber_namespace=
|
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
|
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
|
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
|
File without changes
|
File without changes
|
{qontract_reconcile-0.10.1rc806.dist-info → qontract_reconcile-0.10.1rc808.dist-info}/top_level.txt
RENAMED
File without changes
|