qontract-reconcile 0.10.1rc757__py3-none-any.whl → 0.10.1rc759__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.1rc757
3
+ Version: 0.10.1rc759
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
@@ -105,7 +105,7 @@ reconcile/service_dependencies.py,sha256=PMKP9vc6oL-78rzyF_RE8DzLSQMSqN8vCqt9sWp
105
105
  reconcile/signalfx_endpoint_monitoring.py,sha256=D1m8iq0EAKie0OD59FOcVCtpWWZ7xlo6lwBS9urwMIk,2894
106
106
  reconcile/slack_base.py,sha256=K3fSYx46G1djoPb07_C9j6ChhMCt5LgV5l6v2TFkNZk,3479
107
107
  reconcile/slack_usergroups.py,sha256=XC7bYHP322EFWrEaR4Orw_sOoMFmuV3o08OC0UE4xLQ,27592
108
- reconcile/sql_query.py,sha256=zZkihfI-f0JjMez9A83HGTlVwqqbkP8lLjRg-z7sOUU,25878
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
111
111
  reconcile/terraform_aws_route53.py,sha256=R8eZHlvP368nvtmLd_cMSK3RGxD7jso9qE7NP92iniU,9986
@@ -122,7 +122,7 @@ reconcile/vpc_peerings_validator.py,sha256=Kv22HJVlTW9l9GB2eXwjPWqdDbr_VuvQBNPtt
122
122
  reconcile/aus/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
123
123
  reconcile/aus/advanced_upgrade_service.py,sha256=MPqcWpq1QeYzBsB8rtTlo102h_cR_q83oOYtWAncuAk,22391
124
124
  reconcile/aus/aus_label_source.py,sha256=qoP8Fgxuu1tCuhG6ixCWve7Ll-KD6a79E2uLAmC0ifw,4184
125
- reconcile/aus/base.py,sha256=RqFUwH2xiWFN1U6plp-UG77iFkK60b8YKODsD4YWWyc,49880
125
+ reconcile/aus/base.py,sha256=89tNKGZAsfCiYivF-oU15nois91eP4b8tRRT45zaY9M,49886
126
126
  reconcile/aus/cluster_version_data.py,sha256=j4UyEBi5mQuvPq5Lo7a_L_0blxvH790wJV07uAiikFU,7126
127
127
  reconcile/aus/healthchecks.py,sha256=S8_KPn_zFiOo_wf5XlVmz-I3tUDYAim3EGSqiSPMvLQ,2707
128
128
  reconcile/aus/metrics.py,sha256=nKT4m2zGT-QOMR0c-z-npVNKWsNMubzdffpU_f9n4II,3927
@@ -437,7 +437,7 @@ reconcile/terraform_init/integration.py,sha256=xcFKTc_or3xB3kE_I3OECNkkgbwALIwwd
437
437
  reconcile/terraform_init/merge_request.py,sha256=3CYtgSd7Q9zjKg4wsDz437EPCRfGeZZ8fZ0Y-ChKXJY,1475
438
438
  reconcile/terraform_init/merge_request_manager.py,sha256=fMcT6hbdEF3nFATJpvr8BedvQHq_MzFkgVJSloBNwOQ,3101
439
439
  reconcile/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
440
- reconcile/test/conftest.py,sha256=rQousYrxUz-EwAIbsYO6bIwR1B4CrOz9y_zaUVo2lfI,4466
440
+ reconcile/test/conftest.py,sha256=0pO4UxFeBALKbL9gwemyap0VkbPR8n5TtZbf5c9pSv0,4303
441
441
  reconcile/test/fixtures.py,sha256=9SDWAUlSd1rCx7z3GhULHcpr-I6FyCsXxaFAZIqYQsQ,591
442
442
  reconcile/test/test_acs_notifiers.py,sha256=xf3WL6q6V7KQdTVSx6YI-pa4yzOX3mkvIJomgPUc3Mw,12746
443
443
  reconcile/test/test_acs_policies.py,sha256=8pwnXpAO-0OI-6oubjf_oPPlpZjVldeZfJJ9uhsNMWM,17579
@@ -455,7 +455,7 @@ reconcile/test/test_cli.py,sha256=qx_iBwh4Z-YkK3sbjK1wEziPTgn060EN-baf9DNvR3k,10
455
455
  reconcile/test/test_closedbox_endpoint_monitoring.py,sha256=isMHYwRWMFARU2nbJgbl69kD6H0eA86noCM4MPVI1fo,7151
456
456
  reconcile/test/test_dashdotdb_dora.py,sha256=MfHGAsX2eSQSvBVt9_1Sah3aQKNJBXA9Iu86X0NWD6c,7705
