qontract-reconcile 0.10.2.dev294__py3-none-any.whl → 0.10.2.dev295__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.2.dev294.dist-info → qontract_reconcile-0.10.2.dev295.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.2.dev294.dist-info → qontract_reconcile-0.10.2.dev295.dist-info}/RECORD +10 -10
- reconcile/aws_iam_password_reset.py +5 -5
- reconcile/ocm_additional_routers.py +7 -3
- reconcile/queries.py +227 -103
- reconcile/utils/ocm/ocm.py +3 -3
- tools/app_interface_reporter.py +36 -28
- tools/qontract_cli.py +28 -16
- {qontract_reconcile-0.10.2.dev294.dist-info → qontract_reconcile-0.10.2.dev295.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev294.dist-info → qontract_reconcile-0.10.2.dev295.dist-info}/entry_points.txt +0 -0
{qontract_reconcile-0.10.2.dev294.dist-info → qontract_reconcile-0.10.2.dev295.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.2.
|
3
|
+
Version: 0.10.2.dev295
|
4
4
|
Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
|
5
5
|
Project-URL: homepage, https://github.com/app-sre/qontract-reconcile
|
6
6
|
Project-URL: repository, https://github.com/app-sre/qontract-reconcile
|
{qontract_reconcile-0.10.2.dev294.dist-info → qontract_reconcile-0.10.2.dev295.dist-info}/RECORD
RENAMED
@@ -4,7 +4,7 @@ reconcile/acs_rbac.py,sha256=15vNfNzdG_DeXaJ-f5m8DSaJh__LUK766_xAECqyTsg,22657
|
|
4
4
|
reconcile/aws_ami_share.py,sha256=M_gT7y3cSAyT_Pm90PBCNDSmbZtqREqe2jNETh0i9Qs,3808
|
5
5
|
reconcile/aws_ecr_image_pull_secrets.py,sha256=F58PtX1GlB9XHqj8hGy9ItiTznXLAAKTNlWD9iT2MWI,2593
|
6
6
|
reconcile/aws_iam_keys.py,sha256=pVqaXus2pH1LcRlog0C9UsWFttW420tuf7n_Ox-OJs4,4091
|
7
|
-
reconcile/aws_iam_password_reset.py,sha256=
|
7
|
+
reconcile/aws_iam_password_reset.py,sha256=5oajSspJVAvpGd445hKsxtEGYb75dM4l1_PJTzrfHk0,3253
|
8
8
|
reconcile/aws_support_cases_sos.py,sha256=G9g0oM6ohvuJ5N592ePjiPeaDug4_vapAy58RyG-S3Y,3478
|
9
9
|
reconcile/blackbox_exporter_endpoint_monitoring.py,sha256=O1wFp52EyF538c6txaWBs8eMtUIy19gyHZ6VzJ6QXS8,3512
|
10
10
|
reconcile/checkpoint.py,sha256=gjtS8g6KIyKFYlHMSZjAqDUOlVh83nh4go-9yNrhWZU,5016
|
@@ -44,7 +44,7 @@ reconcile/jenkins_worker_fleets.py,sha256=tLFEF3ijnqF0jA7hgmFOOrshmfjGYXHFlQcvMZ
|
|
44
44
|
reconcile/jira_permissions_validator.py,sha256=nVHZg7kNn04Q-ryNM20wthMrhXos28g3O9b0ahzxAKc,14690
|
45
45
|
reconcile/ldap_users.py,sha256=oP1CAxmgSi3zDJ3vKTPySjap6WmEX1U469FmFrov5l4,4599
|
46
46
|
reconcile/mr_client_gateway.py,sha256=3L21YncbetuUI3HYvDAEb5JX5HO5KG2CfUyjapX3w8E,2063
|
47
|
-
reconcile/ocm_additional_routers.py,sha256=
|
47
|
+
reconcile/ocm_additional_routers.py,sha256=FUtMeh14i1u2TJ5LSL0pAVjkdBRB7_FietObWO0s_UU,3942
|
48
48
|
reconcile/ocm_addons.py,sha256=b59NWAMmd_zW4pxAH7hm8jzAkis0VZrUBmPYgduVlJc,3684
|
49
49
|
reconcile/ocm_addons_upgrade_tests_trigger.py,sha256=A9zXeYG-_52DsS1dz47yDSnHz62du5XpPBlaeRa6zxY,3975
|
50
50
|
reconcile/ocm_aws_infrastructure_access.py,sha256=f-zVCEf0ucdslhWvfeLcXxQ6Y4xtfCXUG6pxswGgWnU,7251
|
@@ -88,7 +88,7 @@ reconcile/quay_mirror.py,sha256=pA1_OujRduwQ6dYljoWXU_VJgAwlv7DzThk26ymKmGs,1432
|
|
88
88
|
reconcile/quay_mirror_org.py,sha256=2xLD-PZggP33LhZYxun5I3deF8hwGH9zueMtAByphzE,10842
|
89
89
|
reconcile/quay_permissions.py,sha256=BF539lRxjpgwm88WzazklzgaCF_ipRALwbO2AdpqUqE,4388
|
90
90
|
reconcile/quay_repos.py,sha256=woB2afCBgz0UPekHcYtV8zwQCZHZZBL8VDf82ATWZxE,7524
|
91
|
-
reconcile/queries.py,sha256=
|
91
|
+
reconcile/queries.py,sha256=FLUZBtFC2S-e6yjtC1Oq968CJP6t3nc36NPj0wYa0bE,53472
|
92
92
|
reconcile/query_validator.py,sha256=csOSkKxcf6ZlpchJu4ck2jLYKUN6y1l-UmSQUFHgssY,1618
|
93
93
|
reconcile/requests_sender.py,sha256=914iluuF4UVgG3VyxxtnHOu4yf6YKS2fIy6PViSsFTQ,3875
|
94
94
|
reconcile/resource_scraper.py,sha256=sg10j7lwAE8JxsyBTaxixOR3QYnePctsNuwOLiz4QVg,2309
|
@@ -728,7 +728,7 @@ reconcile/utils/ocm/identity_providers.py,sha256=dKed09N8iWmn39tI_MpwgVe47x23eLs
|
|
728
728
|
reconcile/utils/ocm/label_sources.py,sha256=ES_5VP4X6gsRxMFZ95WgbwE_HqqIUo_JRjHjdGYw6Ss,1846
|
729
729
|
reconcile/utils/ocm/labels.py,sha256=CmAgaOEPiaUb4gLtKab9vNkSDJceuREPd4ApgGcIA1U,6240
|
730
730
|
reconcile/utils/ocm/manifests.py,sha256=Q6kgOeiAwLbJY_vO_BEW2oePvbLDZcMZk20YpJJGpOA,1195
|
731
|
-
reconcile/utils/ocm/ocm.py,sha256=
|
731
|
+
reconcile/utils/ocm/ocm.py,sha256=tHRGWdpHkvrq6XakDjE1KrXNijdh-ubxKgK183fdhyQ,31378
|
732
732
|
reconcile/utils/ocm/products.py,sha256=UtWpkAvSMCxPOulEB7aV5ZY8ej_rmErlE_HVdm9Gnjk,26021
|
733
733
|
reconcile/utils/ocm/search_filters.py,sha256=09p4Wq1d1HGrDiinf1dmLJ46VtFhkkRCOL4V-N-zwjY,14808
|
734
734
|
reconcile/utils/ocm/service_log.py,sha256=RG1f0MMn6joKaRCAm2xveSJCavdOPP1BVo9FXecDxaI,2018
|
@@ -765,12 +765,12 @@ reconcile/utils/unleash/server.py,sha256=907gDh9Ee8UxLqusnfpzE-7LUnttB38D4xhVJ0v
|
|
765
765
|
tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
766
766
|
tools/alert_report.py,sha256=cyQTei8_SYOggW_6uYvzhrF7Nae-9xOz-jmh9O9V8R8,5589
|
767
767
|
tools/app_interface_metrics_exporter.py,sha256=mCi6SZf20mo5yvRI2VoqmrCdz46Ph3JhpEJPvryXncY,2261
|
768
|
-
tools/app_interface_reporter.py,sha256=
|
768
|
+
tools/app_interface_reporter.py,sha256=m6zAtwIR0l388khSFyoytDSjyEoSg5fjXMAMA9KhCIU,17602
|
769
769
|
tools/app_sre_tekton_access_reporter.py,sha256=5qmkevJdlb2j_lpGC5Pu1Pmo0eomX5ZxzS_GNkqHAEE,3104
|
770
770
|
tools/app_sre_tekton_access_revalidation.py,sha256=vwL1o_j7oSTOhrHNH1znpgjA2LHGzb8yc5iG3aaY4m0,2684
|
771
771
|
tools/glitchtip_access_reporter.py,sha256=wnaiDGW4MkYONV_erltnJ6nGkEj0kQrAiv04NNnOS0k,2859
|
772
772
|
tools/glitchtip_access_revalidation.py,sha256=jjeLO53LTbz_LfQw3G2Cs8lVLO_6xqU39BYyTH3cEPE,2764
|
773
|
-
tools/qontract_cli.py,sha256=
|
773
|
+
tools/qontract_cli.py,sha256=KyK2iCSh68cPolZygQtYb18ZtjIUlFw4aZT9D5p91kw,159892
|
774
774
|
tools/template_validation.py,sha256=Xn9X4sGFznx-rvBDnq9Kq16rfET8V3bqH1EwavsGBac,3335
|
775
775
|
tools/cli_commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
776
776
|
tools/cli_commands/container_images_report.py,sha256=8mAjCS6XR0yD7k0mfiVBlt6xbYU47q_ftdYNi5o5VKE,5566
|
@@ -796,7 +796,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
796
796
|
tools/saas_promotion_state/saas_promotion_state.py,sha256=uQv2QJAmUXP1g2GPIH30WTlvL9soY6m9lefpZEVDM5w,3965
|
797
797
|
tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
|
798
798
|
tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
|
799
|
-
qontract_reconcile-0.10.2.
|
800
|
-
qontract_reconcile-0.10.2.
|
801
|
-
qontract_reconcile-0.10.2.
|
802
|
-
qontract_reconcile-0.10.2.
|
799
|
+
qontract_reconcile-0.10.2.dev295.dist-info/METADATA,sha256=b48r1FF0GwIfFEiB6y-etqnHajQ5GHIn079H9KABEys,24916
|
800
|
+
qontract_reconcile-0.10.2.dev295.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
801
|
+
qontract_reconcile-0.10.2.dev295.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
|
802
|
+
qontract_reconcile-0.10.2.dev295.dist-info/RECORD,,
|
@@ -90,16 +90,16 @@ def run(dry_run: bool, defer: Callable | None = None) -> None:
|
|
90
90
|
)
|
91
91
|
)
|
92
92
|
|
93
|
-
for
|
94
|
-
if not
|
93
|
+
for account_to_reset in accounts_to_reset:
|
94
|
+
if not account_to_reset.reset_passwords:
|
95
95
|
continue
|
96
96
|
|
97
|
-
with AWSApi(1, [
|
98
|
-
for r in
|
97
|
+
with AWSApi(1, [account_to_reset.account], settings=settings) as aws_api:
|
98
|
+
for r in account_to_reset.reset_passwords:
|
99
99
|
user_name = r.user_name
|
100
100
|
state_key = r.state_key
|
101
101
|
|
102
|
-
account_name =
|
102
|
+
account_name = account_to_reset.account["name"]
|
103
103
|
|
104
104
|
logging.info(["reset_password", account_name, user_name])
|
105
105
|
|
@@ -1,8 +1,9 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
1
3
|
import json
|
2
4
|
import logging
|
3
5
|
import sys
|
4
|
-
from
|
5
|
-
from typing import Any
|
6
|
+
from typing import TYPE_CHECKING, Any
|
6
7
|
|
7
8
|
from reconcile import queries
|
8
9
|
from reconcile.status import ExitCodes
|
@@ -12,13 +13,16 @@ from reconcile.utils.ocm import (
|
|
12
13
|
OCMMap,
|
13
14
|
)
|
14
15
|
|
16
|
+
if TYPE_CHECKING:
|
17
|
+
from collections.abc import Iterable, Mapping, MutableMapping, Sequence
|
18
|
+
|
15
19
|
QONTRACT_INTEGRATION = "ocm-additional-routers"
|
16
20
|
|
17
21
|
SUPPORTED_OCM_PRODUCTS = [OCM_PRODUCT_OSD]
|
18
22
|
|
19
23
|
|
20
24
|
def fetch_current_state(
|
21
|
-
clusters:
|
25
|
+
clusters: Sequence[Mapping[str, Any]],
|
22
26
|
) -> tuple[OCMMap, list[dict[str, Any]]]:
|
23
27
|
settings = queries.get_app_interface_settings()
|
24
28
|
ocm_map = OCMMap(
|
reconcile/queries.py
CHANGED
@@ -25,7 +25,10 @@ SECRET_READER_SETTINGS = """
|
|
25
25
|
def get_secret_reader_settings() -> Mapping[str, Any] | None:
|
26
26
|
"""Returns SecretReader settings"""
|
27
27
|
gqlapi = gql.get_api()
|
28
|
-
|
28
|
+
data = gqlapi.query(SECRET_READER_SETTINGS)
|
29
|
+
if not data:
|
30
|
+
return None
|
31
|
+
settings = data.get("settings")
|
29
32
|
if settings:
|
30
33
|
# assuming a single settings file for now
|
31
34
|
return settings[0]
|
@@ -114,14 +117,13 @@ APP_INTERFACE_SETTINGS_QUERY = """
|
|
114
117
|
"""
|
115
118
|
|
116
119
|
|
117
|
-
def get_app_interface_settings():
|
120
|
+
def get_app_interface_settings() -> dict[str, Any]:
|
118
121
|
"""Returns App Interface settings"""
|
119
122
|
gqlapi = gql.get_api()
|
120
|
-
|
121
|
-
if settings:
|
122
|
-
|
123
|
-
|
124
|
-
return None
|
123
|
+
data = gqlapi.query(APP_INTERFACE_SETTINGS_QUERY)
|
124
|
+
if not data or not (settings := data.get("settings")):
|
125
|
+
raise ValueError("no App Interface settings found")
|
126
|
+
return settings[0]
|
125
127
|
|
126
128
|
|
127
129
|
CREDENTIALS_REQUESTS_QUERY = """
|
@@ -139,10 +141,13 @@ CREDENTIALS_REQUESTS_QUERY = """
|
|
139
141
|
"""
|
140
142
|
|
141
143
|
|
142
|
-
def get_credentials_requests():
|
144
|
+
def get_credentials_requests() -> list[dict[str, Any]]:
|
143
145
|
"""Returns Credentials Requests resources defined in app-interface"""
|
144
146
|
gqlapi = gql.get_api()
|
145
|
-
|
147
|
+
data = gqlapi.query(CREDENTIALS_REQUESTS_QUERY)
|
148
|
+
if not data:
|
149
|
+
return []
|
150
|
+
return data.get("credentials_requests") or []
|
146
151
|
|
147
152
|
|
148
153
|
JUMPHOST_FIELDS = """
|
@@ -252,11 +257,13 @@ INTEGRATIONS_QUERY = """
|
|
252
257
|
""" % (indent(JUMPHOST_FIELDS, 12 * " "),)
|
253
258
|
|
254
259
|
|
255
|
-
def get_integrations(managed=False):
|
260
|
+
def get_integrations(managed: bool = False) -> list[dict[str, Any]]:
|
256
261
|
gqlapi = gql.get_api()
|
257
|
-
if managed
|
258
|
-
|
259
|
-
|
262
|
+
query = INTEGRATIONS_QUERY if managed else gql.INTEGRATIONS_QUERY
|
263
|
+
data = gqlapi.query(query)
|
264
|
+
if not data:
|
265
|
+
return []
|
266
|
+
return data.get("integrations") or []
|
260
267
|
|
261
268
|
|
262
269
|
JENKINS_INSTANCES_QUERY = """
|
@@ -326,16 +333,19 @@ JENKINS_INSTANCES_QUERY = """
|
|
326
333
|
"""
|
327
334
|
|
328
335
|
|
329
|
-
def get_jenkins_instances(worker_fleets=False):
|
336
|
+
def get_jenkins_instances(worker_fleets: bool = False) -> list[dict[str, Any]]:
|
330
337
|
"""Returns a list of Jenkins instances"""
|
331
338
|
gqlapi = gql.get_api()
|
332
339
|
query = Template(JENKINS_INSTANCES_QUERY).render(worker_fleets=worker_fleets)
|
333
|
-
|
340
|
+
data = gqlapi.query(query)
|
341
|
+
if not data:
|
342
|
+
return []
|
343
|
+
return data.get("instances") or []
|
334
344
|
|
335
345
|
|
336
|
-
def get_jenkins_instances_previous_urls():
|
346
|
+
def get_jenkins_instances_previous_urls() -> list[str]:
|
337
347
|
instances = get_jenkins_instances()
|
338
|
-
all_previous_urls = []
|
348
|
+
all_previous_urls: list[str] = []
|
339
349
|
for instance in instances:
|
340
350
|
previous_urls = instance.get("previousUrls")
|
341
351
|
if previous_urls:
|
@@ -364,11 +374,13 @@ GITLAB_INSTANCES_QUERY = """
|
|
364
374
|
"""
|
365
375
|
|
366
376
|
|
367
|
-
def get_gitlab_instance():
|
377
|
+
def get_gitlab_instance() -> dict[str, Any]:
|
368
378
|
"""Returns a single GitLab instance"""
|
369
379
|
gqlapi = gql.get_api()
|
370
|
-
|
371
|
-
|
380
|
+
data = gqlapi.query(GITLAB_INSTANCES_QUERY)
|
381
|
+
if not data or not (instances := data.get("instances")):
|
382
|
+
raise ValueError("no GitLab instance found")
|
383
|
+
return instances[0]
|
372
384
|
|
373
385
|
|
374
386
|
GITHUB_INSTANCE_QUERY = """
|
@@ -386,13 +398,16 @@ GITHUB_INSTANCE_QUERY = """
|
|
386
398
|
"""
|
387
399
|
|
388
400
|
|
389
|
-
def get_github_instance():
|
401
|
+
def get_github_instance() -> dict[str, Any]:
|
390
402
|
"""Returns a single Github instance"""
|
391
403
|
gqlapi = gql.get_api()
|
392
|
-
|
404
|
+
data = gqlapi.query(GITHUB_INSTANCE_QUERY)
|
405
|
+
if not data or not (instances := data.get("instances")):
|
406
|
+
raise ValueError("no Github instance found")
|
393
407
|
for instance in instances:
|
394
408
|
if instance["url"] == "https://github.com/app-sre":
|
395
409
|
return instance
|
410
|
+
raise ValueError("no Github instance found")
|
396
411
|
|
397
412
|
|
398
413
|
GITHUB_ORGS_QUERY = """
|
@@ -411,10 +426,13 @@ GITHUB_ORGS_QUERY = """
|
|
411
426
|
"""
|
412
427
|
|
413
428
|
|
414
|
-
def get_github_orgs():
|
429
|
+
def get_github_orgs() -> list[dict[str, Any]]:
|
415
430
|
"""Returns all GitHub orgs"""
|
416
431
|
gqlapi = gql.get_api()
|
417
|
-
|
432
|
+
data = gqlapi.query(GITHUB_ORGS_QUERY)
|
433
|
+
if not data:
|
434
|
+
return []
|
435
|
+
return data.get("orgs") or []
|
418
436
|
|
419
437
|
|
420
438
|
AWS_ACCOUNTS_QUERY = """
|
@@ -521,14 +539,14 @@ AWS_ACCOUNTS_QUERY = """
|
|
521
539
|
|
522
540
|
|
523
541
|
def get_aws_accounts(
|
524
|
-
reset_passwords=False,
|
525
|
-
name=None,
|
526
|
-
uid=None,
|
527
|
-
sharing=False,
|
528
|
-
terraform_state=False,
|
529
|
-
ecrs=True,
|
530
|
-
cleanup=False,
|
531
|
-
):
|
542
|
+
reset_passwords: bool = False,
|
543
|
+
name: str | None = None,
|
544
|
+
uid: str | None = None,
|
545
|
+
sharing: bool = False,
|
546
|
+
terraform_state: bool = False,
|
547
|
+
ecrs: bool = True,
|
548
|
+
cleanup: bool = False,
|
549
|
+
) -> list[dict[str, Any]]:
|
532
550
|
"""Returns all AWS accounts"""
|
533
551
|
gqlapi = gql.get_api()
|
534
552
|
search = name or uid
|
@@ -542,16 +560,19 @@ def get_aws_accounts(
|
|
542
560
|
ecrs=ecrs,
|
543
561
|
cleanup=cleanup,
|
544
562
|
)
|
545
|
-
|
563
|
+
data = gqlapi.query(query)
|
564
|
+
if not data:
|
565
|
+
return []
|
566
|
+
return data.get("accounts") or []
|
546
567
|
|
547
568
|
|
548
|
-
def get_state_aws_accounts(reset_passwords=False):
|
569
|
+
def get_state_aws_accounts(reset_passwords: bool = False) -> list[dict[str, Any]]:
|
549
570
|
"""Returns AWS accounts to use for state management"""
|
550
571
|
name = os.environ["APP_INTERFACE_STATE_BUCKET_ACCOUNT"]
|
551
572
|
return get_aws_accounts(reset_passwords=reset_passwords, name=name)
|
552
573
|
|
553
574
|
|
554
|
-
def get_queue_aws_accounts():
|
575
|
+
def get_queue_aws_accounts() -> list[dict[str, Any]]:
|
555
576
|
"""Returns AWS accounts to use for queue management"""
|
556
577
|
uid = os.environ["gitlab_pr_submitter_queue_url"].split("/")[3] # noqa: SIM112
|
557
578
|
return get_aws_accounts(uid=uid)
|
@@ -987,7 +1008,9 @@ CLUSTERS_MINIMAL_QUERY = """
|
|
987
1008
|
)
|
988
1009
|
|
989
1010
|
|
990
|
-
def get_clusters(
|
1011
|
+
def get_clusters(
|
1012
|
+
minimal: bool = False, aws_infrastructure_access: bool = False
|
1013
|
+
) -> list[dict[str, Any]]:
|
991
1014
|
"""Returns all Clusters"""
|
992
1015
|
gqlapi = gql.get_api()
|
993
1016
|
tmpl = CLUSTERS_MINIMAL_QUERY if minimal else CLUSTERS_QUERY
|
@@ -995,7 +1018,10 @@ def get_clusters(minimal: bool = False, aws_infrastructure_access: bool = False)
|
|
995
1018
|
filter=None,
|
996
1019
|
aws_infrastructure_access=aws_infrastructure_access,
|
997
1020
|
)
|
998
|
-
|
1021
|
+
data = gqlapi.query(query)
|
1022
|
+
if not data:
|
1023
|
+
return []
|
1024
|
+
return data.get("clusters") or []
|
999
1025
|
|
1000
1026
|
|
1001
1027
|
CLUSTER_PEERING_QUERY = """
|
@@ -1223,7 +1249,10 @@ CLUSTER_PEERING_QUERY = """
|
|
1223
1249
|
|
1224
1250
|
|
1225
1251
|
def get_clusters_with_peering_settings() -> list[dict[str, Any]]:
|
1226
|
-
|
1252
|
+
data = gql.get_api().query(CLUSTER_PEERING_QUERY)
|
1253
|
+
if not data:
|
1254
|
+
return []
|
1255
|
+
clusters = data.get("clusters") or []
|
1227
1256
|
return [c for c in clusters if c.get("peering") is not None]
|
1228
1257
|
|
1229
1258
|
|
@@ -1232,14 +1261,19 @@ class ClusterFilter:
|
|
1232
1261
|
name: str = ""
|
1233
1262
|
|
1234
1263
|
|
1235
|
-
def get_clusters_by(
|
1264
|
+
def get_clusters_by(
|
1265
|
+
filter: ClusterFilter, minimal: bool = False
|
1266
|
+
) -> list[dict[str, Any]]:
|
1236
1267
|
"""Returns all Clusters fitting given filter"""
|
1237
1268
|
gqlapi = gql.get_api()
|
1238
1269
|
tmpl = CLUSTERS_MINIMAL_QUERY if minimal else CLUSTERS_QUERY
|
1239
1270
|
query = Template(tmpl).render(
|
1240
1271
|
filter=filter,
|
1241
1272
|
)
|
1242
|
-
|
1273
|
+
data = gqlapi.query(query)
|
1274
|
+
if not data:
|
1275
|
+
return []
|
1276
|
+
return data.get("clusters") or []
|
1243
1277
|
|
1244
1278
|
|
1245
1279
|
OCM_QUERY = """
|
@@ -1352,7 +1386,10 @@ OCM_QUERY = """
|
|
1352
1386
|
|
1353
1387
|
|
1354
1388
|
def get_openshift_cluster_managers() -> list[dict[str, Any]]:
|
1355
|
-
|
1389
|
+
data = gql.get_api().query(OCM_QUERY)
|
1390
|
+
if not data:
|
1391
|
+
return []
|
1392
|
+
return data.get("instances") or []
|
1356
1393
|
|
1357
1394
|
|
1358
1395
|
NAMESPACES_QUERY = """
|
@@ -1510,12 +1547,14 @@ NAMESPACES_MINIMAL_QUERY = """
|
|
1510
1547
|
""" % (indent(JUMPHOST_FIELDS, 8 * " "),)
|
1511
1548
|
|
1512
1549
|
|
1513
|
-
def get_namespaces(minimal=False):
|
1550
|
+
def get_namespaces(minimal: bool = False) -> list[dict[str, Any]]:
|
1514
1551
|
"""Returns all Namespaces"""
|
1515
1552
|
gqlapi = gql.get_api()
|
1516
|
-
if minimal
|
1517
|
-
|
1518
|
-
|
1553
|
+
query = NAMESPACES_MINIMAL_QUERY if minimal else NAMESPACES_QUERY
|
1554
|
+
data = gqlapi.query(query)
|
1555
|
+
if not data:
|
1556
|
+
return []
|
1557
|
+
return data.get("namespaces") or []
|
1519
1558
|
|
1520
1559
|
|
1521
1560
|
PRODUCTS_QUERY = """
|
@@ -1533,10 +1572,13 @@ PRODUCTS_QUERY = """
|
|
1533
1572
|
"""
|
1534
1573
|
|
1535
1574
|
|
1536
|
-
def get_products():
|
1575
|
+
def get_products() -> list[dict[str, Any]]:
|
1537
1576
|
"""Returns all Products"""
|
1538
1577
|
gqlapi = gql.get_api()
|
1539
|
-
|
1578
|
+
data = gqlapi.query(PRODUCTS_QUERY)
|
1579
|
+
if not data:
|
1580
|
+
return []
|
1581
|
+
return data.get("products") or []
|
1540
1582
|
|
1541
1583
|
|
1542
1584
|
ENVIRONMENTS_QUERY = """
|
@@ -1562,10 +1604,13 @@ ENVIRONMENTS_QUERY = """
|
|
1562
1604
|
"""
|
1563
1605
|
|
1564
1606
|
|
1565
|
-
def get_environments():
|
1607
|
+
def get_environments() -> list[dict[str, Any]]:
|
1566
1608
|
"""Returns all Products"""
|
1567
1609
|
gqlapi = gql.get_api()
|
1568
|
-
|
1610
|
+
data = gqlapi.query(ENVIRONMENTS_QUERY)
|
1611
|
+
if not data:
|
1612
|
+
return []
|
1613
|
+
return data.get("environments") or []
|
1569
1614
|
|
1570
1615
|
|
1571
1616
|
APPS_QUERY = """
|
@@ -1630,13 +1675,16 @@ CODE_COMPONENT_REPO_QUERY = """
|
|
1630
1675
|
"""
|
1631
1676
|
|
1632
1677
|
|
1633
|
-
def get_apps():
|
1678
|
+
def get_apps() -> list[dict[str, Any]]:
|
1634
1679
|
"""Returns all Apps."""
|
1635
1680
|
gqlapi = gql.get_api()
|
1636
|
-
|
1681
|
+
data = gqlapi.query(APPS_QUERY)
|
1682
|
+
if not data:
|
1683
|
+
return []
|
1684
|
+
return data.get("apps") or []
|
1637
1685
|
|
1638
1686
|
|
1639
|
-
def get_code_components():
|
1687
|
+
def get_code_components() -> list[dict[str, Any]]:
|
1640
1688
|
"""Returns code components from all apps."""
|
1641
1689
|
apps = get_apps()
|
1642
1690
|
code_components_lists = [
|
@@ -1646,13 +1694,13 @@ def get_code_components():
|
|
1646
1694
|
return code_components
|
1647
1695
|
|
1648
1696
|
|
1649
|
-
def get_review_repos():
|
1697
|
+
def get_review_repos() -> list[dict[str, str]]:
|
1650
1698
|
"""Returns name and url of code components marked for review"""
|
1651
1699
|
code_components = get_code_components()
|
1652
1700
|
return [
|
1653
1701
|
{"url": c["url"], "name": c["name"]}
|
1654
1702
|
for c in code_components
|
1655
|
-
if c
|
1703
|
+
if c["showInReviewQueue"] is not None
|
1656
1704
|
]
|
1657
1705
|
|
1658
1706
|
|
@@ -1661,7 +1709,10 @@ def get_repos(server: str = "", exclude_manage_permissions: bool = False) -> lis
|
|
1661
1709
|
Optional arguments:
|
1662
1710
|
server: url of the server to return. for example: https://github.com
|
1663
1711
|
"""
|
1664
|
-
|
1712
|
+
data = gql.get_api().query(CODE_COMPONENT_REPO_QUERY)
|
1713
|
+
if not data:
|
1714
|
+
return []
|
1715
|
+
apps = data.get("apps") or []
|
1665
1716
|
repos: list[str] = []
|
1666
1717
|
for a in apps:
|
1667
1718
|
if a["codeComponents"] is not None:
|
@@ -1673,7 +1724,7 @@ def get_repos(server: str = "", exclude_manage_permissions: bool = False) -> lis
|
|
1673
1724
|
return repos
|
1674
1725
|
|
1675
1726
|
|
1676
|
-
def get_repos_gitlab_owner(server=""):
|
1727
|
+
def get_repos_gitlab_owner(server: str = "") -> list[dict[str, Any]]:
|
1677
1728
|
"""Returns all repos defined under codeComponents that have gitlabOwner
|
1678
1729
|
enabled.
|
1679
1730
|
Optional arguments:
|
@@ -1689,7 +1740,7 @@ def get_repos_gitlab_owner(server=""):
|
|
1689
1740
|
]
|
1690
1741
|
|
1691
1742
|
|
1692
|
-
def get_repos_gitlab_housekeeping(server=""):
|
1743
|
+
def get_repos_gitlab_housekeeping(server: str = "") -> list[dict[str, Any]]:
|
1693
1744
|
"""Returns all repos defined under codeComponents that have
|
1694
1745
|
gitlabHousekeeping enabled.
|
1695
1746
|
Optional arguments:
|
@@ -1705,7 +1756,7 @@ def get_repos_gitlab_housekeeping(server=""):
|
|
1705
1756
|
]
|
1706
1757
|
|
1707
1758
|
|
1708
|
-
def get_repos_gitlab_jira(server=""):
|
1759
|
+
def get_repos_gitlab_jira(server: str = "") -> list[dict[str, Any]]:
|
1709
1760
|
code_components = get_code_components()
|
1710
1761
|
return [
|
1711
1762
|
{"url": c["url"], "jira": c["jira"]}
|
@@ -1754,10 +1805,13 @@ QUAY_ORGS_QUERY = """
|
|
1754
1805
|
"""
|
1755
1806
|
|
1756
1807
|
|
1757
|
-
def get_quay_orgs():
|
1808
|
+
def get_quay_orgs() -> list[dict[str, Any]]:
|
1758
1809
|
"""Returns all Quay orgs."""
|
1759
1810
|
gqlapi = gql.get_api()
|
1760
|
-
|
1811
|
+
data = gqlapi.query(QUAY_ORGS_QUERY)
|
1812
|
+
if not data:
|
1813
|
+
return []
|
1814
|
+
return data.get("quay_orgs") or []
|
1761
1815
|
|
1762
1816
|
|
1763
1817
|
USERS_QUERY = """
|
@@ -1880,22 +1934,33 @@ ROLES_QUERY = """
|
|
1880
1934
|
"""
|
1881
1935
|
|
1882
1936
|
|
1883
|
-
def get_roles(
|
1937
|
+
def get_roles(
|
1938
|
+
aws: bool = True,
|
1939
|
+
saas_files: bool = True,
|
1940
|
+
sendgrid: bool = False,
|
1941
|
+
permissions: bool = True,
|
1942
|
+
) -> list[dict[str, Any]]:
|
1884
1943
|
gqlapi = gql.get_api()
|
1885
1944
|
query = Template(ROLES_QUERY).render(
|
1886
1945
|
aws=aws, saas_files=saas_files, sendgrid=sendgrid, permissions=permissions
|
1887
1946
|
)
|
1888
|
-
|
1947
|
+
data = gqlapi.query(query)
|
1948
|
+
if not data:
|
1949
|
+
return []
|
1950
|
+
return data.get("users") or []
|
1889
1951
|
|
1890
1952
|
|
1891
|
-
def get_users(refs=False):
|
1953
|
+
def get_users(refs: bool = False) -> list[dict[str, Any]]:
|
1892
1954
|
"""Returnes all Users."""
|
1893
1955
|
gqlapi = gql.get_api()
|
1894
1956
|
query = Template(USERS_QUERY).render(
|
1895
1957
|
filter=None,
|
1896
1958
|
refs=refs,
|
1897
1959
|
)
|
1898
|
-
|
1960
|
+
data = gqlapi.query(query)
|
1961
|
+
if not data:
|
1962
|
+
return []
|
1963
|
+
return data.get("users") or []
|
1899
1964
|
|
1900
1965
|
|
1901
1966
|
@dataclass
|
@@ -1910,7 +1975,10 @@ def get_users_by(filter: UserFilter, refs: bool = False) -> list[dict[str, str]]
|
|
1910
1975
|
filter=filter,
|
1911
1976
|
refs=refs,
|
1912
1977
|
)
|
1913
|
-
|
1978
|
+
data = gqlapi.query(query)
|
1979
|
+
if not data:
|
1980
|
+
return []
|
1981
|
+
return data.get("users") or []
|
1914
1982
|
|
1915
1983
|
|
1916
1984
|
BOTS_QUERY = """
|
@@ -1926,10 +1994,13 @@ BOTS_QUERY = """
|
|
1926
1994
|
"""
|
1927
1995
|
|
1928
1996
|
|
1929
|
-
def get_bots():
|
1997
|
+
def get_bots() -> list[dict[str, Any]]:
|
1930
1998
|
"""Returnes all Bots."""
|
1931
1999
|
gqlapi = gql.get_api()
|
1932
|
-
|
2000
|
+
data = gqlapi.query(BOTS_QUERY)
|
2001
|
+
if not data:
|
2002
|
+
return []
|
2003
|
+
return data.get("bots") or []
|
1933
2004
|
|
1934
2005
|
|
1935
2006
|
EXTERNAL_USERS_QUERY = """
|
@@ -1943,10 +2014,13 @@ EXTERNAL_USERS_QUERY = """
|
|
1943
2014
|
"""
|
1944
2015
|
|
1945
2016
|
|
1946
|
-
def get_external_users():
|
2017
|
+
def get_external_users() -> list[dict[str, Any]]:
|
1947
2018
|
"""Returnes all Users."""
|
1948
2019
|
gqlapi = gql.get_api()
|
1949
|
-
|
2020
|
+
data = gqlapi.query(EXTERNAL_USERS_QUERY)
|
2021
|
+
if not data:
|
2022
|
+
return []
|
2023
|
+
return data.get("external_users") or []
|
1950
2024
|
|
1951
2025
|
|
1952
2026
|
APP_INTERFACE_SQL_QUERIES_QUERY = """
|
@@ -2019,10 +2093,13 @@ APP_INTERFACE_SQL_QUERIES_QUERY = """
|
|
2019
2093
|
"""
|
2020
2094
|
|
2021
2095
|
|
2022
|
-
def get_app_interface_sql_queries():
|
2096
|
+
def get_app_interface_sql_queries() -> list[dict[str, Any]]:
|
2023
2097
|
"""Returns SqlQuery resources defined in app-interface"""
|
2024
2098
|
gqlapi = gql.get_api()
|
2025
|
-
|
2099
|
+
data = gqlapi.query(APP_INTERFACE_SQL_QUERIES_QUERY)
|
2100
|
+
if not data:
|
2101
|
+
return []
|
2102
|
+
return data.get("sql_queries") or []
|
2026
2103
|
|
2027
2104
|
|
2028
2105
|
PIPELINES_PROVIDERS_QUERY = """
|
@@ -2121,10 +2198,13 @@ PIPELINES_PROVIDERS_QUERY = """
|
|
2121
2198
|
""" % (indent(JUMPHOST_FIELDS, 12 * " "),)
|
2122
2199
|
|
2123
2200
|
|
2124
|
-
def get_pipelines_providers():
|
2201
|
+
def get_pipelines_providers() -> list[dict[str, Any]]:
|
2125
2202
|
"""Returns PipelinesProvider resources defined in app-interface."""
|
2126
2203
|
gqlapi = gql.get_api()
|
2127
|
-
|
2204
|
+
data = gqlapi.query(PIPELINES_PROVIDERS_QUERY)
|
2205
|
+
if not data:
|
2206
|
+
return []
|
2207
|
+
pipelines_providers = data.get("pipelines_providers") or []
|
2128
2208
|
|
2129
2209
|
for pp in pipelines_providers:
|
2130
2210
|
defaults = pp.pop("defaults")
|
@@ -2156,10 +2236,13 @@ JIRA_BOARDS_QUICK_QUERY = """
|
|
2156
2236
|
"""
|
2157
2237
|
|
2158
2238
|
|
2159
|
-
def get_simple_jira_boards(app_path: str):
|
2239
|
+
def get_simple_jira_boards(app_path: str) -> list[dict[str, Any]]:
|
2160
2240
|
gqlapi = gql.get_api()
|
2161
2241
|
query = JIRA_BOARDS_QUICK_QUERY.replace("APATH", shlex.quote(app_path))
|
2162
|
-
|
2242
|
+
data = gqlapi.query(query)
|
2243
|
+
if not data:
|
2244
|
+
return []
|
2245
|
+
return data.get("jira_boards") or []
|
2163
2246
|
|
2164
2247
|
|
2165
2248
|
UNLEASH_INSTANCES_QUERY = """
|
@@ -2207,10 +2290,13 @@ UNLEASH_INSTANCES_QUERY = """
|
|
2207
2290
|
"""
|
2208
2291
|
|
2209
2292
|
|
2210
|
-
def get_unleash_instances():
|
2293
|
+
def get_unleash_instances() -> list[dict[str, Any]]:
|
2211
2294
|
"""Returns Unleash instances defined in app-interface"""
|
2212
2295
|
gqlapi = gql.get_api()
|
2213
|
-
|
2296
|
+
data = gqlapi.query(UNLEASH_INSTANCES_QUERY)
|
2297
|
+
if not data:
|
2298
|
+
return []
|
2299
|
+
return data.get("unleash_instances") or []
|
2214
2300
|
|
2215
2301
|
|
2216
2302
|
DNS_RECORD = """
|
@@ -2304,12 +2390,15 @@ DNS_ZONES_QUERY = """
|
|
2304
2390
|
""" % (indent(DNS_RECORD, 6 * " "),)
|
2305
2391
|
|
2306
2392
|
|
2307
|
-
def get_dns_zones(account_name=None):
|
2393
|
+
def get_dns_zones(account_name: str | None = None) -> list[dict[str, Any]]:
|
2308
2394
|
"""Returnes all AWS Route53 DNS Zones."""
|
2309
2395
|
gqlapi = gql.get_api()
|
2310
|
-
|
2396
|
+
data = gqlapi.query(DNS_ZONES_QUERY)
|
2397
|
+
if not data:
|
2398
|
+
return []
|
2399
|
+
zones = data.get("zones") or []
|
2311
2400
|
if account_name:
|
2312
|
-
zones = [z for z in zones if z
|
2401
|
+
zones = [z for z in zones if z.get("account", {}).get("name") == account_name]
|
2313
2402
|
|
2314
2403
|
return zones
|
2315
2404
|
|
@@ -2345,13 +2434,16 @@ SLACK_WORKSPACES_QUERY = """
|
|
2345
2434
|
"""
|
2346
2435
|
|
2347
2436
|
|
2348
|
-
def get_slack_workspace():
|
2437
|
+
def get_slack_workspace() -> dict[str, Any] | None:
|
2349
2438
|
"""Returns a single Slack workspace"""
|
2350
2439
|
gqlapi = gql.get_api()
|
2351
|
-
|
2352
|
-
if
|
2440
|
+
data = gqlapi.query(SLACK_WORKSPACES_QUERY)
|
2441
|
+
if not data:
|
2442
|
+
return None
|
2443
|
+
slack_workspaces = data.get("slack_workspaces") or []
|
2444
|
+
if len(slack_workspaces) > 1:
|
2353
2445
|
logging.warning("multiple Slack workspaces found.")
|
2354
|
-
return slack_workspaces[0]
|
2446
|
+
return slack_workspaces[0] if slack_workspaces else None
|
2355
2447
|
|
2356
2448
|
|
2357
2449
|
SENDGRID_ACCOUNTS_QUERY = """
|
@@ -2370,10 +2462,13 @@ SENDGRID_ACCOUNTS_QUERY = """
|
|
2370
2462
|
"""
|
2371
2463
|
|
2372
2464
|
|
2373
|
-
def get_sendgrid_accounts():
|
2465
|
+
def get_sendgrid_accounts() -> list[dict[str, Any]]:
|
2374
2466
|
"""Returns SendGrid accounts"""
|
2375
2467
|
gqlapi = gql.get_api()
|
2376
|
-
|
2468
|
+
data = gqlapi.query(SENDGRID_ACCOUNTS_QUERY)
|
2469
|
+
if not data:
|
2470
|
+
return []
|
2471
|
+
return data.get("sendgrid_accounts") or []
|
2377
2472
|
|
2378
2473
|
|
2379
2474
|
QUAY_REPOS_QUERY = """
|
@@ -2408,9 +2503,12 @@ QUAY_REPOS_QUERY = """
|
|
2408
2503
|
"""
|
2409
2504
|
|
2410
2505
|
|
2411
|
-
def get_quay_repos():
|
2506
|
+
def get_quay_repos() -> list[dict[str, Any]]:
|
2412
2507
|
gqlapi = gql.get_api()
|
2413
|
-
|
2508
|
+
data = gqlapi.query(QUAY_REPOS_QUERY)
|
2509
|
+
if not data:
|
2510
|
+
return []
|
2511
|
+
return data.get("apps") or []
|
2414
2512
|
|
2415
2513
|
|
2416
2514
|
SRE_CHECKPOINTS_QUERY = """
|
@@ -2426,9 +2524,12 @@ SRE_CHECKPOINTS_QUERY = """
|
|
2426
2524
|
"""
|
2427
2525
|
|
2428
2526
|
|
2429
|
-
def get_sre_checkpoints():
|
2527
|
+
def get_sre_checkpoints() -> list[dict[str, Any]]:
|
2430
2528
|
gqlapi = gql.get_api()
|
2431
|
-
|
2529
|
+
data = gqlapi.query(SRE_CHECKPOINTS_QUERY)
|
2530
|
+
if not data:
|
2531
|
+
return []
|
2532
|
+
return data.get("sre_checkpoints") or []
|
2432
2533
|
|
2433
2534
|
|
2434
2535
|
GABI_INSTANCES_QUERY = """
|
@@ -2490,9 +2591,12 @@ GABI_INSTANCES_QUERY = """
|
|
2490
2591
|
""" % (indent(JUMPHOST_FIELDS, 12 * " "),)
|
2491
2592
|
|
2492
2593
|
|
2493
|
-
def get_gabi_instances():
|
2594
|
+
def get_gabi_instances() -> list[dict[str, Any]]:
|
2494
2595
|
gqlapi = gql.get_api()
|
2495
|
-
|
2596
|
+
data = gqlapi.query(GABI_INSTANCES_QUERY)
|
2597
|
+
if not data:
|
2598
|
+
return []
|
2599
|
+
return data.get("gabi_instances") or []
|
2496
2600
|
|
2497
2601
|
|
2498
2602
|
CLOSED_BOX_MONITORING_PROBES_QUERY = """
|
@@ -2556,9 +2660,12 @@ CLOSED_BOX_MONITORING_PROBES_QUERY = """
|
|
2556
2660
|
"""
|
2557
2661
|
|
2558
2662
|
|
2559
|
-
def get_service_monitoring_endpoints():
|
2663
|
+
def get_service_monitoring_endpoints() -> list[dict[str, Any]]:
|
2560
2664
|
gqlapi = gql.get_api()
|
2561
|
-
|
2665
|
+
data = gqlapi.query(CLOSED_BOX_MONITORING_PROBES_QUERY)
|
2666
|
+
if not data:
|
2667
|
+
return []
|
2668
|
+
return data.get("apps") or []
|
2562
2669
|
|
2563
2670
|
|
2564
2671
|
# Use APATH as place holder because query strings have a lot of curly
|
@@ -2606,7 +2713,10 @@ def get_app_metadata(app_path: str) -> dict:
|
|
2606
2713
|
"""Fetch the metadata for the path stored in app_path."""
|
2607
2714
|
app_query = APP_METADATA.replace("APATH", shlex.quote(app_path))
|
2608
2715
|
gqlapi = gql.get_api()
|
2609
|
-
|
2716
|
+
data = gqlapi.query(app_query)
|
2717
|
+
if not data:
|
2718
|
+
return {}
|
2719
|
+
return data.get("apps", {})
|
2610
2720
|
|
2611
2721
|
|
2612
2722
|
BLACKBOX_EXPORTER_MONITORING_PROVIDER = """
|
@@ -2631,7 +2741,10 @@ BLACKBOX_EXPORTER_MONITORING_PROVIDER = """
|
|
2631
2741
|
|
2632
2742
|
def get_blackbox_exporter_monitoring_provider() -> dict:
|
2633
2743
|
gqlapi = gql.get_api()
|
2634
|
-
|
2744
|
+
data = gqlapi.query(BLACKBOX_EXPORTER_MONITORING_PROVIDER)
|
2745
|
+
if not data:
|
2746
|
+
return {}
|
2747
|
+
return data.get("providers", {})
|
2635
2748
|
|
2636
2749
|
|
2637
2750
|
JENKINS_CONFIGS = """
|
@@ -2662,9 +2775,12 @@ JENKINS_CONFIGS = """
|
|
2662
2775
|
"""
|
2663
2776
|
|
2664
2777
|
|
2665
|
-
def get_jenkins_configs():
|
2778
|
+
def get_jenkins_configs() -> list[dict[str, Any]]:
|
2666
2779
|
gqlapi = gql.get_api()
|
2667
|
-
|
2780
|
+
data = gqlapi.query(JENKINS_CONFIGS)
|
2781
|
+
if not data:
|
2782
|
+
return []
|
2783
|
+
return data.get("jenkins_configs") or []
|
2668
2784
|
|
2669
2785
|
|
2670
2786
|
TF_RESOURCES_PROVIDER_EXCLUSIONS_BY_PROVISIONER = """
|
@@ -2686,10 +2802,15 @@ def get_tf_resources_provider_exclusions_by_provisioner() -> (
|
|
2686
2802
|
list[dict[str, Any]] | None
|
2687
2803
|
):
|
2688
2804
|
gqlapi = gql.get_api()
|
2689
|
-
|
2690
|
-
|
2691
|
-
|
2692
|
-
|
2805
|
+
data = gqlapi.query(TF_RESOURCES_PROVIDER_EXCLUSIONS_BY_PROVISIONER)
|
2806
|
+
if not data:
|
2807
|
+
return None
|
2808
|
+
settings = data.get("tf_provider_exclusions")
|
2809
|
+
if (
|
2810
|
+
settings
|
2811
|
+
and len(settings) == 1
|
2812
|
+
and "terraformResourcesProviderExclusions" in settings[0]
|
2813
|
+
):
|
2693
2814
|
return settings[0]["terraformResourcesProviderExclusions"]
|
2694
2815
|
return None
|
2695
2816
|
|
@@ -2719,4 +2840,7 @@ SCHEMAS_QUERY = """
|
|
2719
2840
|
# TODO: replace with typed query following https://issues.redhat.com/browse/APPSRE-10983
|
2720
2841
|
def get_schemas() -> dict:
|
2721
2842
|
gqlapi = gql.get_api()
|
2722
|
-
|
2843
|
+
data = gqlapi.query(SCHEMAS_QUERY)
|
2844
|
+
if not data:
|
2845
|
+
return {}
|
2846
|
+
return data.get("schemas", {})
|
reconcile/utils/ocm/ocm.py
CHANGED
@@ -403,7 +403,7 @@ class OCM:
|
|
403
403
|
api = (
|
404
404
|
f"{CS_API_BASE}/v1/clusters/{cluster_id}" + "/external_configuration/labels"
|
405
405
|
)
|
406
|
-
items = self._get_json(api).get("items")
|
406
|
+
items = self._get_json(api).get("items", [])
|
407
407
|
item = [item for item in items if label.items() <= item.items()]
|
408
408
|
if not item:
|
409
409
|
return
|
@@ -597,14 +597,14 @@ class OCM:
|
|
597
597
|
def _init_addons(self):
|
598
598
|
"""Returns a list of Addons"""
|
599
599
|
api = f"{CS_API_BASE}/v1/addons"
|
600
|
-
self.addons = self._get_json(api).get("items")
|
600
|
+
self.addons = self._get_json(api).get("items", [])
|
601
601
|
|
602
602
|
def _init_version_gates(self):
|
603
603
|
"""Returns a list of version gates"""
|
604
604
|
if self.version_gates:
|
605
605
|
return
|
606
606
|
api = f"{CS_API_BASE}/v1/version_gates"
|
607
|
-
self.version_gates = self._get_json(api).get("items")
|
607
|
+
self.version_gates = self._get_json(api).get("items", [])
|
608
608
|
|
609
609
|
def get_addon(self, id):
|
610
610
|
for addon in self.addons:
|
tools/app_interface_reporter.py
CHANGED
@@ -275,17 +275,17 @@ def get_apps_data(
|
|
275
275
|
cluster = sample.labels["cluster"]
|
276
276
|
if app_namespace["cluster"]["name"] != cluster:
|
277
277
|
continue
|
278
|
-
|
279
|
-
if app_namespace["name"] !=
|
278
|
+
sample_namespace = sample.labels["namespace"]
|
279
|
+
if app_namespace["name"] != sample_namespace:
|
280
280
|
continue
|
281
281
|
severity = sample.labels["severity"]
|
282
282
|
if cluster not in vuln_mx:
|
283
283
|
vuln_mx[cluster] = {}
|
284
|
-
if
|
285
|
-
vuln_mx[cluster][
|
286
|
-
if severity not in vuln_mx[cluster][
|
284
|
+
if sample_namespace not in vuln_mx[cluster]:
|
285
|
+
vuln_mx[cluster][sample_namespace] = {}
|
286
|
+
if severity not in vuln_mx[cluster][sample_namespace]:
|
287
287
|
value = int(sample.value)
|
288
|
-
vuln_mx[cluster][
|
288
|
+
vuln_mx[cluster][sample_namespace][severity] = value
|
289
289
|
for family in text_string_to_metric_families(validt_metrics):
|
290
290
|
for sample in family.samples:
|
291
291
|
if sample.name == "deploymentvalidation_total":
|
@@ -293,8 +293,8 @@ def get_apps_data(
|
|
293
293
|
cluster = sample.labels["cluster"]
|
294
294
|
if app_namespace["cluster"]["name"] != cluster:
|
295
295
|
continue
|
296
|
-
|
297
|
-
if app_namespace["name"] !=
|
296
|
+
sample_namespace = sample.labels["namespace"]
|
297
|
+
if app_namespace["name"] != sample_namespace:
|
298
298
|
continue
|
299
299
|
validation = sample.labels["validation"]
|
300
300
|
# dvo: fail == 1, pass == 0, py: true == 1, false == 0
|
@@ -302,14 +302,19 @@ def get_apps_data(
|
|
302
302
|
status = ("Passed", "Failed")[int(sample.labels["status"])]
|
303
303
|
if cluster not in validt_mx:
|
304
304
|
validt_mx[cluster] = {}
|
305
|
-
if
|
306
|
-
validt_mx[cluster][
|
307
|
-
if validation not in validt_mx[cluster][
|
308
|
-
validt_mx[cluster][
|
309
|
-
if
|
310
|
-
|
305
|
+
if sample_namespace not in validt_mx[cluster]:
|
306
|
+
validt_mx[cluster][sample_namespace] = {}
|
307
|
+
if validation not in validt_mx[cluster][sample_namespace]:
|
308
|
+
validt_mx[cluster][sample_namespace][validation] = {}
|
309
|
+
if (
|
310
|
+
status
|
311
|
+
not in validt_mx[cluster][sample_namespace][validation]
|
312
|
+
):
|
313
|
+
validt_mx[cluster][sample_namespace][validation][
|
314
|
+
status
|
315
|
+
] = {}
|
311
316
|
value = int(sample.value)
|
312
|
-
validt_mx[cluster][
|
317
|
+
validt_mx[cluster][sample_namespace][validation][status] = value
|
313
318
|
for family in text_string_to_metric_families(slo_metrics):
|
314
319
|
for sample in family.samples:
|
315
320
|
if sample.name == "serviceslometrics":
|
@@ -317,25 +322,28 @@ def get_apps_data(
|
|
317
322
|
cluster = sample.labels["cluster"]
|
318
323
|
if app_namespace["cluster"]["name"] != cluster:
|
319
324
|
continue
|
320
|
-
|
321
|
-
if app_namespace["name"] !=
|
325
|
+
sample_namespace = sample.labels["namespace"]
|
326
|
+
if app_namespace["name"] != sample_namespace:
|
322
327
|
continue
|
323
328
|
slo_doc_name = sample.labels["slodoc"]
|
324
329
|
slo_name = sample.labels["name"]
|
325
330
|
if cluster not in slo_mx:
|
326
331
|
slo_mx[cluster] = {}
|
327
|
-
if
|
328
|
-
slo_mx[cluster][
|
329
|
-
if slo_doc_name not in slo_mx[cluster][
|
330
|
-
slo_mx[cluster][
|
331
|
-
if
|
332
|
-
|
333
|
-
|
334
|
-
|
332
|
+
if sample_namespace not in slo_mx[cluster]:
|
333
|
+
slo_mx[cluster][sample_namespace] = {}
|
334
|
+
if slo_doc_name not in slo_mx[cluster][sample_namespace]:
|
335
|
+
slo_mx[cluster][sample_namespace][slo_doc_name] = {}
|
336
|
+
if (
|
337
|
+
slo_name
|
338
|
+
not in slo_mx[cluster][sample_namespace][slo_doc_name]
|
339
|
+
):
|
340
|
+
slo_mx[cluster][sample_namespace][slo_doc_name][
|
341
|
+
slo_name
|
342
|
+
] = {sample.labels["type"]: sample.value}
|
335
343
|
else:
|
336
|
-
slo_mx[cluster][
|
337
|
-
|
338
|
-
})
|
344
|
+
slo_mx[cluster][sample_namespace][slo_doc_name][
|
345
|
+
slo_name
|
346
|
+
].update({sample.labels["type"]: sample.value})
|
339
347
|
app["container_vulnerabilities"] = vuln_mx
|
340
348
|
app["deployment_validations"] = validt_mx
|
341
349
|
app["service_slo"] = slo_mx
|
tools/qontract_cli.py
CHANGED
@@ -1715,7 +1715,10 @@ def add_resource(item: dict, resource: Mapping, columns: list[str]) -> None:
|
|
1715
1715
|
@click.pass_context
|
1716
1716
|
def cluster_openshift_resources(ctx: click.Context) -> None:
|
1717
1717
|
gqlapi = gql.get_api()
|
1718
|
-
|
1718
|
+
data = gqlapi.query(orb.NAMESPACES_QUERY)
|
1719
|
+
if not data:
|
1720
|
+
raise ValueError("no namespaces found")
|
1721
|
+
namespaces = data.get("namespaces", [])
|
1719
1722
|
columns = ["name", "total"]
|
1720
1723
|
results: dict = {}
|
1721
1724
|
for ns_info in namespaces:
|
@@ -1912,6 +1915,7 @@ def rds_recommendations(ctx: click.Context) -> None:
|
|
1912
1915
|
print("[TOC]")
|
1913
1916
|
for account in accounts:
|
1914
1917
|
account_name = account.get("name")
|
1918
|
+
assert account_name is not None # make mypy happy
|
1915
1919
|
account_deployment_regions = account.get("supportedDeploymentRegions")
|
1916
1920
|
for region in account_deployment_regions or []:
|
1917
1921
|
with AWSApi(1, [account], settings=settings, init_users=False) as aws:
|
@@ -1926,9 +1930,9 @@ def rds_recommendations(ctx: click.Context) -> None:
|
|
1926
1930
|
recommendations = [
|
1927
1931
|
{
|
1928
1932
|
**rec,
|
1929
|
-
"ResourceName": rec
|
1933
|
+
"ResourceName": rec.get("ResourceArn", "").split(":")[-1],
|
1930
1934
|
# The Description field has \n that are causing issues with the markdown table
|
1931
|
-
"Description": rec
|
1935
|
+
"Description": rec.get("Description", "").replace("\n", " "),
|
1932
1936
|
}
|
1933
1937
|
for rec in db_recommendations
|
1934
1938
|
if rec.get("Status") not in ignored_statuses
|
@@ -2710,16 +2714,16 @@ def ec2_jenkins_workers(
|
|
2710
2714
|
)
|
2711
2715
|
continue
|
2712
2716
|
instance = ec2.Instance(i["InstanceId"])
|
2713
|
-
state = instance.state
|
2717
|
+
state = instance.state.get("Name")
|
2714
2718
|
if state != "running":
|
2715
2719
|
continue
|
2716
2720
|
os = ""
|
2717
2721
|
url = ""
|
2718
2722
|
for t in instance.tags:
|
2719
2723
|
if t.get("Key") == "os":
|
2720
|
-
os = t
|
2724
|
+
os = t.get("Value", "")
|
2721
2725
|
if t.get("Key") == "jenkins_controller":
|
2722
|
-
url = f"https://{t
|
2726
|
+
url = f"https://{t.get('Value', '').replace('-', '.')}.devshift.net/computer/{instance.id}"
|
2723
2727
|
image = ec2.Image(instance.image_id)
|
2724
2728
|
commit_url = ""
|
2725
2729
|
for t in image.tags:
|
@@ -3633,7 +3637,10 @@ def template(
|
|
3633
3637
|
secret_reader: str,
|
3634
3638
|
) -> None:
|
3635
3639
|
gqlapi = gql.get_api()
|
3636
|
-
|
3640
|
+
data = gqlapi.query(orb.NAMESPACES_QUERY)
|
3641
|
+
if not data:
|
3642
|
+
raise ValueError("no namespaces found")
|
3643
|
+
namespaces = data.get("namespaces", [])
|
3637
3644
|
namespaces_info = [
|
3638
3645
|
n
|
3639
3646
|
for n in namespaces
|
@@ -3725,7 +3732,7 @@ def run_prometheus_test(
|
|
3725
3732
|
ptr.run_test(test=test, alerting_services=get_alerting_services())
|
3726
3733
|
|
3727
3734
|
print(test.result)
|
3728
|
-
if
|
3735
|
+
if test.result is None:
|
3729
3736
|
sys.exit(1)
|
3730
3737
|
|
3731
3738
|
|
@@ -3804,7 +3811,10 @@ def alert_to_receiver(
|
|
3804
3811
|
additional_labels[key] = value
|
3805
3812
|
|
3806
3813
|
gqlapi = gql.get_api()
|
3807
|
-
|
3814
|
+
data = gqlapi.query(orb.NAMESPACES_QUERY)
|
3815
|
+
if not data:
|
3816
|
+
raise ValueError("no namespaces found")
|
3817
|
+
namespaces = data.get("namespaces", [])
|
3808
3818
|
cluster_namespaces = [n for n in namespaces if n["cluster"]["name"] == cluster]
|
3809
3819
|
|
3810
3820
|
if len(cluster_namespaces) == 0:
|
@@ -4027,15 +4037,16 @@ def query(output: str, query: str) -> None:
|
|
4027
4037
|
def promquery(cluster: str, query: str) -> None:
|
4028
4038
|
"""Run a PromQL query"""
|
4029
4039
|
config_data = config.get_config()
|
4030
|
-
|
4040
|
+
prom_auth = {"path": config_data["promql-auth"]["secret_path"], "field": "token"}
|
4031
4041
|
settings = queries.get_app_interface_settings()
|
4032
4042
|
secret_reader = SecretReader(settings=settings)
|
4033
|
-
|
4034
|
-
prom_auth = requests.auth.HTTPBasicAuth(*prom_auth_creds.split(":"))
|
4043
|
+
prom_user, prom_pass = secret_reader.read(prom_auth).split(":")
|
4035
4044
|
|
4036
4045
|
url = f"https://prometheus.{cluster}.devshift.net/api/v1/query"
|
4037
4046
|
|
4038
|
-
response = requests.get(
|
4047
|
+
response = requests.get(
|
4048
|
+
url, params={"query": query}, auth=(prom_user, prom_pass), timeout=60
|
4049
|
+
)
|
4039
4050
|
response.raise_for_status()
|
4040
4051
|
|
4041
4052
|
print(json.dumps(response.json(), indent=4))
|
@@ -4092,11 +4103,12 @@ def sre_checkpoint_metadata(
|
|
4092
4103
|
board_info = queries.get_simple_jira_boards(jiradef)
|
4093
4104
|
else:
|
4094
4105
|
board_info = app["escalationPolicy"]["channels"]["jiraBoard"]
|
4095
|
-
board_info
|
4106
|
+
assert board_info # make mypy happy
|
4107
|
+
board = board_info[0]
|
4096
4108
|
# Overrides for easier testing
|
4097
4109
|
if jiraboard:
|
4098
|
-
|
4099
|
-
report_invalid_metadata(app, app_path,
|
4110
|
+
board["name"] = jiraboard
|
4111
|
+
report_invalid_metadata(app, app_path, board, settings, parent_ticket, dry_run)
|
4100
4112
|
|
4101
4113
|
|
4102
4114
|
@root.command()
|
{qontract_reconcile-0.10.2.dev294.dist-info → qontract_reconcile-0.10.2.dev295.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|