qontract-reconcile 0.10.1rc792__py3-none-any.whl → 0.10.1rc796__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.1rc792.dist-info → qontract_reconcile-0.10.1rc796.dist-info}/METADATA +1 -2
- {qontract_reconcile-0.10.1rc792.dist-info → qontract_reconcile-0.10.1rc796.dist-info}/RECORD +19 -16
- reconcile/aus/aus_label_source.py +1 -1
- reconcile/cli.py +16 -0
- reconcile/cluster_auth_rhidp/integration.py +257 -0
- reconcile/gql_definitions/cluster_auth_rhidp/__init__.py +0 -0
- reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +127 -0
- reconcile/gql_definitions/common/clusters_minimal.py +8 -1
- reconcile/ocm_labels/integration.py +11 -8
- reconcile/openshift_base.py +1 -0
- reconcile/openshift_users.py +2 -1
- reconcile/statuspage/atlassian.py +15 -16
- reconcile/utils/saasherder/saasherder.py +3 -0
- tools/qontract_cli.py +0 -64
- {qontract_reconcile-0.10.1rc792.dist-info → qontract_reconcile-0.10.1rc796.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc792.dist-info → qontract_reconcile-0.10.1rc796.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc792.dist-info → qontract_reconcile-0.10.1rc796.dist-info}/top_level.txt +0 -0
- /reconcile/{gql_definitions/ocm_subscription_labels → cluster_auth_rhidp}/__init__.py +0 -0
- /reconcile/{ocm_labels → utils/ocm}/label_sources.py +0 -0
{qontract_reconcile-0.10.1rc792.dist-info → qontract_reconcile-0.10.1rc796.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.1rc796
|
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
|
@@ -46,7 +46,6 @@ Requires-Dist: kubernetes ~=24.0
|
|
46
46
|
Requires-Dist: websocket-client <0.55.0,>=0.35
|
47
47
|
Requires-Dist: sshtunnel >=0.4.0
|
48
48
|
Requires-Dist: croniter <1.1.0,>=1.0.15
|
49
|
-
Requires-Dist: transity-statuspageio <0.1,>=0.0.3
|
50
49
|
Requires-Dist: pydantic ~=1.10.6
|
51
50
|
Requires-Dist: MarkupSafe ==2.1.1
|
52
51
|
Requires-Dist: filetype ~=1.2.0
|
{qontract_reconcile-0.10.1rc792.dist-info → qontract_reconcile-0.10.1rc796.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=IQEXC-Fg-c-9h3j_9JewMYMqgSLkJKT8ChWAHXmtt3k,100436
|
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
|
@@ -62,7 +62,7 @@ reconcile/ocm_groups.py,sha256=CluPyvmwE5JOZS2HQSReC1sD8L1ChhnJlAg8lcwdtxc,3395
|
|
62
62
|
reconcile/ocm_machine_pools.py,sha256=oY4oLPm5Y_ajBV8KFg2LuBQvsZl-CxTjSxEyxg4b2OI,16634
|
63
63
|
reconcile/ocm_update_recommended_version.py,sha256=IYkfLXIprOW1jguZeELcGP1iBPuj-b53R-FTqKulMl8,4204
|
64
64
|
reconcile/ocm_upgrade_scheduler_org_updater.py,sha256=49Ss6sp9_n5F9914gXb-uEap4Vm2t-KPTJRFFViJMIo,4184
|
65
|
-
reconcile/openshift_base.py,sha256=
|
65
|
+
reconcile/openshift_base.py,sha256=mE_NuKgEFsZDeA3kUo4iMsvIF1wN5yemUHeuE0M9fbY,49735
|
66
66
|
reconcile/openshift_cluster_bots.py,sha256=eRPYZqWMKFNxLlSN0QG97V5t1iIESQ0BbGaiaQP5VB0,10940
|
67
67
|
reconcile/openshift_clusterrolebindings.py,sha256=QfSy1Ik8eEY5XObc1Q4xyhqyErZenJmbPv_u9wcDNNo,5864
|
68
68
|
reconcile/openshift_groups.py,sha256=fqBQ6ITDOArkC_zOjskmMigdCUDq3wntLZ0NcppXaFc,9414
|
@@ -86,7 +86,7 @@ reconcile/openshift_saas_deploy_trigger_upstream_jobs.py,sha256=etfBGj7GDXTOhNHK
|
|
86
86
|
reconcile/openshift_serviceaccount_tokens.py,sha256=kc8o6tYDpzYTuX7BGIuZjGR1rC4tAB1tfN-ijCS0AgA,6005
|
87
87
|
reconcile/openshift_tekton_resources.py,sha256=u17OOKPWp9k8WgPXA9RcrMoANYPocNEf-smD7rKRVgE,16278
|
88
88
|
reconcile/openshift_upgrade_watcher.py,sha256=y1DoU--iX5QqDkYGP8YrHv2nH7rbiT9fRwcJ9i3Zp2o,6609
|
89
|
-
reconcile/openshift_users.py,sha256=
|
89
|
+
reconcile/openshift_users.py,sha256=1mhxHvkspSz8dn8zL7PpAG_QZ2rSbYzBuvZ66zWxyL4,5339
|
90
90
|
reconcile/openshift_vault_secrets.py,sha256=9rTqV6wzCQx2Oh712E_Xj8wMG7u8Oh-pY8DWjlv4mZw,1660
|
91
91
|
reconcile/quay_base.py,sha256=WlrTGlpK2Ma9HxXqTRJ_W-7g6e6RM3RlN1vq1ANMP_I,1889
|
92
92
|
reconcile/quay_membership.py,sha256=LKrHwHQDhsBQEP7rUKanks8KTX63qa_93CyHRVwdjfo,6291
|
@@ -121,7 +121,7 @@ reconcile/vault_replication.py,sha256=79GZ_kCimPoQcxkdhkWTQxPOAa46E0mNhf05s_Mk5s
|
|
121
121
|
reconcile/vpc_peerings_validator.py,sha256=Kv22HJVlTW9l9GB2eXwjPWqdDbr_VuvQBNPttox6s5o,7177
|
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
|
-
reconcile/aus/aus_label_source.py,sha256=
|
124
|
+
reconcile/aus/aus_label_source.py,sha256=QG3XuKy5tAyJo9ABPHANrDpECxpkzm2LT5C9Xsu42oI,4183
|
125
125
|
reconcile/aus/base.py,sha256=n53ZtW5MpBitN745mymFxcq7LT5X8si8U0-l8hH6AEc,49878
|
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
|
@@ -168,6 +168,8 @@ reconcile/change_owners/diff.py,sha256=puiyo0dyLxBvbSKUJGIxAsgqs6Omrc_75TEUXk40X
|
|
168
168
|
reconcile/change_owners/implicit_ownership.py,sha256=6BehZvx4IjrphmOt_LLLk9_02Fl5BY5jd00Wuz_PBZk,4234
|
169
169
|
reconcile/change_owners/self_service_roles.py,sha256=4_Dr6ZyRInKLKXCRYaCKLQsoH1USsH-NN72LvnwYsaA,9662
|
170
170
|
reconcile/change_owners/tester.py,sha256=8XGCIa0SIDkhHBDnN8-XCx4OreOmGRU_6N-1MrBuziY,9005
|
171
|
+
reconcile/cluster_auth_rhidp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
172
|
+
reconcile/cluster_auth_rhidp/integration.py,sha256=KIAiP_XFjsOA2OE8oFJa8lD0T1a7EwOmhct2xbj7tr8,9560
|
171
173
|
reconcile/cna/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
172
174
|
reconcile/cna/client.py,sha256=t9gJDrKf4ApBlgu8c4QUbmzrYoSo1QPsnAGfucva2_U,1562
|
173
175
|
reconcile/cna/integration.py,sha256=gSxQAsgErvV2wF4Xnr96kgvX0z0lH_Ez5jH2GFNNSqI,5164
|
@@ -220,6 +222,8 @@ reconcile/gql_definitions/change_owners/__init__.py,sha256=47DEQpj8HBSa-_TImW-5J
|
|
220
222
|
reconcile/gql_definitions/change_owners/queries/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
221
223
|
reconcile/gql_definitions/change_owners/queries/change_types.py,sha256=9S2YRNnSAvutjzuubZIQQe35yd8V2rGKvWSUI6yl11Q,5017
|
222
224
|
reconcile/gql_definitions/change_owners/queries/self_service_roles.py,sha256=gU5qQ_zncXqM41WW_c2NYEZBuXlI9Xwm08D9HF6dP7g,4627
|
225
|
+
reconcile/gql_definitions/cluster_auth_rhidp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
226
|
+
reconcile/gql_definitions/cluster_auth_rhidp/clusters.py,sha256=FTSj4nFD4OY6tjqTEuhAYWx3phckAiANbuVTWOHlo4Q,3267
|
223
227
|
reconcile/gql_definitions/cna/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
224
228
|
reconcile/gql_definitions/cna/queries/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
225
229
|
reconcile/gql_definitions/cna/queries/cna_provisioners.py,sha256=YJOO6vo_q2a4z4Dgx6IN3zTmUDFgSZftqPNLf_U5yzU,2993
|
@@ -234,7 +238,7 @@ reconcile/gql_definitions/common/app_interface_state_settings.py,sha256=VXIK0Hmy
|
|
234
238
|
reconcile/gql_definitions/common/app_interface_vault_settings.py,sha256=w8quvdG0cSq71ZyJokPPp7MyMpoDb6-HLQ3o9JHVGRQ,1771
|
235
239
|
reconcile/gql_definitions/common/aws_vpcs.py,sha256=Dss9dQ3xagnz3Ltg1e9mtG2PAmQGBbUzKCmmzvuN28s,1892
|
236
240
|
reconcile/gql_definitions/common/clusters.py,sha256=eJIbMQltj-Sc7h_QVIeFkbRy1b_QJIkHATfbagxM-yU,21527
|
237
|
-
reconcile/gql_definitions/common/clusters_minimal.py,sha256=
|
241
|
+
reconcile/gql_definitions/common/clusters_minimal.py,sha256=JYrJV_aStmryiiGKyiXhj47qpF_8KilCqy-d9CofBCo,4635
|
238
242
|
reconcile/gql_definitions/common/clusters_with_dms.py,sha256=GJ53P8tgMLh1NfVkaV9_AmaqF9pNUqJZcDkcKzKzUy0,2242
|
239
243
|
reconcile/gql_definitions/common/clusters_with_peering.py,sha256=6mv1m8lc9UDzMWXatkTbYHwBaXoHIIC62qXULsfQN5Y,11822
|
240
244
|
reconcile/gql_definitions/common/github_orgs.py,sha256=rZ0pDAA2_9hF9N-ykRZIxPtEmczTSjuA_k3nkp0k1W0,2039
|
@@ -317,7 +321,6 @@ reconcile/gql_definitions/ocm_labels/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeu
|
|
317
321
|
reconcile/gql_definitions/ocm_labels/clusters.py,sha256=MIVR5c8JxEOjsdGNpB737QyHGkjmHCycY6MAYNclPck,2916
|
318
322
|
reconcile/gql_definitions/ocm_labels/organizations.py,sha256=mmYB5C5Fp_nPzwBDKdKG4qWiLre2VkZ26U_2O-jRKC4,2001
|
319
323
|
reconcile/gql_definitions/ocm_oidc_idp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
320
|
-
reconcile/gql_definitions/ocm_subscription_labels/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
321
324
|
reconcile/gql_definitions/openshift_cluster_bots/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
322
325
|
reconcile/gql_definitions/openshift_cluster_bots/clusters.py,sha256=68meUg2Wgh91gplbPHAIlRWjnGg2RDrwtWd93QK6qRE,3672
|
323
326
|
reconcile/gql_definitions/openshift_groups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -384,8 +387,7 @@ reconcile/ocm/types.py,sha256=ibJYvzfAZyyMFkcF1bP8u3rkXciYJRplt_7Z1pKHFh0,2484
|
|
384
387
|
reconcile/ocm_internal_notifications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
385
388
|
reconcile/ocm_internal_notifications/integration.py,sha256=Gw2oB1Oe1Vvbj-fN_undhkQ2y5tCVhUfW5DenKu9ybM,4395
|
386
389
|
reconcile/ocm_labels/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
387
|
-
reconcile/ocm_labels/integration.py,sha256=
|
388
|
-
reconcile/ocm_labels/label_sources.py,sha256=z5Rg5uMTfRkTi3QbEQK1P82LLciWrSnp65XBEpZf2-o,1877
|
390
|
+
reconcile/ocm_labels/integration.py,sha256=JmqjY_8QI8lgnCgXroiEfj58wkd98fOe5mTiKvkLeOQ,14946
|
389
391
|
reconcile/oum/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
390
392
|
reconcile/oum/base.py,sha256=gw5qDx3VKtIk-VW_g0j5iPdM4qAweqy0YROHJhKHt0M,13596
|
391
393
|
reconcile/oum/labelset.py,sha256=MTOMEyBMbge3JOq0mOKWja-kV3cs0ZId9Ozxv7FJ9Kw,2185
|
@@ -429,7 +431,7 @@ reconcile/skupper_network/models.py,sha256=DNTI7HZv-rqY42GIIxyRuvroHLvdH6rJerjIq
|
|
429
431
|
reconcile/skupper_network/reconciler.py,sha256=XS-1oKBr_1l3dYUAVqUH6gCHg1G5ZuOfY_7fgGVAiFA,9996
|
430
432
|
reconcile/skupper_network/site_controller.py,sha256=A3K-62BjJ5HiFVydV0ouGoD1NwrO7XhAH15BHAcS9fk,1550
|
431
433
|
reconcile/statuspage/__init__.py,sha256=o9vR6sp3ARDQFZrbCEShelTxjF1XgfLaElK_QVt_248,261
|
432
|
-
reconcile/statuspage/atlassian.py,sha256=
|
434
|
+
reconcile/statuspage/atlassian.py,sha256=1W9wQyO0B0qcw5Zrke8h7Rv9xhpXLyMezM7N-5XE8Dg,13665
|
433
435
|
reconcile/statuspage/integration.py,sha256=---tzyl381RddAkIhXb7n3ySjUhuX7FBBI152SYsRfk,3654
|
434
436
|
reconcile/statuspage/page.py,sha256=cJH2sDA8jiAmSdaDitQqNjkyDq_UP2w3s7eauCi-yt4,3740
|
435
437
|
reconcile/statuspage/state.py,sha256=HD9EOoKm_nEqCMLIwW809En3cq5VhyzKJPUbsh-bae8,1617
|
@@ -727,6 +729,7 @@ reconcile/utils/ocm/base.py,sha256=KPS1CgiALlq7INdgTDpN7MmtZ6uQMSWcUDjeGHmp5Z4,1
|
|
727
729
|
reconcile/utils/ocm/cluster_groups.py,sha256=F8oqVqN_4QUnGL0K61zZhoYIzJeP57EcmZpwmoV0mr4,1751
|
728
730
|
reconcile/utils/ocm/clusters.py,sha256=Nw9m-jgN3GHHCh6w9UOBbMV4rtS24_-Ep09jAWQ-_fE,7653
|
729
731
|
reconcile/utils/ocm/identity_providers.py,sha256=dKed09N8iWmn39tI_MpwgVe47x23eLsknGbjMUxtwr4,2175
|
732
|
+
reconcile/utils/ocm/label_sources.py,sha256=z5Rg5uMTfRkTi3QbEQK1P82LLciWrSnp65XBEpZf2-o,1877
|
730
733
|
reconcile/utils/ocm/labels.py,sha256=pRzTE506hKAgVbBNO51IBlGOuCbJmTYDMsL0pWBEwp8,5945
|
731
734
|
reconcile/utils/ocm/ocm.py,sha256=axXuTUpJR-fqhDo6OiDzEygOsR9OCX8ZV1I_Q2vWJQc,36712
|
732
735
|
reconcile/utils/ocm/products.py,sha256=835Wr354wrP4hDhBi6dVMy1ru_G3-C-wCJyjki43KuA,25961
|
@@ -750,7 +753,7 @@ reconcile/utils/runtime/sharding.py,sha256=roCdbnBklhTK_g34zbgQYqzpKPaNQ8J6Xd9XL
|
|
750
753
|
reconcile/utils/saasherder/__init__.py,sha256=J3MBZBFa5YmhqYm08QsjBXz8mFcVOCiOCkyIcw41t7E,343
|
751
754
|
reconcile/utils/saasherder/interfaces.py,sha256=XXY35h8VWQ66z3LBPxaoUAMkIW50264DQiecrzyV6oA,9076
|
752
755
|
reconcile/utils/saasherder/models.py,sha256=1DKXUmiTS_MejUfSpFCeuBLMTgR4ldv2N1tAz8qHAwc,5547
|
753
|
-
reconcile/utils/saasherder/saasherder.py,sha256=
|
756
|
+
reconcile/utils/saasherder/saasherder.py,sha256=Z6indeXBLzo_1w9Utc8Uj27wSe4J0OwBqykYYAqPpnI,86416
|
754
757
|
reconcile/utils/terraform/__init__.py,sha256=zNbiyTWo35AT1sFTElL2j_AA0jJ_yWE_bfFn-nD2xik,250
|
755
758
|
reconcile/utils/terraform/config.py,sha256=5UVrd563TMcvi4ooa5JvWVDW1I3bIWg484u79evfV_8,164
|
756
759
|
reconcile/utils/terraform/config_client.py,sha256=py-Ree-QUYD6Hvng6bM40VgSuttteehIKNgwOSoJO1o,4706
|
@@ -767,7 +770,7 @@ tools/app_interface_metrics_exporter.py,sha256=zkwkxdAUAxjdc-pzx2_oJXG25fo0Fnyd5
|
|
767
770
|
tools/app_interface_reporter.py,sha256=upA-J-n-HXHKVDINRuMR7vTt-iJvQORKUVi9D3leQto,17738
|
768
771
|
tools/glitchtip_access_reporter.py,sha256=oPBnk_YoDuljU3v0FaChzOwwnk4vap1xEE67QEjzdqs,2948
|
769
772
|
tools/glitchtip_access_revalidation.py,sha256=8kbBJk04mkq28kWoRDDkfCGIF3GRg3pJrFAh1sW0dbk,2821
|
770
|
-
tools/qontract_cli.py,sha256=
|
773
|
+
tools/qontract_cli.py,sha256=shVGUSDTqa8KO1H6P6YD4fpygQSzZuGxB-5MdhTtzUs,113982
|
771
774
|
tools/sd_app_sre_alert_report.py,sha256=e9vAdyenUz2f5c8-z-5WY0wv-SJ9aePKDH2r4IwB6pc,5063
|
772
775
|
tools/template_validation.py,sha256=-U-lTGeLaci8yWPEblCJeev2DOlY1jM9QOOh-O1zts8,3376
|
773
776
|
tools/cli_commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -785,8 +788,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
|
|
785
788
|
tools/test/test_qontract_cli.py,sha256=w2l4BHB09k1d-BGJ1jBUNCqDv7zkqYrMHojQXg-21kQ,4155
|
786
789
|
tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
|
787
790
|
tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
|
788
|
-
qontract_reconcile-0.10.
|
789
|
-
qontract_reconcile-0.10.
|
790
|
-
qontract_reconcile-0.10.
|
791
|
-
qontract_reconcile-0.10.
|
792
|
-
qontract_reconcile-0.10.
|
791
|
+
qontract_reconcile-0.10.1rc796.dist-info/METADATA,sha256=GQarCBXsn_w6KRkt0BIseHFItIEHlKjlJUE4UqBfGdQ,2314
|
792
|
+
qontract_reconcile-0.10.1rc796.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
793
|
+
qontract_reconcile-0.10.1rc796.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
|
794
|
+
qontract_reconcile-0.10.1rc796.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
795
|
+
qontract_reconcile-0.10.1rc796.dist-info/RECORD,,
|
@@ -16,7 +16,7 @@ from reconcile.gql_definitions.advanced_upgrade_service.aus_organization import
|
|
16
16
|
query as aus_organizations_query,
|
17
17
|
)
|
18
18
|
from reconcile.gql_definitions.fragments.aus_organization import AUSOCMOrganization
|
19
|
-
from reconcile.
|
19
|
+
from reconcile.utils.ocm.label_sources import (
|
20
20
|
ClusterRef,
|
21
21
|
LabelSource,
|
22
22
|
LabelState,
|
reconcile/cli.py
CHANGED
@@ -2918,6 +2918,22 @@ def rhidp_sso_client(
|
|
2918
2918
|
)
|
2919
2919
|
|
2920
2920
|
|
2921
|
+
@integration.command(
|
2922
|
+
short_help="Manages the OCM subscription labels for clusters with RHIDP authentication. Part of RHIDP."
|
2923
|
+
)
|
2924
|
+
@click.pass_context
|
2925
|
+
def cluster_auth_rhidp(ctx):
|
2926
|
+
from reconcile.cluster_auth_rhidp.integration import (
|
2927
|
+
ClusterAuthRhidpIntegration,
|
2928
|
+
ClusterAuthRhidpIntegrationParams,
|
2929
|
+
)
|
2930
|
+
|
2931
|
+
run_class_integration(
|
2932
|
+
integration=ClusterAuthRhidpIntegration(ClusterAuthRhidpIntegrationParams()),
|
2933
|
+
ctx=ctx.obj,
|
2934
|
+
)
|
2935
|
+
|
2936
|
+
|
2921
2937
|
@integration.command(
|
2922
2938
|
short_help="Automatically provide dedicated Dynatrace tokens to management clusters"
|
2923
2939
|
)
|
@@ -0,0 +1,257 @@
|
|
1
|
+
import logging
|
2
|
+
from collections.abc import Callable, Iterable
|
3
|
+
from typing import Any
|
4
|
+
|
5
|
+
from deepdiff import DeepHash
|
6
|
+
|
7
|
+
from reconcile.gql_definitions.cluster_auth_rhidp.clusters import (
|
8
|
+
ClusterAuthRHIDPV1,
|
9
|
+
ClusterV1,
|
10
|
+
)
|
11
|
+
from reconcile.gql_definitions.cluster_auth_rhidp.clusters import query as cluster_query
|
12
|
+
from reconcile.gql_definitions.common.ocm_environments import (
|
13
|
+
query as ocm_environment_query,
|
14
|
+
)
|
15
|
+
from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment
|
16
|
+
from reconcile.rhidp.common import (
|
17
|
+
AUTH_NAME_LABEL_KEY,
|
18
|
+
ISSUER_LABEL_KEY,
|
19
|
+
RHIDP_NAMESPACE_LABEL_KEY,
|
20
|
+
STATUS_LABEL_KEY,
|
21
|
+
StatusValue,
|
22
|
+
)
|
23
|
+
from reconcile.utils import gql
|
24
|
+
from reconcile.utils.defer import defer
|
25
|
+
from reconcile.utils.differ import diff_mappings
|
26
|
+
from reconcile.utils.disabled_integrations import integration_is_enabled
|
27
|
+
from reconcile.utils.ocm.clusters import discover_clusters_for_organizations
|
28
|
+
from reconcile.utils.ocm.label_sources import ClusterRef, LabelState
|
29
|
+
from reconcile.utils.ocm.labels import add_label, delete_label, update_label
|
30
|
+
from reconcile.utils.ocm_base_client import (
|
31
|
+
OCMAPIClientConfigurationProtocol,
|
32
|
+
OCMBaseClient,
|
33
|
+
init_ocm_base_client,
|
34
|
+
)
|
35
|
+
from reconcile.utils.runtime.integration import (
|
36
|
+
PydanticRunParams,
|
37
|
+
QontractReconcileIntegration,
|
38
|
+
)
|
39
|
+
from reconcile.utils.secret_reader import SecretReaderBase
|
40
|
+
from reconcile.utils.semver_helper import make_semver
|
41
|
+
|
42
|
+
QONTRACT_INTEGRATION = "cluster-auth-rhidp"
|
43
|
+
QONTRACT_INTEGRATION_VERSION = make_semver(1, 0, 0)
|
44
|
+
|
45
|
+
|
46
|
+
class ClusterAuthRhidpIntegrationParams(PydanticRunParams):
|
47
|
+
pass
|
48
|
+
|
49
|
+
|
50
|
+
class ManagedLabelConflictError(Exception):
|
51
|
+
pass
|
52
|
+
|
53
|
+
|
54
|
+
OcmApis = dict[str, OCMBaseClient]
|
55
|
+
|
56
|
+
|
57
|
+
class ClusterAuthRhidpIntegration(
|
58
|
+
QontractReconcileIntegration[ClusterAuthRhidpIntegrationParams]
|
59
|
+
):
|
60
|
+
"""Manages the OCM subscription labels for clusters with RHIDP authentication."""
|
61
|
+
|
62
|
+
@property
|
63
|
+
def name(self) -> str:
|
64
|
+
return QONTRACT_INTEGRATION
|
65
|
+
|
66
|
+
def get_early_exit_desired_state(
|
67
|
+
self, query_func: Callable | None = None
|
68
|
+
) -> dict[str, Any]:
|
69
|
+
"""Return the desired state for early exit."""
|
70
|
+
if not query_func:
|
71
|
+
query_func = gql.get_api().query
|
72
|
+
|
73
|
+
desired = {
|
74
|
+
"subs_labels": self.fetch_desired_state(self.get_clusters(query_func)),
|
75
|
+
}
|
76
|
+
# to figure out wheter to run a PR check of to exit early, a hash value
|
77
|
+
# of the desired state is sufficient
|
78
|
+
return {"hash": DeepHash(desired).get(desired)}
|
79
|
+
|
80
|
+
def get_clusters(self, query_func: Callable) -> list[ClusterV1]:
|
81
|
+
data = cluster_query(query_func)
|
82
|
+
return [
|
83
|
+
c
|
84
|
+
for c in data.clusters or []
|
85
|
+
if integration_is_enabled(self.name, c)
|
86
|
+
# ocm is mandatory
|
87
|
+
and c.ocm
|
88
|
+
and c.spec
|
89
|
+
and c.spec.q_id
|
90
|
+
]
|
91
|
+
|
92
|
+
def get_environments(self, query_func: Callable) -> list[OCMEnvironment]:
|
93
|
+
return ocm_environment_query(query_func).environments
|
94
|
+
|
95
|
+
def fetch_desired_state(self, clusters: Iterable[ClusterV1]) -> LabelState:
|
96
|
+
"""Fetches the desired state of subscription labels for the given clusters."""
|
97
|
+
states: LabelState = {}
|
98
|
+
|
99
|
+
for cluster in clusters:
|
100
|
+
assert cluster.ocm and cluster.spec and cluster.spec.q_id # make mypy happy
|
101
|
+
label = {}
|
102
|
+
if auth := next(
|
103
|
+
(
|
104
|
+
a
|
105
|
+
for a in cluster.auth
|
106
|
+
if isinstance(a, ClusterAuthRHIDPV1) and a.service == "rhidp"
|
107
|
+
),
|
108
|
+
None,
|
109
|
+
):
|
110
|
+
label = {
|
111
|
+
STATUS_LABEL_KEY: auth.status or StatusValue.ENABLED.value,
|
112
|
+
AUTH_NAME_LABEL_KEY: auth.name,
|
113
|
+
}
|
114
|
+
if auth.issuer:
|
115
|
+
label[ISSUER_LABEL_KEY] = auth.issuer
|
116
|
+
cluster_ref = ClusterRef(
|
117
|
+
cluster_id=cluster.spec.q_id,
|
118
|
+
org_id=cluster.ocm.org_id,
|
119
|
+
ocm_env=cluster.ocm.environment.name,
|
120
|
+
name=cluster.name,
|
121
|
+
label_container_href=None,
|
122
|
+
)
|
123
|
+
states[cluster_ref] = label
|
124
|
+
|
125
|
+
return states
|
126
|
+
|
127
|
+
def fetch_current_state(
|
128
|
+
self,
|
129
|
+
ocm_apis: OcmApis,
|
130
|
+
clusters: Iterable[ClusterV1],
|
131
|
+
managed_label_prefixes: Iterable[str],
|
132
|
+
) -> LabelState:
|
133
|
+
"""Fetches the current state of subscription labels for the given clusters.
|
134
|
+
|
135
|
+
If a cluster can't be found in OCM, the resulting dict will not contain a
|
136
|
+
state for it, not even an empty one.
|
137
|
+
"""
|
138
|
+
cluster_ids = {c.spec.q_id for c in clusters if c.spec and c.spec.q_id}
|
139
|
+
states: LabelState = {}
|
140
|
+
for env_name, ocm_api in ocm_apis.items():
|
141
|
+
for cluster_details in discover_clusters_for_organizations(
|
142
|
+
ocm_api=ocm_api,
|
143
|
+
organization_ids=list({
|
144
|
+
c.ocm.org_id
|
145
|
+
for c in clusters
|
146
|
+
if c.ocm and c.ocm.environment.name == env_name
|
147
|
+
}),
|
148
|
+
):
|
149
|
+
if cluster_details.ocm_cluster.id not in cluster_ids:
|
150
|
+
# there might be more clusters in an organization than we care about
|
151
|
+
continue
|
152
|
+
|
153
|
+
filtered_labels = {
|
154
|
+
label: value
|
155
|
+
for label, value in cluster_details.subscription_labels.get_values_dict().items()
|
156
|
+
if label.startswith(tuple(managed_label_prefixes))
|
157
|
+
}
|
158
|
+
states[
|
159
|
+
ClusterRef(
|
160
|
+
cluster_id=cluster_details.ocm_cluster.id,
|
161
|
+
org_id=cluster_details.organization_id,
|
162
|
+
ocm_env=env_name,
|
163
|
+
name=cluster_details.ocm_cluster.name,
|
164
|
+
label_container_href=f"{cluster_details.ocm_cluster.subscription.href}/labels",
|
165
|
+
)
|
166
|
+
] = filtered_labels
|
167
|
+
return states
|
168
|
+
|
169
|
+
def init_ocm_apis(
|
170
|
+
self,
|
171
|
+
environments: Iterable[OCMEnvironment],
|
172
|
+
init_ocm_base_client: Callable[
|
173
|
+
[OCMAPIClientConfigurationProtocol, SecretReaderBase], OCMBaseClient
|
174
|
+
] = init_ocm_base_client,
|
175
|
+
) -> OcmApis:
|
176
|
+
"""Initialize OCM clients for each OCM environment."""
|
177
|
+
return {
|
178
|
+
env.name: init_ocm_base_client(env, self.secret_reader)
|
179
|
+
for env in environments
|
180
|
+
}
|
181
|
+
|
182
|
+
def reconcile(
|
183
|
+
self,
|
184
|
+
dry_run: bool,
|
185
|
+
ocm_apis: OcmApis,
|
186
|
+
current_state: LabelState,
|
187
|
+
desired_state: LabelState,
|
188
|
+
) -> None:
|
189
|
+
# we iterate via the current state because it refers to the clusters we can act on
|
190
|
+
for label_owner_ref, current_labels in current_state.items():
|
191
|
+
ocm_api = ocm_apis[label_owner_ref.ocm_env]
|
192
|
+
desired_labels = desired_state.get(label_owner_ref, {})
|
193
|
+
if current_labels == desired_labels:
|
194
|
+
continue
|
195
|
+
|
196
|
+
diff_result = diff_mappings(current_labels, desired_labels)
|
197
|
+
|
198
|
+
for label_to_add, value in diff_result.add.items():
|
199
|
+
logging.info([
|
200
|
+
"create_label",
|
201
|
+
*label_owner_ref.identity_labels(),
|
202
|
+
f"{label_to_add}={value}",
|
203
|
+
])
|
204
|
+
if not dry_run:
|
205
|
+
add_label(
|
206
|
+
ocm_api=ocm_api,
|
207
|
+
label_container_href=label_owner_ref.required_label_container_href(),
|
208
|
+
label=label_to_add,
|
209
|
+
value=value,
|
210
|
+
)
|
211
|
+
for label_to_rm, value in diff_result.delete.items():
|
212
|
+
logging.info([
|
213
|
+
"delete_label",
|
214
|
+
*label_owner_ref.identity_labels(),
|
215
|
+
f"{label_to_rm}={value}",
|
216
|
+
])
|
217
|
+
if not dry_run:
|
218
|
+
delete_label(
|
219
|
+
ocm_api=ocm_api,
|
220
|
+
label_container_href=label_owner_ref.required_label_container_href(),
|
221
|
+
label=label_to_rm,
|
222
|
+
)
|
223
|
+
for label_to_update, diff_pair in diff_result.change.items():
|
224
|
+
value = diff_pair.desired
|
225
|
+
logging.info([
|
226
|
+
"update_label",
|
227
|
+
*label_owner_ref.identity_labels(),
|
228
|
+
f"{label_to_update}={value}",
|
229
|
+
])
|
230
|
+
if not dry_run:
|
231
|
+
update_label(
|
232
|
+
ocm_api=ocm_api,
|
233
|
+
label_container_href=label_owner_ref.required_label_container_href(),
|
234
|
+
label=label_to_update,
|
235
|
+
value=value,
|
236
|
+
)
|
237
|
+
|
238
|
+
@defer
|
239
|
+
def run(self, dry_run: bool, defer: Callable | None = None) -> None:
|
240
|
+
"""Run the integration."""
|
241
|
+
gql_api = gql.get_api()
|
242
|
+
clusters = self.get_clusters(gql_api.query)
|
243
|
+
environments = self.get_environments(gql_api.query)
|
244
|
+
ocm_apis = self.init_ocm_apis(environments, init_ocm_base_client)
|
245
|
+
if defer:
|
246
|
+
defer(lambda: [ocm_api.close() for ocm_api in ocm_apis.values()]) # type: ignore
|
247
|
+
|
248
|
+
current_state = self.fetch_current_state(
|
249
|
+
ocm_apis, clusters, managed_label_prefixes=[RHIDP_NAMESPACE_LABEL_KEY]
|
250
|
+
)
|
251
|
+
desired_state = self.fetch_desired_state(clusters)
|
252
|
+
self.reconcile(
|
253
|
+
dry_run=dry_run,
|
254
|
+
ocm_apis=ocm_apis,
|
255
|
+
current_state=current_state,
|
256
|
+
desired_state=desired_state,
|
257
|
+
)
|
File without changes
|
@@ -0,0 +1,127 @@
|
|
1
|
+
"""
|
2
|
+
Generated by qenerate plugin=pydantic_v1. DO NOT MODIFY MANUALLY!
|
3
|
+
"""
|
4
|
+
from collections.abc import Callable # noqa: F401 # pylint: disable=W0611
|
5
|
+
from datetime import datetime # noqa: F401 # pylint: disable=W0611
|
6
|
+
from enum import Enum # noqa: F401 # pylint: disable=W0611
|
7
|
+
from typing import ( # noqa: F401 # pylint: disable=W0611
|
8
|
+
Any,
|
9
|
+
Optional,
|
10
|
+
Union,
|
11
|
+
)
|
12
|
+
|
13
|
+
from pydantic import ( # noqa: F401 # pylint: disable=W0611
|
14
|
+
BaseModel,
|
15
|
+
Extra,
|
16
|
+
Field,
|
17
|
+
Json,
|
18
|
+
)
|
19
|
+
|
20
|
+
from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment
|
21
|
+
|
22
|
+
|
23
|
+
DEFINITION = """
|
24
|
+
fragment OCMEnvironment on OpenShiftClusterManagerEnvironment_v1 {
|
25
|
+
name
|
26
|
+
labels
|
27
|
+
url
|
28
|
+
accessTokenClientId
|
29
|
+
accessTokenUrl
|
30
|
+
accessTokenClientSecret {
|
31
|
+
... VaultSecret
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
fragment VaultSecret on VaultSecret_v1 {
|
36
|
+
path
|
37
|
+
field
|
38
|
+
version
|
39
|
+
format
|
40
|
+
}
|
41
|
+
|
42
|
+
query ClusterAuthRhidp {
|
43
|
+
clusters: clusters_v1 {
|
44
|
+
name
|
45
|
+
spec {
|
46
|
+
id
|
47
|
+
}
|
48
|
+
ocm {
|
49
|
+
environment {
|
50
|
+
...OCMEnvironment
|
51
|
+
}
|
52
|
+
orgId
|
53
|
+
}
|
54
|
+
disable {
|
55
|
+
integrations
|
56
|
+
}
|
57
|
+
auth {
|
58
|
+
service
|
59
|
+
... on ClusterAuthRHIDP_v1 {
|
60
|
+
name
|
61
|
+
status
|
62
|
+
issuer
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
"""
|
68
|
+
|
69
|
+
|
70
|
+
class ConfiguredBaseModel(BaseModel):
|
71
|
+
class Config:
|
72
|
+
smart_union=True
|
73
|
+
extra=Extra.forbid
|
74
|
+
|
75
|
+
|
76
|
+
class ClusterSpecV1(ConfiguredBaseModel):
|
77
|
+
q_id: Optional[str] = Field(..., alias="id")
|
78
|
+
|
79
|
+
|
80
|
+
class OpenShiftClusterManagerV1(ConfiguredBaseModel):
|
81
|
+
environment: OCMEnvironment = Field(..., alias="environment")
|
82
|
+
org_id: str = Field(..., alias="orgId")
|
83
|
+
|
84
|
+
|
85
|
+
class DisableClusterAutomationsV1(ConfiguredBaseModel):
|
86
|
+
integrations: Optional[list[str]] = Field(..., alias="integrations")
|
87
|
+
|
88
|
+
|
89
|
+
class ClusterAuthV1(ConfiguredBaseModel):
|
90
|
+
service: str = Field(..., alias="service")
|
91
|
+
|
92
|
+
|
93
|
+
class ClusterAuthRHIDPV1(ClusterAuthV1):
|
94
|
+
name: str = Field(..., alias="name")
|
95
|
+
status: Optional[str] = Field(..., alias="status")
|
96
|
+
issuer: Optional[str] = Field(..., alias="issuer")
|
97
|
+
|
98
|
+
|
99
|
+
class ClusterV1(ConfiguredBaseModel):
|
100
|
+
name: str = Field(..., alias="name")
|
101
|
+
spec: Optional[ClusterSpecV1] = Field(..., alias="spec")
|
102
|
+
ocm: Optional[OpenShiftClusterManagerV1] = Field(..., alias="ocm")
|
103
|
+
disable: Optional[DisableClusterAutomationsV1] = Field(..., alias="disable")
|
104
|
+
auth: list[Union[ClusterAuthRHIDPV1, ClusterAuthV1]] = Field(..., alias="auth")
|
105
|
+
|
106
|
+
|
107
|
+
class ClusterAuthRhidpQueryData(ConfiguredBaseModel):
|
108
|
+
clusters: Optional[list[ClusterV1]] = Field(..., alias="clusters")
|
109
|
+
|
110
|
+
|
111
|
+
def query(query_func: Callable, **kwargs: Any) -> ClusterAuthRhidpQueryData:
|
112
|
+
"""
|
113
|
+
This is a convenience function which queries and parses the data into
|
114
|
+
concrete types. It should be compatible with most GQL clients.
|
115
|
+
You do not have to use it to consume the generated data classes.
|
116
|
+
Alternatively, you can also mime and alternate the behavior
|
117
|
+
of this function in the caller.
|
118
|
+
|
119
|
+
Parameters:
|
120
|
+
query_func (Callable): Function which queries your GQL Server
|
121
|
+
kwargs: optional arguments that will be passed to the query function
|
122
|
+
|
123
|
+
Returns:
|
124
|
+
ClusterAuthRhidpQueryData: queried data parsed into generated classes
|
125
|
+
"""
|
126
|
+
raw_data: dict[Any, Any] = query_func(DEFINITION, **kwargs)
|
127
|
+
return ClusterAuthRhidpQueryData(**raw_data)
|
@@ -80,6 +80,9 @@ query ClustersMinimal($name: String) {
|
|
80
80
|
... on ClusterAuthOIDC_v1 {
|
81
81
|
name
|
82
82
|
}
|
83
|
+
... on ClusterAuthRHIDP_v1 {
|
84
|
+
name
|
85
|
+
}
|
83
86
|
}
|
84
87
|
}
|
85
88
|
}
|
@@ -121,6 +124,10 @@ class ClusterAuthOIDCV1(ClusterAuthV1):
|
|
121
124
|
name: str = Field(..., alias="name")
|
122
125
|
|
123
126
|
|
127
|
+
class ClusterAuthRHIDPV1(ClusterAuthV1):
|
128
|
+
name: str = Field(..., alias="name")
|
129
|
+
|
130
|
+
|
124
131
|
class ClusterV1(ConfiguredBaseModel):
|
125
132
|
name: str = Field(..., alias="name")
|
126
133
|
server_url: str = Field(..., alias="serverUrl")
|
@@ -136,7 +143,7 @@ class ClusterV1(ConfiguredBaseModel):
|
|
136
143
|
cluster_admin_automation_token: Optional[VaultSecret] = Field(..., alias="clusterAdminAutomationToken")
|
137
144
|
internal: Optional[bool] = Field(..., alias="internal")
|
138
145
|
disable: Optional[DisableClusterAutomationsV1] = Field(..., alias="disable")
|
139
|
-
auth: list[Union[ClusterAuthGithubOrgTeamV1, ClusterAuthGithubOrgV1, ClusterAuthOIDCV1, ClusterAuthV1]] = Field(..., alias="auth")
|
146
|
+
auth: list[Union[ClusterAuthGithubOrgTeamV1, ClusterAuthGithubOrgV1, ClusterAuthOIDCV1, ClusterAuthRHIDPV1, ClusterAuthV1]] = Field(..., alias="auth")
|
140
147
|
|
141
148
|
|
142
149
|
class ClustersMinimalQueryData(ConfiguredBaseModel):
|
@@ -27,17 +27,18 @@ from reconcile.gql_definitions.ocm_labels.organizations import OpenShiftClusterM
|
|
27
27
|
from reconcile.gql_definitions.ocm_labels.organizations import (
|
28
28
|
query as organization_query,
|
29
29
|
)
|
30
|
-
from reconcile.ocm_labels.label_sources import (
|
31
|
-
ClusterRef,
|
32
|
-
LabelSource,
|
33
|
-
LabelState,
|
34
|
-
OrgRef,
|
35
|
-
)
|
36
30
|
from reconcile.utils import gql
|
31
|
+
from reconcile.utils.defer import defer
|
37
32
|
from reconcile.utils.differ import diff_mappings
|
38
33
|
from reconcile.utils.disabled_integrations import integration_is_enabled
|
39
34
|
from reconcile.utils.helpers import flatten
|
40
35
|
from reconcile.utils.ocm.clusters import discover_clusters_for_organizations
|
36
|
+
from reconcile.utils.ocm.label_sources import (
|
37
|
+
ClusterRef,
|
38
|
+
LabelSource,
|
39
|
+
LabelState,
|
40
|
+
OrgRef,
|
41
|
+
)
|
41
42
|
from reconcile.utils.ocm.labels import (
|
42
43
|
add_label,
|
43
44
|
build_organization_labels_href,
|
@@ -138,14 +139,16 @@ class OcmLabelsIntegration(QontractReconcileIntegration[OcmLabelsIntegrationPara
|
|
138
139
|
# of the desired state is sufficient
|
139
140
|
return {"hash": DeepHash(desired).get(desired)}
|
140
141
|
|
141
|
-
|
142
|
+
@defer
|
143
|
+
def run(self, dry_run: bool, defer: Callable | None = None) -> None:
|
142
144
|
gqlapi = gql.get_api()
|
143
|
-
self.get_early_exit_desired_state()
|
144
145
|
clusters = self.get_clusters(gqlapi.query)
|
145
146
|
organizations = self.get_organizations(gqlapi.query)
|
146
147
|
environments = self.get_environments(gqlapi.query)
|
147
148
|
|
148
149
|
self.ocm_apis = self.init_ocm_apis(environments, init_ocm_base_client)
|
150
|
+
if defer:
|
151
|
+
defer(lambda: [ocm_api.close() for ocm_api in self.ocm_apis.values()]) # type: ignore
|
149
152
|
|
150
153
|
# organization labels
|
151
154
|
orgs_current_state, orgs_desired_state = self.fetch_organization_label_states(
|
reconcile/openshift_base.py
CHANGED
reconcile/openshift_users.py
CHANGED
@@ -18,6 +18,7 @@ from reconcile import (
|
|
18
18
|
)
|
19
19
|
from reconcile.gql_definitions.common.clusters_minimal import (
|
20
20
|
ClusterAuthOIDCV1,
|
21
|
+
ClusterAuthRHIDPV1,
|
21
22
|
ClusterV1,
|
22
23
|
)
|
23
24
|
from reconcile.typed_queries.app_interface_vault_settings import (
|
@@ -51,7 +52,7 @@ def get_cluster_users(
|
|
51
52
|
identity_prefixes = ["github"]
|
52
53
|
|
53
54
|
for auth in cluster_info.auth:
|
54
|
-
if isinstance(auth, ClusterAuthOIDCV1):
|
55
|
+
if isinstance(auth, (ClusterAuthOIDCV1, ClusterAuthRHIDPV1)):
|
55
56
|
identity_prefixes.append(auth.name)
|
56
57
|
|
57
58
|
for u in oc.get_users():
|
@@ -7,7 +7,6 @@ from typing import (
|
|
7
7
|
)
|
8
8
|
|
9
9
|
import requests
|
10
|
-
import statuspageio # type: ignore
|
11
10
|
from pydantic import BaseModel
|
12
11
|
from requests import Response
|
13
12
|
from sretoolbox.utils import retry
|
@@ -49,14 +48,9 @@ class AtlassianAPI(Protocol):
|
|
49
48
|
def delete_component(self, id: str) -> None: ...
|
50
49
|
|
51
50
|
|
52
|
-
class
|
51
|
+
class AtlassianRESTAPI:
|
53
52
|
"""
|
54
|
-
This API class wraps the statuspageio
|
55
|
-
This class is named Legacy for a couple reasons:
|
56
|
-
* the underlying library is not maintained anymore
|
57
|
-
* the library has no type annotated
|
58
|
-
* the library does not support pagination which becomes important for this API
|
59
|
-
Therefore this lib will be replaced by a think wrapper based on uplink in an upcoming PR.
|
53
|
+
This API class wraps the statuspageio REST API for basic component operations.
|
60
54
|
"""
|
61
55
|
|
62
56
|
def __init__(self, page_id: str, api_url: str, token: str):
|
@@ -64,9 +58,6 @@ class LegacyLibAtlassianAPI:
|
|
64
58
|
self.api_url = api_url
|
65
59
|
self.token = token
|
66
60
|
self.auth_headers = {"Authorization": f"OAuth {self.token}"}
|
67
|
-
self._client = statuspageio.Client(
|
68
|
-
api_key=self.token, page_id=self.page_id, organization_id="unset"
|
69
|
-
)
|
70
61
|
|
71
62
|
@retry(max_attempts=10)
|
72
63
|
def _do_get(self, url: str, params: dict[str, Any]) -> Response:
|
@@ -96,14 +87,22 @@ class LegacyLibAtlassianAPI:
|
|
96
87
|
return all_components
|
97
88
|
|
98
89
|
def update_component(self, id: str, data: dict[str, Any]) -> None:
|
99
|
-
self.
|
90
|
+
url = f"{self.api_url}/v1/pages/{self.page_id}/components/{id}"
|
91
|
+
requests.patch(
|
92
|
+
url, json={"component": data}, headers=self.auth_headers
|
93
|
+
).raise_for_status()
|
100
94
|
|
101
95
|
def create_component(self, data: dict[str, Any]) -> str:
|
102
|
-
|
103
|
-
|
96
|
+
url = f"{self.api_url}/v1/pages/{self.page_id}/components"
|
97
|
+
response = requests.post(
|
98
|
+
url, json={"component": data}, headers=self.auth_headers
|
99
|
+
)
|
100
|
+
response.raise_for_status()
|
101
|
+
return response.json()["id"]
|
104
102
|
|
105
103
|
def delete_component(self, id: str) -> None:
|
106
|
-
self.
|
104
|
+
url = f"{self.api_url}/v1/pages/{self.page_id}/components/{id}"
|
105
|
+
requests.delete(url, headers=self.auth_headers).raise_for_status()
|
107
106
|
|
108
107
|
|
109
108
|
class AtlassianStatusPageProvider(StatusPageProvider):
|
@@ -364,7 +363,7 @@ def init_provider_for_page(
|
|
364
363
|
"""
|
365
364
|
return AtlassianStatusPageProvider(
|
366
365
|
page_name=page.name,
|
367
|
-
api=
|
366
|
+
api=AtlassianRESTAPI(
|
368
367
|
page_id=page.page_id,
|
369
368
|
api_url=page.api_url,
|
370
369
|
token=token,
|
@@ -95,6 +95,7 @@ TARGET_CONFIG_HASH = "target_config_hash"
|
|
95
95
|
|
96
96
|
|
97
97
|
UNIQUE_SAAS_FILE_ENV_COMBO_LEN = 56
|
98
|
+
REQUEST_TIMEOUT = 60
|
98
99
|
|
99
100
|
|
100
101
|
def is_commit_sha(ref: str) -> bool:
|
@@ -1159,6 +1160,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
1159
1160
|
username=username,
|
1160
1161
|
password=password,
|
1161
1162
|
auth_server=image_auth.auth_server,
|
1163
|
+
timeout=REQUEST_TIMEOUT,
|
1162
1164
|
)
|
1163
1165
|
|
1164
1166
|
# basic auth fallback for backwards compatibility
|
@@ -1168,6 +1170,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
1168
1170
|
username=image_auth.username,
|
1169
1171
|
password=image_auth.password,
|
1170
1172
|
auth_server=image_auth.auth_server,
|
1173
|
+
timeout=REQUEST_TIMEOUT,
|
1171
1174
|
)
|
1172
1175
|
except Exception as e:
|
1173
1176
|
logging.error(
|
tools/qontract_cli.py
CHANGED
@@ -32,7 +32,6 @@ from rich.console import (
|
|
32
32
|
)
|
33
33
|
from rich.table import Table
|
34
34
|
from rich.tree import Tree
|
35
|
-
from sretoolbox.utils import threaded
|
36
35
|
|
37
36
|
import reconcile.aus.base as aus
|
38
37
|
import reconcile.openshift_base as ob
|
@@ -1197,69 +1196,6 @@ def clusters_aws_account_ids(ctx):
|
|
1197
1196
|
print_output(ctx.obj["options"], results, columns)
|
1198
1197
|
|
1199
1198
|
|
1200
|
-
@get.command()
|
1201
|
-
@click.pass_context
|
1202
|
-
def terraform_users_credentials(ctx) -> None:
|
1203
|
-
credentials = []
|
1204
|
-
state = init_state(integration="account-notifier")
|
1205
|
-
|
1206
|
-
skip_accounts, appsre_pgp_key, _ = tfu.get_reencrypt_settings()
|
1207
|
-
|
1208
|
-
if skip_accounts:
|
1209
|
-
accounts, working_dirs, _, aws_api = tfu.setup(
|
1210
|
-
False,
|
1211
|
-
1,
|
1212
|
-
skip_accounts,
|
1213
|
-
account_name=None,
|
1214
|
-
appsre_pgp_key=appsre_pgp_key,
|
1215
|
-
)
|
1216
|
-
|
1217
|
-
tf = Terraform(
|
1218
|
-
tfu.QONTRACT_INTEGRATION,
|
1219
|
-
tfu.QONTRACT_INTEGRATION_VERSION,
|
1220
|
-
tfu.QONTRACT_TF_PREFIX,
|
1221
|
-
accounts,
|
1222
|
-
working_dirs,
|
1223
|
-
10,
|
1224
|
-
aws_api,
|
1225
|
-
init_users=True,
|
1226
|
-
)
|
1227
|
-
for account, output in tf.outputs.items():
|
1228
|
-
if account in skip_accounts:
|
1229
|
-
user_passwords = tf.format_output(output, tf.OUTPUT_TYPE_PASSWORDS)
|
1230
|
-
console_urls = tf.format_output(output, tf.OUTPUT_TYPE_CONSOLEURLS)
|
1231
|
-
for user_name, enc_password in user_passwords.items():
|
1232
|
-
item = {
|
1233
|
-
"account": account,
|
1234
|
-
"console_url": console_urls[account],
|
1235
|
-
"user_name": user_name,
|
1236
|
-
"encrypted_password": enc_password,
|
1237
|
-
}
|
1238
|
-
credentials.append(item)
|
1239
|
-
|
1240
|
-
secrets = state.ls()
|
1241
|
-
|
1242
|
-
def _get_secret(secret_key: str):
|
1243
|
-
if secret_key.startswith("/output/"):
|
1244
|
-
secret_data = state.get(secret_key[1:])
|
1245
|
-
if secret_data["account"] not in skip_accounts:
|
1246
|
-
return secret_data
|
1247
|
-
return None
|
1248
|
-
|
1249
|
-
secret_result = threaded.run(
|
1250
|
-
_get_secret,
|
1251
|
-
secrets,
|
1252
|
-
10,
|
1253
|
-
)
|
1254
|
-
|
1255
|
-
for secret in secret_result:
|
1256
|
-
if secret and secret["account"] not in skip_accounts:
|
1257
|
-
credentials.append(secret)
|
1258
|
-
|
1259
|
-
columns = ["account", "console_url", "user_name", "encrypted_password"]
|
1260
|
-
print_output(ctx.obj["options"], credentials, columns)
|
1261
|
-
|
1262
|
-
|
1263
1199
|
@root.command()
|
1264
1200
|
@click.argument("account_name")
|
1265
1201
|
@click.pass_context
|
File without changes
|
File without changes
|
{qontract_reconcile-0.10.1rc792.dist-info → qontract_reconcile-0.10.1rc796.dist-info}/top_level.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|