457
457
  reconcile/test/test_database_access_manager.py,sha256=-9fYo8wMNhbJUTK_bd7g_fS5zYsAlqQ0rBDDYBMZvZQ,19595
458
- reconcile/test/test_deadmanssnitch.py,sha256=qtn1zwWgIQYw5JULLPvDLaj0GWiecYnvky0HcuETjdo,9843
458
+ reconcile/test/test_deadmanssnitch.py,sha256=YAf8wlZoEC60Ul7UA6Y6XqwnZ1yqf07J15ABqeLpqW4,9835
459
459
  reconcile/test/test_gabi_authorized_users.py,sha256=6XnV5Q9inxP81ktGMVKyWucjBTUj8Imy2L0HG3YHyUE,2496
460
460
  reconcile/test/test_gcr_mirror.py,sha256=A0y8auKZzr62-mGoxSQ__JnN0-ijZUltzjwR5miBgso,490
461
461
  reconcile/test/test_github_org.py,sha256=j3KeB4OnSln1gm2hidce49xdMru-j75NS3cM-AEgzZc,4511
@@ -473,7 +473,7 @@ reconcile/test/test_make.py,sha256=zTdjgq-3idFlec_0qJenk9wWw0QMLvSpJfPsptXmync,6
473
473
  reconcile/test/test_ocm_additional_routers.py,sha256=dtbpUnD5un6Q3VoLbuFRb_njmt5SSCnBzvSSBcO_Xxs,4248
474
474
  reconcile/test/test_ocm_clusters.py,sha256=aBzL3eW_g3bTP2wmKE1hr8-f33OOhBiKDxJ0fNxWGCQ,23888
475
475
  reconcile/test/test_ocm_clusters_manifest_updates.py,sha256=jFRVfc5jby1kI2x_gT6wcqPPgkav1et9wZH6JqQbNSY,3278
476
- reconcile/test/test_ocm_machine_pools.py,sha256=3qo6t2Jfr1Wee0NUacyLTDmatp0o7CUNpkVOpHiOiGk,29737
476
+ reconcile/test/test_ocm_machine_pools.py,sha256=X4S5lksvljAgCMSW7fDGguc6JMtNQ0bO2WAoLC2AAJw,29737
477
477
  reconcile/test/test_ocm_update_recommended_version.py,sha256=iA4BVirTGVXlwcOyeR52IuNO81X_8NR6ZNd7ZFE7igs,4328
478
478
  reconcile/test/test_ocm_upgrade_scheduler_org_updater.py,sha256=V91g2XQMa2nvKwkLVWkiPwNL6pMQE16s4jO0oXJ6wdk,4330
479
479
  reconcile/test/test_openshift_base.py,sha256=YgTKcLmzmt9oR12s_022LAp9qr1R_CBOppYwoknspzE,33868
@@ -501,7 +501,7 @@ reconcile/test/test_secret_reader.py,sha256=kz7nzcPjvA08cytnvcA_PMA98AEyqJWsESkY
501
501
  reconcile/test/test_slack_base.py,sha256=gpbWOLNxMMX6fyAbs1JakhLTnwfedb3f7WpUae4tQZE,5060
502
502
  reconcile/test/test_slack_usergroups.py,sha256=UO-OzqbGMSpNsyddu2TbWOzSiVze6Bq95Ph1QIJqLWY,23990
503
503
  reconcile/test/test_sql_query.py,sha256=rC-lf1_isT9i2ZIV9W0hkUkLi2oBIjZMRMhk-6mV-34,11029
504
- reconcile/test/test_status_board.py,sha256=WdAq4pFoWWqcOcfgMzssZD3xfvT1QLrEHJqUARldtvA,7875
504
+ reconcile/test/test_status_board.py,sha256=go3YSWo03OLIdK95SuiDJa1Nqk-eN_9QtS7dfmu9__8,7875
505
505
  reconcile/test/test_terraform_aws_route53.py,sha256=xHggb8K1P76OyCfFcogbkmyKle-NlUylcbDnuv3IqvY,771
506
506
  reconcile/test/test_terraform_cloudflare_dns.py,sha256=aQTXX8Vr4h9aWvJZTnpZEhMGYoBpT2d45ZxU_ECIQ6o,3425
507
507
  reconcile/test/test_terraform_cloudflare_resources.py,sha256=NK_uktyWihkQ3gMN4bCaKerpi43CXAVYGIKTfcz05rY,13550
@@ -513,7 +513,7 @@ reconcile/test/test_terraform_users.py,sha256=XOAfGvITCJPI1LTlISmHbA4ONMQMkxYUMT
513
513
  reconcile/test/test_terraform_vpc_peerings.py,sha256=ubcsKh0TrUIwuI1-W3ETIgzsFvzAyeoFmEJFC-IK6JY,20538
