qontract-reconcile 0.10.1rc693__py3-none-any.whl → 0.10.1rc694__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.1rc693.dist-info → qontract_reconcile-0.10.1rc694.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc693.dist-info → qontract_reconcile-0.10.1rc694.dist-info}/RECORD +12 -12
- reconcile/aus/base.py +58 -14
- reconcile/aus/ocm_addons_upgrade_scheduler_org.py +8 -4
- reconcile/cli.py +1 -0
- reconcile/queries.py +1 -0
- reconcile/utils/ocm/addons.py +205 -34
- reconcile/utils/ocm/upgrades.py +0 -66
- tools/qontract_cli.py +17 -9
- {qontract_reconcile-0.10.1rc693.dist-info → qontract_reconcile-0.10.1rc694.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc693.dist-info → qontract_reconcile-0.10.1rc694.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc693.dist-info → qontract_reconcile-0.10.1rc694.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc693.dist-info → qontract_reconcile-0.10.1rc694.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.1rc694
|
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.1rc693.dist-info → qontract_reconcile-0.10.1rc694.dist-info}/RECORD
RENAMED
@@ -9,7 +9,7 @@ reconcile/aws_iam_password_reset.py,sha256=NwErtrqgBiXr7eGCAHdtGGOx0S7-4JnSc29Ie
|
|
9
9
|
reconcile/aws_support_cases_sos.py,sha256=Jk6_XjDeJSYxgRGqcEAOcynt9qJF2r5HPIPcSKmoBv8,2974
|
10
10
|
reconcile/blackbox_exporter_endpoint_monitoring.py,sha256=W_VJagnsJR1v5oqjlI3RJJE0_nhtJ0m81RS8zWA5u5c,3538
|
11
11
|
reconcile/checkpoint.py,sha256=R2WFXUXLTB4sWMi4GeA4eegsuf_1-Q4vH8M0Toh3Ij4,5036
|
12
|
-
reconcile/cli.py,sha256=
|
12
|
+
reconcile/cli.py,sha256=Xj_msd-518yR9r1hy39FI3Q9gBRZQsfM9HRA-Ep6CKY,93661
|
13
13
|
reconcile/closedbox_endpoint_monitoring_base.py,sha256=SMhkcQqprWvThrIJa3U_3uh5w1h-alleW1QnCJFY4Qw,4909
|
14
14
|
reconcile/cluster_deployment_mapper.py,sha256=2Ah-nu-Mdig0pjuiZl_XLrmVAjYzFjORR3dMlCgkmw0,2352
|
15
15
|
reconcile/dashdotdb_base.py,sha256=a5aPLVxyqPSbjdB0Ty-uliOtxwvEbbEljHJKxdK3-Zk,4813
|
@@ -92,7 +92,7 @@ reconcile/quay_mirror.py,sha256=9NzbNoxl-NdD8CwImcXNG5xTdHmUJxBfeVk5XHH41J8,1488
|
|
92
92
|
reconcile/quay_mirror_org.py,sha256=Oq-t3kSkgfeSAOUDjLCDRBeEvOIEBacfX38qrX_s0oc,10801
|
93
93
|
reconcile/quay_permissions.py,sha256=9KOutS1w4RFQqkvMSy54VtsKNx56-phzP6yI_rEW-B8,4244
|
94
94
|
reconcile/quay_repos.py,sha256=cuEYG0HUe0ut5yvLdEwOF5-CmccpXQHRb_wDazvDrvQ,6895
|
95
|
-
reconcile/queries.py,sha256=
|
95
|
+
reconcile/queries.py,sha256=hgQizeUT5_a1ZI9i8wH-ajr7e956u5ynIp90zKMeRCA,50560
|
96
96
|
reconcile/query_validator.py,sha256=BAjGrU8_VhzTOv5k0-uz0hY9ziZyconv8VAhgre1Auc,1497
|
97
97
|
reconcile/requests_sender.py,sha256=914iluuF4UVgG3VyxxtnHOu4yf6YKS2fIy6PViSsFTQ,3875
|
98
98
|
reconcile/resource_scraper.py,sha256=vo1N9vLJCYWvXlTwFRIpEuWjx_39ZV9zxJlpoPq4g3U,2330
|
@@ -120,12 +120,12 @@ reconcile/vpc_peerings_validator.py,sha256=Kv22HJVlTW9l9GB2eXwjPWqdDbr_VuvQBNPtt
|
|
120
120
|
reconcile/aus/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
121
121
|
reconcile/aus/advanced_upgrade_service.py,sha256=MPqcWpq1QeYzBsB8rtTlo102h_cR_q83oOYtWAncuAk,22391
|
122
122
|
reconcile/aus/aus_label_source.py,sha256=qoP8Fgxuu1tCuhG6ixCWve7Ll-KD6a79E2uLAmC0ifw,4184
|
123
|
-
reconcile/aus/base.py,sha256=
|
123
|
+
reconcile/aus/base.py,sha256=4VTHqc22IW1xyLCgxhUrSBDRsaF99RW3uzoQafTQDN4,49410
|
124
124
|
reconcile/aus/cluster_version_data.py,sha256=j4UyEBi5mQuvPq5Lo7a_L_0blxvH790wJV07uAiikFU,7126
|
125
125
|
reconcile/aus/healthchecks.py,sha256=S8_KPn_zFiOo_wf5XlVmz-I3tUDYAim3EGSqiSPMvLQ,2707
|
126
126
|
reconcile/aus/metrics.py,sha256=nKT4m2zGT-QOMR0c-z-npVNKWsNMubzdffpU_f9n4II,3927
|
127
127
|
reconcile/aus/models.py,sha256=2e0IPHDJNSM4opqIJUGGxjXLF3zFyrBCAFWRJKjgEEQ,7371
|
128
|
-
reconcile/aus/ocm_addons_upgrade_scheduler_org.py,sha256=
|
128
|
+
reconcile/aus/ocm_addons_upgrade_scheduler_org.py,sha256=t2_J7CuovTm6FGvwWI6HsyiftPbt3ZRWEKjsGmIRcEI,10207
|
129
129
|
reconcile/aus/ocm_upgrade_scheduler.py,sha256=2uPn13y3QGCHLoKwCc1Z7q9wQsoQf_F1HATMYUbl53s,3695
|
130
130
|
reconcile/aus/ocm_upgrade_scheduler_org.py,sha256=f7pE_XrX9695EMZpg-CFZiakZ9vZ9BoRpkE2I9UC0sI,3190
|
131
131
|
reconcile/aus/upgrades.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -667,7 +667,7 @@ reconcile/utils/mr/ocm_update_recommended_version.py,sha256=p_aVP0TGrlKk9WBwgQnY
|
|
667
667
|
reconcile/utils/mr/ocm_upgrade_scheduler_org_updates.py,sha256=RzEKRT_BhvB2ud9pyNFZ1cNZFmDGBUah9vjpP0y9f9w,2810
|
668
668
|
reconcile/utils/mr/user_maintenance.py,sha256=cHPBn8zrReWLHalyk-EFdkFJe9zjVjRoZhT4t2zZfGE,3956
|
669
669
|
reconcile/utils/ocm/__init__.py,sha256=xv7CJp7K9LCQfa4gL_W0MMCOD1P4qOy8t5aZj1xXNUE,808
|
670
|
-
reconcile/utils/ocm/addons.py,sha256=
|
670
|
+
reconcile/utils/ocm/addons.py,sha256=cofEAtnoBGKbtShSe3oAz9YbEuql1z6w_2FoNiBcFwA,6887
|
671
671
|
reconcile/utils/ocm/base.py,sha256=GclZtCrPkPJmGP9HHvqIlV-8VXSKuaQTQJkA2pklN60,13817
|
672
672
|
reconcile/utils/ocm/cluster_groups.py,sha256=F8oqVqN_4QUnGL0K61zZhoYIzJeP57EcmZpwmoV0mr4,1751
|
673
673
|
reconcile/utils/ocm/clusters.py,sha256=Nw9m-jgN3GHHCh6w9UOBbMV4rtS24_-Ep09jAWQ-_fE,7653
|
@@ -681,7 +681,7 @@ reconcile/utils/ocm/sre_capability_labels.py,sha256=-TUmTzvK5yu7qY8SUMGj6-684wa8
|
|
681
681
|
reconcile/utils/ocm/status_board.py,sha256=fOuyzkykxU9Rr7zhW5VaY0Vkn8Ur-GxvElzb8No-DZg,2283
|
682
682
|
reconcile/utils/ocm/subscriptions.py,sha256=4qSH8uF9JvFxiecVSV1Kh8-mPcGSTfTTK7In5qHz_2w,2568
|
683
683
|
reconcile/utils/ocm/syncsets.py,sha256=zvji9qWvInIRTdoybMaM9-VUhq4L1VewWfWCQmp4urc,940
|
684
|
-
reconcile/utils/ocm/upgrades.py,sha256=
|
684
|
+
reconcile/utils/ocm/upgrades.py,sha256=zrr_J9X2WIgnnW4hz5NCqdLq22jmoIAX82xKhz-_LY8,4910
|
685
685
|
reconcile/utils/rosa/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
686
686
|
reconcile/utils/rosa/rosa_cli.py,sha256=b7V3EgO4b4hOnvZzrxdn-bxRbkINQysOg_ecuB8l5GA,11364
|
687
687
|
reconcile/utils/rosa/session.py,sha256=jYJ0QsJv0mgV15MQIrfTuk2arscmgO4zkBhKcwyO5qo,6915
|
@@ -712,7 +712,7 @@ tools/app_interface_metrics_exporter.py,sha256=zkwkxdAUAxjdc-pzx2_oJXG25fo0Fnyd5
|
|
712
712
|
tools/app_interface_reporter.py,sha256=upA-J-n-HXHKVDINRuMR7vTt-iJvQORKUVi9D3leQto,17738
|
713
713
|
tools/glitchtip_access_reporter.py,sha256=oPBnk_YoDuljU3v0FaChzOwwnk4vap1xEE67QEjzdqs,2948
|
714
714
|
tools/glitchtip_access_revalidation.py,sha256=8kbBJk04mkq28kWoRDDkfCGIF3GRg3pJrFAh1sW0dbk,2821
|
715
|
-
tools/qontract_cli.py,sha256=
|
715
|
+
tools/qontract_cli.py,sha256=fxXsgjmLBzC1zDkmNnB5jfOnwL-kGci5xC_4BsoIe3M,111648
|
716
716
|
tools/sd_app_sre_alert_report.py,sha256=e9vAdyenUz2f5c8-z-5WY0wv-SJ9aePKDH2r4IwB6pc,5063
|
717
717
|
tools/template_validation.py,sha256=-U-lTGeLaci8yWPEblCJeev2DOlY1jM9QOOh-O1zts8,3376
|
718
718
|
tools/cli_commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -724,8 +724,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
|
|
724
724
|
tools/test/test_qontract_cli.py,sha256=OvalpVRfY4pNmpMaWHHYqBjV68b1eGQjX8SCyTAXb1w,3501
|
725
725
|
tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
|
726
726
|
tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
|
727
|
-
qontract_reconcile-0.10.
|
728
|
-
qontract_reconcile-0.10.
|
729
|
-
qontract_reconcile-0.10.
|
730
|
-
qontract_reconcile-0.10.
|
731
|
-
qontract_reconcile-0.10.
|
727
|
+
qontract_reconcile-0.10.1rc694.dist-info/METADATA,sha256=cJGxg2IBbK-ByqiYdq5k4iFEqTyNRhmB3W8V5a1a_II,2382
|
728
|
+
qontract_reconcile-0.10.1rc694.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
729
|
+
qontract_reconcile-0.10.1rc694.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
|
730
|
+
qontract_reconcile-0.10.1rc694.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
731
|
+
qontract_reconcile-0.10.1rc694.dist-info/RECORD,,
|
reconcile/aus/base.py
CHANGED
@@ -8,6 +8,7 @@ from abc import (
|
|
8
8
|
from datetime import (
|
9
9
|
datetime,
|
10
10
|
timedelta,
|
11
|
+
timezone,
|
11
12
|
)
|
12
13
|
from typing import (
|
13
14
|
Callable,
|
@@ -74,6 +75,7 @@ from reconcile.utils.clusterhealth.telemeter import (
|
|
74
75
|
from reconcile.utils.defer import defer
|
75
76
|
from reconcile.utils.disabled_integrations import integration_is_enabled
|
76
77
|
from reconcile.utils.filtering import remove_none_values_from_dict
|
78
|
+
from reconcile.utils.ocm.addons import AddonService, AddonServiceV1, AddonServiceV2
|
77
79
|
from reconcile.utils.ocm.clusters import (
|
78
80
|
OCMCluster,
|
79
81
|
get_node_pools,
|
@@ -81,14 +83,11 @@ from reconcile.utils.ocm.clusters import (
|
|
81
83
|
)
|
82
84
|
from reconcile.utils.ocm.upgrades import (
|
83
85
|
OCMVersionGate,
|
84
|
-
create_addon_upgrade_policy,
|
85
86
|
create_control_plane_upgrade_policy,
|
86
87
|
create_node_pool_upgrade_policy,
|
87
88
|
create_upgrade_policy,
|
88
|
-
delete_addon_upgrade_policy,
|
89
89
|
delete_control_plane_upgrade_policy,
|
90
90
|
delete_upgrade_policy,
|
91
|
-
get_addon_upgrade_policies,
|
92
91
|
get_control_plane_upgrade_policies,
|
93
92
|
get_node_pool_upgrade_policies,
|
94
93
|
get_upgrade_policies,
|
@@ -365,6 +364,34 @@ class AdvancedUpgradeSchedulerBaseIntegration(
|
|
365
364
|
return None
|
366
365
|
|
367
366
|
|
367
|
+
def init_addon_service(ocm_env: OCMEnvironment) -> AddonService:
|
368
|
+
"""
|
369
|
+
Initialize the right version of addon-service for an OCM environment.
|
370
|
+
Since this is just temporary until all OCM environments are on v2, we
|
371
|
+
use a label on the OCM environmentschema to determine which version to use.
|
372
|
+
"""
|
373
|
+
addon_service_version = (ocm_env.labels or {}).get(
|
374
|
+
"feature_flag_addon_service_version"
|
375
|
+
) or "v2"
|
376
|
+
return init_addon_service_version(addon_service_version)
|
377
|
+
|
378
|
+
|
379
|
+
def init_addon_service_version(addon_service_version: str) -> AddonService:
|
380
|
+
"""
|
381
|
+
Initialize the right version of addon-service based on the version string.
|
382
|
+
Supported versions are:
|
383
|
+
- v1: part of CS
|
384
|
+
- v2: standalone service using upgrade-plans instead of upgrade-policies
|
385
|
+
"""
|
386
|
+
match addon_service_version:
|
387
|
+
case "v1":
|
388
|
+
return AddonServiceV1()
|
389
|
+
case "v2":
|
390
|
+
return AddonServiceV2()
|
391
|
+
case _:
|
392
|
+
raise ValueError(f"Unknown addon service version: {addon_service_version}")
|
393
|
+
|
394
|
+
|
368
395
|
class RemainingSoakDayMetricsBuilder(Protocol):
|
369
396
|
def __call__(
|
370
397
|
self, cluster_uuid: str, soaking_version: str
|
@@ -397,27 +424,39 @@ class AbstractUpgradePolicy(ABC, BaseModel):
|
|
397
424
|
pass
|
398
425
|
|
399
426
|
|
427
|
+
def addon_upgrade_policy_soonest_next_run() -> str:
|
428
|
+
now = datetime.now(tz=timezone.utc)
|
429
|
+
next_run = now + timedelta(minutes=MIN_DELTA_MINUTES)
|
430
|
+
return next_run.strftime("%Y-%m-%dT%H:%M:%SZ")
|
431
|
+
|
432
|
+
|
400
433
|
class AddonUpgradePolicy(AbstractUpgradePolicy):
|
401
434
|
"""Class to create and delete Addon upgrade policies in OCM"""
|
402
435
|
|
403
436
|
addon_id: str
|
437
|
+
addon_service: AddonService
|
438
|
+
|
439
|
+
class Config:
|
440
|
+
arbitrary_types_allowed = True
|
404
441
|
|
405
442
|
def create(self, ocm_api: OCMBaseClient) -> None:
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
"
|
411
|
-
|
412
|
-
|
413
|
-
|
443
|
+
self.addon_service.create_addon_upgrade_policy(
|
444
|
+
ocm_api=ocm_api,
|
445
|
+
cluster_id=self.cluster.id,
|
446
|
+
addon_id=self.addon_id,
|
447
|
+
schedule_type="manual",
|
448
|
+
version=self.version,
|
449
|
+
next_run=self.next_run or addon_upgrade_policy_soonest_next_run(),
|
450
|
+
)
|
414
451
|
|
415
452
|
def delete(self, ocm_api: OCMBaseClient) -> None:
|
416
453
|
if not self.id:
|
417
454
|
raise ValueError(
|
418
455
|
"Cannot delete addon upgrade policy without id (not created yet)"
|
419
456
|
)
|
420
|
-
|
457
|
+
self.addon_service.delete_addon_upgrade_policy(
|
458
|
+
ocm_api=ocm_api, cluster_id=self.cluster.id, policy_id=self.id
|
459
|
+
)
|
421
460
|
|
422
461
|
def summarize(self) -> str:
|
423
462
|
details = {
|
@@ -544,15 +583,18 @@ def fetch_current_state(
|
|
544
583
|
addons: bool = False,
|
545
584
|
) -> list[AbstractUpgradePolicy]:
|
546
585
|
current_state: list[AbstractUpgradePolicy] = []
|
586
|
+
addon_service = init_addon_service(org_upgrade_spec.org.environment)
|
547
587
|
for spec in org_upgrade_spec.specs:
|
548
588
|
if addons and isinstance(spec, ClusterAddonUpgradeSpec):
|
549
589
|
addon_spec = cast(ClusterAddonUpgradeSpec, spec)
|
550
|
-
upgrade_policies = get_addon_upgrade_policies(
|
590
|
+
upgrade_policies = addon_service.get_addon_upgrade_policies(
|
551
591
|
ocm_api, spec.cluster.id, addon_id=addon_spec.addon.addon.id
|
552
592
|
)
|
553
593
|
for upgrade_policy in upgrade_policies:
|
554
594
|
upgrade_policy["cluster"] = spec.cluster
|
555
|
-
current_state.append(
|
595
|
+
current_state.append(
|
596
|
+
AddonUpgradePolicy(**upgrade_policy, addon_service=addon_service)
|
597
|
+
)
|
556
598
|
elif spec.cluster.is_rosa_hypershift():
|
557
599
|
upgrade_policies = get_control_plane_upgrade_policies(
|
558
600
|
ocm_api, spec.cluster.id
|
@@ -1015,6 +1057,7 @@ def calculate_diff(
|
|
1015
1057
|
for mutex in spec.effective_mutexes:
|
1016
1058
|
locked[mutex] = spec.cluster.id
|
1017
1059
|
|
1060
|
+
addon_service = init_addon_service(desired_state.org.environment)
|
1018
1061
|
now = datetime.utcnow()
|
1019
1062
|
gates = get_version_gates(ocm_api)
|
1020
1063
|
for spec in desired_state.specs:
|
@@ -1063,6 +1106,7 @@ def calculate_diff(
|
|
1063
1106
|
schedule_type="manual",
|
1064
1107
|
addon_id=addon_id,
|
1065
1108
|
upgrade_type="ADDON",
|
1109
|
+
addon_service=addon_service,
|
1066
1110
|
),
|
1067
1111
|
)
|
1068
1112
|
)
|
@@ -6,6 +6,7 @@ from reconcile.aus import base as aus
|
|
6
6
|
from reconcile.aus.base import (
|
7
7
|
AbstractUpgradePolicy,
|
8
8
|
AddonUpgradePolicy,
|
9
|
+
init_addon_service,
|
9
10
|
)
|
10
11
|
from reconcile.aus.cluster_version_data import VersionData
|
11
12
|
from reconcile.aus.healthchecks import (
|
@@ -26,8 +27,6 @@ from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment
|
|
26
27
|
from reconcile.utils import metrics
|
27
28
|
from reconcile.utils.ocm.addons import (
|
28
29
|
OCMAddonInstallation,
|
29
|
-
get_addon_latest_versions,
|
30
|
-
get_addons_for_cluster,
|
31
30
|
)
|
32
31
|
from reconcile.utils.ocm.clusters import (
|
33
32
|
OCMCluster,
|
@@ -137,15 +136,17 @@ class OCMAddonsUpgradeSchedulerOrgIntegration(
|
|
137
136
|
if not organizations:
|
138
137
|
return {}
|
139
138
|
|
139
|
+
addon_service = init_addon_service(ocm_env)
|
140
|
+
|
140
141
|
# lookup cluster in OCM to figure out if they exist
|
141
142
|
# and to get their UUID
|
142
143
|
with init_ocm_base_client(ocm_env, self.secret_reader) as ocm_api:
|
143
144
|
clusters = discover_clusters_for_organizations(
|
144
145
|
ocm_api, [org.org_id for org in organizations]
|
145
146
|
)
|
146
|
-
addon_latest_versions = get_addon_latest_versions(ocm_api)
|
147
|
+
addon_latest_versions = addon_service.get_addon_latest_versions(ocm_api)
|
147
148
|
addons_per_cluster: dict[str, list[OCMAddonInstallation]] = {
|
148
|
-
cluster.ocm_cluster.name: get_addons_for_cluster(
|
149
|
+
cluster.ocm_cluster.name: addon_service.get_addons_for_cluster(
|
149
150
|
ocm_api=ocm_api,
|
150
151
|
cluster_id=cluster.ocm_cluster.id,
|
151
152
|
addon_latest_versions=addon_latest_versions,
|
@@ -260,6 +261,9 @@ def calculate_diff(
|
|
260
261
|
id=current.id,
|
261
262
|
addon_id=current.addon_id,
|
262
263
|
schedule_type=current.schedule_type,
|
264
|
+
addon_service=init_addon_service(
|
265
|
+
org_upgrade_spec.org.environment
|
266
|
+
),
|
263
267
|
),
|
264
268
|
)
|
265
269
|
)
|
reconcile/cli.py
CHANGED
@@ -2469,6 +2469,7 @@ def ocm_addons_upgrade_scheduler_org(
|
|
2469
2469
|
run_class_integration(
|
2470
2470
|
integration=OCMAddonsUpgradeSchedulerOrgIntegration(
|
2471
2471
|
AdvancedUpgradeSchedulerBaseIntegrationParams(
|
2472
|
+
ocm_environment="ocm-integration",
|
2472
2473
|
ocm_organization_ids=set(org_id),
|
2473
2474
|
excluded_ocm_organization_ids=set(exclude_org_id),
|
2474
2475
|
)
|
reconcile/queries.py
CHANGED
reconcile/utils/ocm/addons.py
CHANGED
@@ -6,46 +6,217 @@ from typing import (
|
|
6
6
|
from reconcile.utils.ocm.base import OCMAddonInstallation
|
7
7
|
from reconcile.utils.ocm_base_client import OCMBaseClient
|
8
8
|
|
9
|
+
ADDON_UPGRADE_POLICY_DESIRED_KEYS = {
|
10
|
+
"id",
|
11
|
+
"addon_id",
|
12
|
+
"schedule_type",
|
13
|
+
"schedule",
|
14
|
+
"next_run",
|
15
|
+
"version",
|
16
|
+
}
|
9
17
|
|
10
|
-
def get_addons_for_cluster(
|
11
|
-
ocm_api: OCMBaseClient,
|
12
|
-
cluster_id: str,
|
13
|
-
addon_latest_versions: dict[str, str],
|
14
|
-
required_state: Optional[str],
|
15
|
-
) -> list[OCMAddonInstallation]:
|
16
|
-
"""
|
17
|
-
Returns a list of Addons installed on a cluster
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
class AddonService:
|
20
|
+
def get_addon_latest_versions(self, ocm_api: OCMBaseClient) -> dict[str, str]:
|
21
|
+
"""
|
22
|
+
Returns the latest version for each addon.
|
23
|
+
"""
|
24
|
+
latest_versions: dict[str, str] = {}
|
25
|
+
for addon in ocm_api.get_paginated(f"{self.addon_base_api_path()}/addons"):
|
26
|
+
addon_id = addon["id"]
|
27
|
+
latest_versions[addon_id] = addon["version"]["id"]
|
28
|
+
return latest_versions
|
29
|
+
|
30
|
+
def get_addons_for_cluster(
|
31
|
+
self,
|
32
|
+
ocm_api: OCMBaseClient,
|
33
|
+
cluster_id: str,
|
34
|
+
addon_latest_versions: dict[str, str],
|
35
|
+
required_state: Optional[str],
|
36
|
+
) -> list[OCMAddonInstallation]:
|
37
|
+
"""
|
38
|
+
Returns a list of Addons installed on a cluster
|
39
|
+
|
40
|
+
:param cluster_id: ID of the cluster
|
41
|
+
:param addon_latest_versions: dict of addon_id -> latest version. This allows us to
|
42
|
+
populate the addonsinstalation available upgrades in an efficient way.
|
43
|
+
:param required_state: only return addons with this state
|
44
|
+
"""
|
45
|
+
|
46
|
+
params: Optional[dict[str, Any]] = None
|
47
|
+
if required_state:
|
48
|
+
params = {"search": f"state='{required_state}'"}
|
49
|
+
|
50
|
+
addons = []
|
51
|
+
for addon in ocm_api.get_paginated(
|
52
|
+
api_path=f"{self.addon_base_api_path()}/clusters/{cluster_id}/addons",
|
53
|
+
params=params,
|
54
|
+
):
|
55
|
+
current_version = addon["addon_version"]["id"]
|
56
|
+
latest_version = addon_latest_versions.get(addon["id"])
|
57
|
+
addon["addon_version"]["available_upgrades"] = (
|
58
|
+
[latest_version] if latest_version != current_version else []
|
59
|
+
)
|
60
|
+
addons.append(OCMAddonInstallation(**addon))
|
61
|
+
return addons
|
62
|
+
|
63
|
+
def addon_base_api_path(self) -> str:
|
64
|
+
raise NotImplementedError()
|
65
|
+
|
66
|
+
def get_addon_upgrade_policies(
|
67
|
+
self, ocm_api: OCMBaseClient, cluster_id: str, addon_id: Optional[str] = None
|
68
|
+
) -> list[dict[str, Any]]:
|
69
|
+
raise NotImplementedError()
|
70
|
+
|
71
|
+
def create_addon_upgrade_policy(
|
72
|
+
self,
|
73
|
+
ocm_api: OCMBaseClient,
|
74
|
+
cluster_id: str,
|
75
|
+
addon_id: str,
|
76
|
+
schedule_type: str,
|
77
|
+
version: str,
|
78
|
+
next_run: str,
|
79
|
+
) -> None:
|
80
|
+
raise NotImplementedError()
|
81
|
+
|
82
|
+
def delete_addon_upgrade_policy(
|
83
|
+
self, ocm_api: OCMBaseClient, cluster_id: str, policy_id: str
|
84
|
+
) -> None:
|
85
|
+
raise NotImplementedError()
|
86
|
+
|
87
|
+
|
88
|
+
class AddonServiceV1(AddonService):
|
23
89
|
"""
|
90
|
+
The original addon-service API that is part of CS.
|
91
|
+
"""
|
92
|
+
|
93
|
+
def addon_base_api_path(self) -> str:
|
94
|
+
return "/api/clusters_mgmt/v1"
|
95
|
+
|
96
|
+
def get_addon_upgrade_policies(
|
97
|
+
self, ocm_api: OCMBaseClient, cluster_id: str, addon_id: Optional[str] = None
|
98
|
+
) -> list[dict[str, Any]]:
|
99
|
+
results: list[dict[str, Any]] = []
|
24
100
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
101
|
+
for policy in ocm_api.get_paginated(
|
102
|
+
f"{self.addon_base_api_path()}/clusters/{cluster_id}/addon_upgrade_policies"
|
103
|
+
):
|
104
|
+
if addon_id and policy["addon_id"] != addon_id:
|
105
|
+
continue
|
106
|
+
policy_data = {
|
107
|
+
k: v
|
108
|
+
for k, v in policy.items()
|
109
|
+
if k in ADDON_UPGRADE_POLICY_DESIRED_KEYS
|
110
|
+
}
|
111
|
+
policy_data["state"] = self._get_addon_upgrade_policy_state(
|
112
|
+
ocm_api, cluster_id, policy["id"]
|
113
|
+
)
|
114
|
+
results.append(policy_data)
|
115
|
+
|
116
|
+
return results
|
117
|
+
|
118
|
+
def _get_addon_upgrade_policy_state(
|
119
|
+
self, ocm_api: OCMBaseClient, cluster_id: str, addon_upgrade_policy_id: str
|
120
|
+
) -> Optional[str]:
|
121
|
+
try:
|
122
|
+
state_data = ocm_api.get(
|
123
|
+
f"{self.addon_base_api_path()}/clusters/{cluster_id}/addon_upgrade_policies/{addon_upgrade_policy_id}/state"
|
124
|
+
)
|
125
|
+
return state_data.get("value")
|
126
|
+
except Exception:
|
127
|
+
return None
|
128
|
+
|
129
|
+
def create_addon_upgrade_policy(
|
130
|
+
self,
|
131
|
+
ocm_api: OCMBaseClient,
|
132
|
+
cluster_id: str,
|
133
|
+
addon_id: str,
|
134
|
+
schedule_type: str,
|
135
|
+
version: str,
|
136
|
+
next_run: str,
|
137
|
+
) -> None:
|
138
|
+
"""
|
139
|
+
Creates a new Addon Upgrade Policy
|
140
|
+
"""
|
141
|
+
spec = {
|
142
|
+
"version": version,
|
143
|
+
"schedule_type": schedule_type,
|
144
|
+
"addon_id": addon_id,
|
145
|
+
"cluster_id": cluster_id,
|
146
|
+
"upgrade_type": "ADDON",
|
147
|
+
}
|
148
|
+
ocm_api.post(
|
149
|
+
f"{self.addon_base_api_path()}/clusters/{cluster_id}/addon_upgrade_policies",
|
150
|
+
spec,
|
38
151
|
)
|
39
|
-
addons.append(OCMAddonInstallation(**addon))
|
40
|
-
return addons
|
41
152
|
|
153
|
+
def delete_addon_upgrade_policy(
|
154
|
+
self, ocm_api: OCMBaseClient, cluster_id: str, policy_id: str
|
155
|
+
) -> None:
|
156
|
+
"""
|
157
|
+
Deletes an existing Addon Upgrade Policy
|
158
|
+
"""
|
159
|
+
ocm_api.delete(
|
160
|
+
f"{self.addon_base_api_path()}/clusters/{cluster_id}/addon_upgrade_policies/{policy_id}"
|
161
|
+
)
|
42
162
|
|
43
|
-
|
163
|
+
|
164
|
+
class AddonServiceV2(AddonService):
|
44
165
|
"""
|
45
|
-
|
166
|
+
The dedicated addon-service API that is part of OCM.
|
46
167
|
"""
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
168
|
+
|
169
|
+
def addon_base_api_path(self) -> str:
|
170
|
+
return "/api/addons_mgmt/v1"
|
171
|
+
|
172
|
+
def get_addon_upgrade_policies(
|
173
|
+
self, ocm_api: OCMBaseClient, cluster_id: str, addon_id: Optional[str] = None
|
174
|
+
) -> list[dict[str, Any]]:
|
175
|
+
results: list[dict[str, Any]] = []
|
176
|
+
|
177
|
+
for policy in ocm_api.get_paginated(
|
178
|
+
f"{self.addon_base_api_path()}/clusters/{cluster_id}/upgrade_plan"
|
179
|
+
):
|
180
|
+
if addon_id and policy["addon_id"] != addon_id:
|
181
|
+
continue
|
182
|
+
policy_data = {
|
183
|
+
k: v
|
184
|
+
for k, v in policy.items()
|
185
|
+
if k in ADDON_UPGRADE_POLICY_DESIRED_KEYS
|
186
|
+
}
|
187
|
+
results.append(policy_data)
|
188
|
+
|
189
|
+
return results
|
190
|
+
|
191
|
+
def create_addon_upgrade_policy(
|
192
|
+
self,
|
193
|
+
ocm_api: OCMBaseClient,
|
194
|
+
cluster_id: str,
|
195
|
+
addon_id: str,
|
196
|
+
schedule_type: str,
|
197
|
+
version: str,
|
198
|
+
next_run: str,
|
199
|
+
) -> None:
|
200
|
+
"""
|
201
|
+
Schedules an addon upgrade. Leverages addon-service upgrade plans behind the scene.
|
202
|
+
"""
|
203
|
+
spec = {
|
204
|
+
"version": version,
|
205
|
+
"type": schedule_type,
|
206
|
+
"addon_id": addon_id,
|
207
|
+
"cluster_id": cluster_id,
|
208
|
+
"next_run": next_run,
|
209
|
+
}
|
210
|
+
ocm_api.post(
|
211
|
+
f"{self.addon_base_api_path()}/clusters/{cluster_id}/upgrade_plan", spec
|
212
|
+
)
|
213
|
+
|
214
|
+
def delete_addon_upgrade_policy(
|
215
|
+
self, ocm_api: OCMBaseClient, cluster_id: str, policy_id: str
|
216
|
+
) -> None:
|
217
|
+
"""
|
218
|
+
Deletes an existing upgrade plan.
|
219
|
+
"""
|
220
|
+
ocm_api.delete(
|
221
|
+
f"{self.addon_base_api_path()}/clusters/{cluster_id}/upgrade_plan/{policy_id}"
|
222
|
+
)
|
reconcile/utils/ocm/upgrades.py
CHANGED
@@ -8,78 +8,12 @@ from reconcile.utils.ocm.base import OCMVersionGate
|
|
8
8
|
from reconcile.utils.ocm_base_client import OCMBaseClient
|
9
9
|
|
10
10
|
UPGRADE_POLICY_DESIRED_KEYS = {"id", "schedule_type", "schedule", "next_run", "version"}
|
11
|
-
ADDON_UPGRADE_POLICY_DESIRED_KEYS = {
|
12
|
-
"id",
|
13
|
-
"addon_id",
|
14
|
-
"schedule_type",
|
15
|
-
"schedule",
|
16
|
-
"next_run",
|
17
|
-
"version",
|
18
|
-
}
|
19
11
|
|
20
12
|
|
21
13
|
def build_cluster_url(cluster_id: str) -> str:
|
22
14
|
return f"/api/clusters_mgmt/v1/clusters/{cluster_id}"
|
23
15
|
|
24
16
|
|
25
|
-
#
|
26
|
-
# ADDON UPGRADE POLICIES
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
def get_addon_upgrade_policies(
|
31
|
-
ocm_api: OCMBaseClient, cluster_id: str, addon_id: Optional[str] = None
|
32
|
-
) -> list[dict[str, Any]]:
|
33
|
-
results: list[dict[str, Any]] = []
|
34
|
-
|
35
|
-
for policy in ocm_api.get_paginated(
|
36
|
-
f"{build_cluster_url(cluster_id)}/addon_upgrade_policies"
|
37
|
-
):
|
38
|
-
if addon_id and policy["addon_id"] != addon_id:
|
39
|
-
continue
|
40
|
-
policy_data = {
|
41
|
-
k: v for k, v in policy.items() if k in ADDON_UPGRADE_POLICY_DESIRED_KEYS
|
42
|
-
}
|
43
|
-
policy_data["state"] = get_addon_upgrade_policy_state(
|
44
|
-
ocm_api, cluster_id, policy["id"]
|
45
|
-
)
|
46
|
-
results.append(policy_data)
|
47
|
-
|
48
|
-
return results
|
49
|
-
|
50
|
-
|
51
|
-
def get_addon_upgrade_policy_state(
|
52
|
-
ocm_api: OCMBaseClient, cluster_id: str, addon_upgrade_policy_id: str
|
53
|
-
) -> Optional[str]:
|
54
|
-
try:
|
55
|
-
state_data = ocm_api.get(
|
56
|
-
f"{build_cluster_url(cluster_id)}/addon_upgrade_policies/{addon_upgrade_policy_id}/state"
|
57
|
-
)
|
58
|
-
return state_data.get("value")
|
59
|
-
except Exception:
|
60
|
-
return None
|
61
|
-
|
62
|
-
|
63
|
-
def create_addon_upgrade_policy(
|
64
|
-
ocm_api: OCMBaseClient, cluster_id: str, spec: dict
|
65
|
-
) -> None:
|
66
|
-
"""
|
67
|
-
Creates a new Addon Upgrade Policy
|
68
|
-
"""
|
69
|
-
ocm_api.post(f"{build_cluster_url(cluster_id)}/addon_upgrade_policies", spec)
|
70
|
-
|
71
|
-
|
72
|
-
def delete_addon_upgrade_policy(
|
73
|
-
ocm_api: OCMBaseClient, cluster_id: str, policy_id: str
|
74
|
-
) -> None:
|
75
|
-
"""
|
76
|
-
Deletes an existing Addon Upgrade Policy
|
77
|
-
"""
|
78
|
-
ocm_api.delete(
|
79
|
-
f"{build_cluster_url(cluster_id)}/addon_upgrade_policies/{policy_id}"
|
80
|
-
)
|
81
|
-
|
82
|
-
|
83
17
|
#
|
84
18
|
# UPGRADE POLICIES
|
85
19
|
#
|
tools/qontract_cli.py
CHANGED
@@ -46,6 +46,8 @@ from reconcile.aus.base import (
|
|
46
46
|
AbstractUpgradePolicy,
|
47
47
|
AdvancedUpgradeSchedulerBaseIntegration,
|
48
48
|
AdvancedUpgradeSchedulerBaseIntegrationParams,
|
49
|
+
addon_upgrade_policy_soonest_next_run,
|
50
|
+
init_addon_service_version,
|
49
51
|
)
|
50
52
|
from reconcile.aus.models import OrganizationUpgradeSpec
|
51
53
|
from reconcile.change_owners.bundle import NoOpFileDiffResolver
|
@@ -834,7 +836,6 @@ def upgrade_cluster_addon(
|
|
834
836
|
ocm_org: str, cluster: str, addon: str, dry_run: bool, force: bool
|
835
837
|
) -> None:
|
836
838
|
import reconcile.aus.ocm_addons_upgrade_scheduler_org as oauso
|
837
|
-
from reconcile.utils.ocm.upgrades import create_addon_upgrade_policy
|
838
839
|
|
839
840
|
settings = queries.get_app_interface_settings()
|
840
841
|
ocms = queries.get_openshift_cluster_managers()
|
@@ -886,14 +887,21 @@ def upgrade_cluster_addon(
|
|
886
887
|
)
|
887
888
|
print(["create", ocm_org, cluster, addon, ocm_addon_version])
|
888
889
|
if not dry_run:
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
"
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
create_addon_upgrade_policy(
|
890
|
+
# detection addon service version
|
891
|
+
ocm_env_labels = json.loads(ocm_info["environment"].get("labels") or "{}")
|
892
|
+
addon_service_version = (
|
893
|
+
ocm_env_labels.get("feature_flag_addon_service_version") or "v2"
|
894
|
+
)
|
895
|
+
addon_service = init_addon_service_version(addon_service_version)
|
896
|
+
|
897
|
+
addon_service.create_addon_upgrade_policy(
|
898
|
+
ocm_api=ocm._ocm_client,
|
899
|
+
cluster_id=ocm.cluster_ids[cluster],
|
900
|
+
addon_id=ocm_addon["id"],
|
901
|
+
schedule_type="manual",
|
902
|
+
version=ocm_addon_version,
|
903
|
+
next_run=addon_upgrade_policy_soonest_next_run(),
|
904
|
+
)
|
897
905
|
|
898
906
|
|
899
907
|
def has_cluster_account_access(cluster: dict[str, Any]):
|
File without changes
|
File without changes
|
{qontract_reconcile-0.10.1rc693.dist-info → qontract_reconcile-0.10.1rc694.dist-info}/top_level.txt
RENAMED
File without changes
|