514
514
  reconcile/test/test_terraform_vpc_peerings_build_desired_state.py,sha256=DAfpb12I0PlqnuVUHK2vh4LH4d1OylT3H2GE_3TGZZI,47852
515
515
  reconcile/test/test_three_way_diff_strategy.py,sha256=2fjEqE2w4pIzKq18PRcADTSe01aGwsZfMGloU8xfNaE,3346
516
- reconcile/test/test_unleash.py,sha256=c1s_FRAZrAzzd3FbZrzHYjJzHELhoxPHBZnEzqsfMQg,6416
516
+ reconcile/test/test_unleash.py,sha256=krPgOVmwTE6lb773040Ely9BPbNYOeOIY0_8BK72dgo,6690
517
517
  reconcile/test/test_utils_jinja2.py,sha256=TpzQlpFnLGzNEZp5WOh0o7AuBiGEktqO4MuwiiJW2YY,3895
518
518
  reconcile/test/test_vault_replication.py,sha256=wlc4jm9f8P641UvvxIFFFc5_unJysNkOVrKJscjhQr0,16867
519
519
  reconcile/test/test_vault_utils.py,sha256=vbJnc89XAuE07qbTuWxHM5o9F6R9SO5aHXA38fwxT7A,1122
@@ -597,7 +597,7 @@ reconcile/utils/binary.py,sha256=EsOGg82Y2QJh91SGJE0tYpBKqU0iaaagQVoYONBtQn8,235
597
597
  reconcile/utils/config.py,sha256=aId5zrPjM_84u_T4yTRE_Psu3zo5-5_JCR6_7Wgv5UQ,990
598
598
  reconcile/utils/constants.py,sha256=pOUd97bqZdsAu5RWJ8NUs9cwCY7K9y0eW9VVeJ4fZIU,138
599
599
  reconcile/utils/data_structures.py,sha256=VyKfnlNJTiRvZKNpfgIrjESQ2YgmEpWuPQXT14WA1vI,311
600
- reconcile/utils/deadmanssnitch_api.py,sha256=hkfbfbRAhzLpI39o6Du7FZKVtf4UVJ1OljOQNUkmODM,2478
600
+ reconcile/utils/deadmanssnitch_api.py,sha256=OWwkqZxjLRNNfFrfZt-zJ4H1hm4OHg5EZ6lP55APOZc,2493
601
601
  reconcile/utils/defer.py,sha256=SniUsbgOEs9Pa8JkecLu0F94O63yQPByKXaElDYe0FI,377
602
602
  reconcile/utils/differ.py,sha256=kJmUp9ZffFPSUEviaAw3s9c92ErwRJeHaRexGPai7wA,7643
603
603
  reconcile/utils/disabled_integrations.py,sha256=avdDsFyl_LdTsrPVzlcIhWzT_V4C4MXw1ZC__aOtluE,1126
@@ -651,12 +651,12 @@ reconcile/utils/promtool.py,sha256=kT2rFZSBaRqW7SSHAuYzGZzQxM5Dzk8KW1NnEUYZU_s,2
651
651
  reconcile/utils/quay_api.py,sha256=EuOegpb-7ntEjkKLFwM2Oo4Nw7SyFtmyl3sQ9aXMtrM,8152
652
652
  reconcile/utils/raw_github_api.py,sha256=ZHC-SZuAyRe1zaMoOU7Krt1-zecDxENd9c_NzQYqK9g,2968
653
653
  reconcile/utils/repo_owners.py,sha256=j-pUjc9PuDzq7KpjNLpnhqfU8tUG4nj2WMhFp4ick7g,6629
654
- reconcile/utils/rest_api_base.py,sha256=uXLdXocNmRCxJsYFWOdUNLaTEu-dcxMLJg_CwRefETE,3970
654
+ reconcile/utils/rest_api_base.py,sha256=X5o4idyRCDzwnF5xFwmjyoaHmM1tXSZnykTA54Z7D2Q,4006
655
655
  reconcile/utils/ruamel.py,sha256=FzL4_L0FnMOUZmgThrZSMJs5MTdXwiy-E9MZWfk8bh8,397
656
656
  reconcile/utils/secret_reader.py,sha256=2DeYAAQFjUULEKlLw3UDAUoND6gbqvCh9uKPtlc-0us,10403
657
657
  reconcile/utils/semver_helper.py,sha256=-WfPOMSA2v1h7hT3PwVf-Htg7wOsoKlQC1JdmDX2Ars,1268
658
658
  reconcile/utils/sharding.py,sha256=gkYf0lD3IUKQPEmdRJZ70mdDT1c9qWjbdP7evRsUis4,839
659
- reconcile/utils/slack_api.py,sha256=OPmzU6L9rJx2XXDlZkMlxLjOWu17yC-fVCoUItzQrXw,16295
659
+ reconcile/utils/slack_api.py,sha256=C-VThgYRtrRWraq9ZE6hEf1bXrwzRDCDK0uRw3DP6ew,16425
660
660
  reconcile/utils/smtp_client.py,sha256=gJNbBQJpAt5PX4t_TaeNHsXM8vt50bFgndml6yK2b5o,2800
661
661
  reconcile/utils/sqs_gateway.py,sha256=gFl9DM4DmGnptuxTOe4lS3YTyE80eSAvK42ljS8h4dA,2287
662
662
  reconcile/utils/state.py,sha256=FK8NLT1xyumuXpYRm0Nk6pWpOE_U6-NovGn6zKCw8vw,16298
@@ -721,7 +721,7 @@ reconcile/utils/mr/ocm_upgrade_scheduler_org_updates.py,sha256=RzEKRT_BhvB2ud9py
721
721
  reconcile/utils/mr/user_maintenance.py,sha256=cHPBn8zrReWLHalyk-EFdkFJe9zjVjRoZhT4t2zZfGE,3956
722
722
  reconcile/utils/ocm/__init__.py,sha256=xv7CJp7K9LCQfa4gL_W0MMCOD1P4qOy8t5aZj1xXNUE,808
723
723
  reconcile/utils/ocm/addons.py,sha256=IHlqOO12TAdYwwU6Oedz3ussF1kELj9EI5GxPP6LKi8,7376
724
- reconcile/utils/ocm/base.py,sha256=sdcINGBy1FlotY0MZuVC--Yn3zcYDn_N33ownMD8SQE,14030
724
+ reconcile/utils/ocm/base.py,sha256=KPS1CgiALlq7INdgTDpN7MmtZ6uQMSWcUDjeGHmp5Z4,14065
725
725
  reconcile/utils/ocm/cluster_groups.py,sha256=F8oqVqN_4QUnGL0K61zZhoYIzJeP57EcmZpwmoV0mr4,1751
726
726
  reconcile/utils/ocm/clusters.py,sha256=Nw9m-jgN3GHHCh6w9UOBbMV4rtS24_-Ep09jAWQ-_fE,7653
727
727
  reconcile/utils/ocm/identity_providers.py,sha256=dKed09N8iWmn39tI_MpwgVe47x23eLsknGbjMUxtwr4,2175
@@ -783,8 +783,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
783
783
  tools/test/test_qontract_cli.py,sha256=w2l4BHB09k1d-BGJ1jBUNCqDv7zkqYrMHojQXg-21kQ,4155
784
784
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
785
785
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
786
- qontract_reconcile-0.10.1rc757.dist-info/METADATA,sha256=0L4M3FIacdQTzZZs5uNpBMpcjoUWVgkQetpJ--aadfA,2382
787
- qontract_reconcile-0.10.1rc757.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
788
- qontract_reconcile-0.10.1rc757.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
789
- qontract_reconcile-0.10.1rc757.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
790
- qontract_reconcile-0.10.1rc757.dist-info/RECORD,,
786
+ qontract_reconcile-0.10.1rc759.dist-info/METADATA,sha256=N17GmMBM1N_QQwB544Gd7bz5DTOnTnT4o284Cj2JVgI,2382
787
+ qontract_reconcile-0.10.1rc759.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
788
+ qontract_reconcile-0.10.1rc759.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
789
+ qontract_reconcile-0.10.1rc759.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
790
+ qontract_reconcile-0.10.1rc759.dist-info/RECORD,,
reconcile/aus/base.py CHANGED
@@ -850,8 +850,8 @@ def is_gate_applicable_to_cluster(gate: OCMVersionGate, cluster: OCMCluster) ->
850
850
  # consider only gates after the clusters current minor version
851
851
  # OCM onls supports creating gate agreements for later minor versions than the
852
852
  # current cluster version
853
- if not semver.match(
854
- f"{cluster.minor_version()}.0", f"<{gate.version_raw_id_prefix}.0"
853
+ if not parse_semver(f"{cluster.minor_version()}.0").match(
854
+ f"<{gate.version_raw_id_prefix}.0"
855
855
  ):
856
856
  return False
857
857
 
reconcile/sql_query.py CHANGED
@@ -15,7 +15,6 @@ from typing import (
15
15
  )
16
16
 
17
17
  import jinja2
18
- from ruamel import yaml
19
18
 
20
19
  from reconcile import (
21
20
  openshift_base,
@@ -34,6 +33,7 @@ from reconcile.utils.openshift_resource import (
34
33
  OpenshiftResource,
35
34
  ResourceInventory,
36
35
  )
36
+ from reconcile.utils.ruamel import create_ruamel_instance
37
37
  from reconcile.utils.secret_reader import SecretReader
38
38
  from reconcile.utils.semver_helper import make_semver
39
39
  from reconcile.utils.smtp_client import (
@@ -591,6 +591,7 @@ def _build_openshift_resources(
591
591
  query_name = query["name"]
592
592
  common_resource_labels = _build_common_resource_labels(query)
593
593
  openshift_resources: list[OpenshiftResource] = []
594
+ yml = create_ruamel_instance()
594
595
  if pull_secret:
595
596
  labels = pull_secret["labels"] or {}
596
597
  labels.update(common_resource_labels)
@@ -651,7 +652,7 @@ def _build_openshift_resources(
651
652
  )
652
653
  openshift_resources.append(
653
654
  OpenshiftResource(
654
- body=yaml.safe_load(job_yaml),
655
+ body=yml.load(job_yaml),
655
656
  integration=QONTRACT_INTEGRATION,
656
657
  integration_version=QONTRACT_INTEGRATION_VERSION,
657
658
  )
@@ -12,10 +12,10 @@ from typing import (
12
12
  )
13
13
  from unittest.mock import create_autospec
14
14
 
15
- import httpretty as _httpretty
16
15
  import pytest
17
16
  from pydantic import BaseModel
18
17
  from pydantic.error_wrappers import ValidationError
18
+ from pytest_httpserver import HTTPServer
19
19
 
20
20
  from reconcile.gql_definitions.fragments.vault_secret import VaultSecret
21
21
  from reconcile.test.fixtures import Fixtures
@@ -29,13 +29,6 @@ def patch_sleep(mocker):
29
29
  yield mocker.patch.object(time, "sleep")
30
30
 
31
31
 
32
- @pytest.fixture()
33
- def httpretty():
34
- with _httpretty.enabled(allow_net_connect=False):
35
- _httpretty.reset()
36
- yield _httpretty
37
-
38
-
39
32
  @pytest.fixture
40
33
  def secret_reader(mocker) -> None:
41
34
  mock_secretreader = mocker.patch(
@@ -153,19 +146,18 @@ def gql_api_builder() -> Callable[[Optional[Mapping]], GqlApi]:
153
146
 
154
147
 
155
148
  @pytest.fixture
156
- def set_httpretty_responses_based_on_fixture(httpretty: _httpretty) -> Callable:
157
- """Create httpretty responses based fixture files."""
149
+ def set_httpserver_responses_based_on_fixture(httpserver: HTTPServer) -> Callable:
150
+ """Create httpserver responses based fixture files."""
158
151
 
159
- def _(url: str, fx: Fixtures, paths: Iterable[str]) -> None:
152
+ def _(fx: Fixtures, paths: Iterable[str]) -> None:
160
153
  for path in paths:
161
154
  for method in ["get", "post", "put", "patch", "delete"]:
162
- method_file = Path(fx.path(path)) / f"{method}.json"
155
+ method_file = Path(fx.path(path.lstrip("/"))) / f"{method}.json"
163
156
  if method_file.exists():
164
- httpretty.register_uri(
165
- getattr(httpretty, method.upper()),
166
- f"{url}/{path}",
167
- body=method_file.read_text(),
168
- content_type="text/json",
157
+ httpserver.expect_oneshot_request(
158
+ path, method=method
159
+ ).respond_with_data(
160
+ method_file.read_text(), content_type="text/json"
169
161
  )
170
162
 
171
163
  return _
@@ -20,7 +20,7 @@ from reconcile.utils.deadmanssnitch_api import (
20
20
 
21
21
 
22
22
  @pytest.fixture
23
- def deadmanssnitch_api() -> MockerFixture:
23
+ def deadmanssnitch_api() -> MagicMock:
24
24
  return create_autospec(DeadMansSnitchApi)
25
25
 
26
26
 
@@ -55,7 +55,7 @@ def secret_reader(mocker: MockerFixture) -> MockerFixture:
55
55
 
56
56
  def test_get_current_state(
57
57
  secret_reader: MagicMock,
58
- deadmanssnitch_api: MockerFixture,
58
+ deadmanssnitch_api: MagicMock,
59
59
  mocker: MockerFixture,
60
60
  deadmanssnitch_settings: DeadMansSnitchSettingsV1,
61
61
  ) -> None:
@@ -32,7 +32,7 @@ from reconcile.ocm_machine_pools import (
32
32
  from reconcile.utils.ocm import OCM
33
33
 
34
34
 
35
- class TestPool(AbstractPool):
35
+ class PoolStub(AbstractPool):
36
36
  created = False
37
37
  deleted = False
38
38
  updated = False
@@ -57,8 +57,8 @@ class TestPool(AbstractPool):
57
57
 
58
58
 
59
59
  @pytest.fixture
60
- def test_pool() -> TestPool:
61
- return TestPool(
60
+ def test_pool() -> PoolStub:
61
+ return PoolStub(
62
62
  id="pool1",
63
63
  replicas=2,
64
64
  labels=None,
@@ -133,7 +133,7 @@ def ocm_mock():
133
133
 
134
134
 
135
135
  def test_diff__has_diff_autoscale(cluster_machine_pool: ClusterMachinePoolV1):
136
- pool = TestPool(id="pool1", cluster="cluster1", cluster_type=ClusterType.OSD)
136
+ pool = PoolStub(id="pool1", cluster="cluster1", cluster_type=ClusterType.OSD)
137
137
 
138
138
  assert cluster_machine_pool.autoscale is None
139
139
  assert not pool._has_diff_autoscale(cluster_machine_pool)
@@ -18,7 +18,7 @@ from reconcile.status_board import (
18
18
  from reconcile.utils.ocm_base_client import OCMBaseClient
19
19
 
20
20
 
21
- class TestStatusBoard(AbstractStatusBoard):
21
+ class StatusBoardStub(AbstractStatusBoard):
22
22
  created: Optional[bool] = False
23
23
  deleted: Optional[bool] = False
24
24
  summarized: Optional[bool] = False
@@ -99,21 +99,21 @@ def test_status_board_handler(mocker: MockerFixture) -> None:
99
99
  ocm = mocker.patch("reconcile.status_board.OCMBaseClient")
100
100
  h = StatusBoardHandler(
101
101
  action="create",
102
- status_board_object=TestStatusBoard(name="foo", fullname="foo"),
102
+ status_board_object=StatusBoardStub(name="foo", fullname="foo"),
103
103
  )
104
104
 
105
105
  h.act(dry_run=False, ocm=ocm)
106
- assert isinstance(h.status_board_object, TestStatusBoard)
106
+ assert isinstance(h.status_board_object, StatusBoardStub)
107
107
  assert h.status_board_object.created
108
108
  assert h.status_board_object.summarized
109
109
 
110
110
  h = StatusBoardHandler(
111
111
  action="delete",
112
- status_board_object=TestStatusBoard(name="foo", fullname="foo"),
112
+ status_board_object=StatusBoardStub(name="foo", fullname="foo"),
113
113
  )
114
114
 
115
115
  h.act(dry_run=False, ocm=ocm)
116
- assert isinstance(h.status_board_object, TestStatusBoard)
116
+ assert isinstance(h.status_board_object, StatusBoardStub)
117
117
  assert h.status_board_object.deleted
118
118
  assert h.status_board_object.summarized
119
119
 
@@ -1,8 +1,8 @@
1
- import json
2
1
  import os
2
+ from collections.abc import Callable
3
3
 
4
- import httpretty
5
4
  import pytest
5
+ from pytest_httpserver import HTTPServer
6
6
  from UnleashClient.features import Feature
7
7
 
8
8
  import reconcile.utils.unleash
@@ -22,6 +22,75 @@ def reset_client():
22
22
  reconcile.utils.unleash.client = None
23
23
 
24
24
 
25
+ def _setup_unleash_httpserver(features: dict, httpserver: HTTPServer) -> HTTPServer:
26
+ httpserver.expect_request("/client/features").respond_with_json(features)
27
+ httpserver.expect_request("/client/register", method="post").respond_with_data(
28
+ status=202
29
+ )
30
+ return httpserver
31
+
32
+
33
+ @pytest.fixture
34
+ def setup_unleash_disable_cluster_strategy(httpserver: HTTPServer):
35
+ def _(enabled: bool) -> HTTPServer:
36
+ features = {
37
+ "version": 2,
38
+ "features": [
39
+ {
40
+ "strategies": [
41
+ {
42
+ "name": "disableCluster",
43
+ "constraints": [],
44
+ "parameters": {"cluster_name": "foo"},
45
+ },
46
+ ],
47
+ "impressionData": False,
48
+ "enabled": enabled,
49
+ "name": "test-strategies",
50
+ "description": "",
51
+ "project": "default",
52
+ "stale": False,
53
+ "type": "release",
54
+ "variants": [],
55
+ }
56
+ ],
57
+ }
58
+ return _setup_unleash_httpserver(features, httpserver)
59
+
60
+ return _
61
+
62
+
63
+ @pytest.fixture
64
+ def setup_unleash_enable_cluster_strategy(httpserver: HTTPServer):
65
+ def _(enabled: bool) -> HTTPServer:
66
+ features = {
67
+ "version": 2,
68
+ "features": [
69
+ {
70
+ "strategies": [
71
+ {
72
+ "name": "enableCluster",
73
+ "constraints": [],
74
+ "parameters": {"cluster_name": "enabled-cluster"},
75
+ },
76
+ ],
77
+ "impressionData": False,
78
+ "enabled": enabled,
79
+ "name": "test-strategies",
80
+ "description": "",
81
+ "project": "default",
82
+ "stale": False,
83
+ "type": "release",
84
+ "variants": [],
85
+ }
86
+ ],
87
+ }
88
+
89
+ return _setup_unleash_httpserver(features, httpserver)
90
+
91
+ return _
92
+
93
+
25
94
  def test__get_unleash_api_client(mocker):
26
95
  mocked_unleash_client = mocker.patch(
27
96
  "reconcile.utils.unleash.UnleashClient",
@@ -108,42 +177,12 @@ def test_get_feature_toggles(mocker, monkeypatch):
108
177
  assert toggles["bar"] == "enabled"
109
178
 
110
179
 
111
- def setup_unleash_disable_cluster_strategy_httpretty(enabled: bool):
112
- features = {
113
- "version": 2,
114
- "features": [
115
- {
116
- "strategies": [
117
- {
118
- "name": "disableCluster",
119
- "constraints": [],
120
- "parameters": {"cluster_name": "foo"},
121
- },
122
- ],
123
- "impressionData": False,
124
- "enabled": enabled,
125
- "name": "test-strategies",
126
- "description": "",
127
- "project": "default",
128
- "stale": False,
129
- "type": "release",
130
- "variants": [],
131
- }
132
- ],
133
- }
134
-
135
- feature_param = (httpretty.GET, "http://unleash/api/client/features")
136
- httpretty.register_uri(*feature_param, body=json.dumps(features), status=200)
137
-
138
- register_param = (httpretty.POST, "http://unleash/api/client/register")
139
- httpretty.register_uri(*register_param, status=202)
140
-
141
-
142
- @httpretty.activate(allow_net_connect=False)
143
- def test_get_feature_toggle_state_with_strategy(reset_client):
144
- os.environ["UNLEASH_API_URL"] = "http://unleash/api"
180
+ def test_get_feature_toggle_state_with_strategy(
181
+ reset_client: None, setup_unleash_disable_cluster_strategy: Callable
182
+ ):
183
+ httpserver = setup_unleash_disable_cluster_strategy(True)
184
+ os.environ["UNLEASH_API_URL"] = httpserver.url_for("/")
145
185
  os.environ["UNLEASH_CLIENT_ACCESS_TOKEN"] = "bar"
146
- setup_unleash_disable_cluster_strategy_httpretty(True)
147
186
  assert not get_feature_toggle_state(
148
187
  "test-strategies", context={"cluster_name": "foo"}
149
188
  )
@@ -151,53 +190,24 @@ def test_get_feature_toggle_state_with_strategy(reset_client):
151
190
  _shutdown_client()
152
191
 
153
192
 
154
- @httpretty.activate(allow_net_connect=False)
155
- def test_get_feature_toggle_state_disabled_with_strategy(reset_client):
156
- os.environ["UNLEASH_API_URL"] = "http://unleash/api"
193
+ def test_get_feature_toggle_state_disabled_with_strategy(
194
+ reset_client: None, setup_unleash_disable_cluster_strategy: Callable
195
+ ):
196
+ httpserver = setup_unleash_disable_cluster_strategy(False)
197
+ os.environ["UNLEASH_API_URL"] = httpserver.url_for("/")
157
198
  os.environ["UNLEASH_CLIENT_ACCESS_TOKEN"] = "bar"
158
- setup_unleash_disable_cluster_strategy_httpretty(False)
159
199
  assert not get_feature_toggle_state(
160
200
  "test-strategies", context={"cluster_name": "bar"}
161
201
  )
162
202
  _shutdown_client()
163
203
 
164
204
 
165
- def setup_unleash_enable_cluster_strategy_httpretty(enabled: bool):
166
- features = {
167
- "version": 2,
168
- "features": [
169
- {
170
- "strategies": [
171
- {
172
- "name": "enableCluster",
173
- "constraints": [],
174
- "parameters": {"cluster_name": "enabled-cluster"},
175
- },
176
- ],
177
- "impressionData": False,
178
- "enabled": enabled,
179
- "name": "test-strategies",
180
- "description": "",
181
- "project": "default",
182
- "stale": False,
183
- "type": "release",
184
- "variants": [],
185
- }
186
- ],
187
- }
188
-
189
- feature_param = (httpretty.GET, "http://unleash/api/client/features")
190
- httpretty.register_uri(*feature_param, body=json.dumps(features), status=200)
191
-
192
- register_param = (httpretty.POST, "http://unleash/api/client/register")
193
- httpretty.register_uri(*register_param, status=202)
194
-
195
-
196
- @httpretty.activate(allow_net_connect=False)
197
- def test_get_feature_toggle_state_with_enable_cluster_strategy(reset_client):
198
- os.environ["UNLEASH_API_URL"] = "http://unleash/api"
205
+ def test_get_feature_toggle_state_with_enable_cluster_strategy(
206
+ reset_client: None, setup_unleash_enable_cluster_strategy: Callable
207
+ ):
208
+ httpserver = setup_unleash_enable_cluster_strategy(True)
209
+ os.environ["UNLEASH_API_URL"] = httpserver.url_for("/")
199
210
  os.environ["UNLEASH_CLIENT_ACCESS_TOKEN"] = "bar"
200
- setup_unleash_enable_cluster_strategy_httpretty(True)
201
211
  assert get_feature_toggle_state(
202
212
  "test-strategies", context={"cluster_name": "enabled-cluster"}
203
213
  )
@@ -49,10 +49,12 @@ class DeadMansSnitchApi:
49
49
  self.session.close()
50
50
 
51
51
  def get_snitches(self, tags: list[str]) -> list[Snitch]:
52
- full_url = f"{self.url}?tags={','.join(tags)}"
53
52
  logging.debug("Getting snitches for tags:%s", tags)
54
53
  response = self.session.get(
55
- url=full_url, auth=(self.token, ""), timeout=self.timeout
54
+ url=self.url,
55
+ params={"tags": ",".join(tags)},
56
+ auth=(self.token, ""),
57
+ timeout=self.timeout,
56
58
  )
57
59
  response.raise_for_status()
58
60
  snitches = [Snitch(**item) for item in response.json()]
@@ -8,13 +8,13 @@ from typing import (
8
8
  TypeVar,
9
9
  )
10
10
 
11
- import semver
12
11
  from pydantic import (
13
12
  BaseModel,
14
13
  Field,
15
14
  )
16
15
 
17
16
  from reconcile.utils.aws_helper import get_account_uid_from_arn, get_role_name_from_arn
17
+ from reconcile.utils.semver_helper import parse_semver
18
18
 
19
19
  LabelSetTypeVar = TypeVar("LabelSetTypeVar", bound=BaseModel)
20
20
  ACTIVE_SUBSCRIPTION_STATES = {"Active", "Reserved"}
@@ -246,8 +246,8 @@ class OCMCluster(BaseModel):
246
246
  external_configuration: Optional[OCMExternalConfiguration]
247
247
 
248
248
  def minor_version(self) -> str:
249
- version_info = semver.parse(self.version.raw_id)
250
- return f"{version_info['major']}.{version_info['minor']}"
249
+ version_info = parse_semver(self.version.raw_id)
250
+ return f"{version_info.major}.{version_info.minor}"
251
251
 
252
252
  def available_upgrades(self) -> list[str]:
253
253
  return self.version.available_upgrades
@@ -75,6 +75,7 @@ class ApiBase:
75
75
 
76
76
  def _get(self, url: str) -> dict[str, Any]:
77
77
  response = self.session.get(urljoin(self.host, url), timeout=self.read_timeout)
78
+ response.raise_for_status()
78
79
  return response.json()
79
80
 
80
81
  def _list(
@@ -166,6 +166,7 @@ class SlackApi:
166
166
  api_config: Optional[SlackApiConfig] = None,
167
167
  init_usergroups: bool = True,
168
168
  channel: Optional[str] = None,
169
+ slack_url: Optional[str] = None,
169
170
  **chat_kwargs: Any,
170
171
  ) -> None:
171
172
  """
@@ -187,7 +188,11 @@ class SlackApi:
187
188
  else:
188
189
  self.config = SlackApiConfig()
189
190
 
190
- self._sc = WebClient(token=token, timeout=self.config.timeout)
191
+ self._sc = WebClient(
192
+ token=token,
193
+ timeout=self.config.timeout,
194
+ base_url=slack_url or WebClient.BASE_URL,
195
+ )
191
196
  self._configure_client_retry()
192
197
 
193
198
  self._results: dict[str, Any] = {}