qontract-reconcile 0.10.1rc1005__py3-none-any.whl → 0.10.1rc1006__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qontract-reconcile
3
- Version: 0.10.1rc1005
3
+ Version: 0.10.1rc1006
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
@@ -99,7 +99,7 @@ reconcile/query_validator.py,sha256=BAjGrU8_VhzTOv5k0-uz0hY9ziZyconv8VAhgre1Auc,
99
99
  reconcile/requests_sender.py,sha256=914iluuF4UVgG3VyxxtnHOu4yf6YKS2fIy6PViSsFTQ,3875
100
100
  reconcile/resource_scraper.py,sha256=znXCHrU7YwPfKuxGBiUrV7T1tYtn4vlz9qmZlfy6Flg,2307
101
101
  reconcile/resource_template_tester.py,sha256=DsKvBuNLPxm4Fa-e1YHHySnhThm5i_j-nF3G4b02Mz0,2416
102
- reconcile/saas_file_validator.py,sha256=ckQL14SfzRLiv1SA_0zB5A-a11Anvsgxp-1NbP8A_8Q,1938
102
+ reconcile/saas_file_validator.py,sha256=QH8tPi2DrU2n9SIVfNEdDJXHPtlbwzlvklcB9RWPhOU,2521
103
103
  reconcile/sendgrid_teammates.py,sha256=oO8QbLb4s1o8A6CGiCagN9CmS05BSS_WLztuY0Ym9D8,4773
104
104
  reconcile/service_dependencies.py,sha256=PMKP9vc6oL-78rzyF_RE8DzLSQMSqN8vCqt9sWpBLAM,4470
105
105
  reconcile/signalfx_endpoint_monitoring.py,sha256=Nqgsg1cflSd2nNnm89y_e8c--7xLUqTrKOHkDs-qADE,2868
@@ -262,6 +262,7 @@ reconcile/gql_definitions/common/pagerduty_instances.py,sha256=CqHMNyI0O1knfzLJo
262
262
  reconcile/gql_definitions/common/pgp_reencryption_settings.py,sha256=NPLmO6J-zSu5B9QiYbDezLHY3TuOO9ihRBV-Zr84R9w,2259
263
263
  reconcile/gql_definitions/common/pipeline_providers.py,sha256=JJgmmghqLIwjKOdcWYHPnf4PDgAq4GF7046i0ozrqgI,9127
264
264
  reconcile/gql_definitions/common/quay_instances.py,sha256=toBkdYYVTmEafezAHZKgaW-mQ29xEW6jeronzsAlNyI,1786
265
+ reconcile/gql_definitions/common/quay_orgs.py,sha256=NhA8kqvVUDbrsryEvEL5mlIv5R3T4XNhSRXtfL_yptY,1788
265
266
  reconcile/gql_definitions/common/reserved_networks.py,sha256=yP9qSQCaSQcva-ZgTnZp09qH27ur5_qK080ToIs04MY,2560
266
267
  reconcile/gql_definitions/common/saas_files.py,sha256=JZdFKBygaZVxGwBUYMki9EbnsGdmfmxuAreMZ3dchwo,16702
267
268
  reconcile/gql_definitions/common/saas_target_namespaces.py,sha256=4VYP2VbwY8WVwtSFk2-jsUNhSmRD3X4FWKxetOKvmd0,2835
@@ -545,7 +546,7 @@ reconcile/test/test_quay_repos.py,sha256=TdkcRF_a8PLp01Kti9eZZN-vGup2yPBT4Iba3k0
545
546
  reconcile/test/test_queries.py,sha256=SpH3RmNpBjEr_ne3VjAMCgKK8RE1z1zo7bypkT5uoO4,1946
546
547
  reconcile/test/test_repo_owners.py,sha256=uRYMLbMmh-9usF0TerabZTZV-Z1CS4I6ybT-LQqCLe8,1423
547
548
  reconcile/test/test_requests_sender.py,sha256=7fd9C2kEFS0-CYtlsif66N1kO9c44pzuBPAJKR9igqU,5385
548
- reconcile/test/test_saasherder.py,sha256=EMzqoAOFVbeFPuz4oG81srkuNfInHSu4smoArLheUa4,57234
549
+ reconcile/test/test_saasherder.py,sha256=SXhjDhpmWNM3xWtOGWn5j6BeznuXDwlttVcUtp9drpo,58014
549
550
  reconcile/test/test_saasherder_allowed_secret_paths.py,sha256=5NHQwNJO66at6HiyMZ5sVRTQDwxdvlOQo0KmkBWCw5Q,4853
550
551
  reconcile/test/test_secret_reader.py,sha256=kz7nzcPjvA08cytnvcA_PMA98AEyqJWsESkYeRn5xCk,4994
551
552
  reconcile/test/test_slack_base.py,sha256=pTUGvJ2S2wF3PhJyGWmiNXG52QtXKy2cbu-G8Ymrv6I,5019
@@ -618,7 +619,7 @@ reconcile/typed_queries/namespaces.py,sha256=vItPrn7sfcHOix-VvkzQkf54_ljzI_ymyxh
618
619
  reconcile/typed_queries/namespaces_minimal.py,sha256=rUtqNQ0ORXXUTQfnpsMURymAJ4gYtE77V-Lb3LiJFEY,278
619
620
  reconcile/typed_queries/ocm.py,sha256=aTXW9NaMpMq-90sBUAUQmGPtk6Hnsk2rzSbXv3pD8dY,312
620
621
  reconcile/typed_queries/pagerduty_instances.py,sha256=zxCNxMak4iikryePaRi71lTADV2k8UXPZvwz8bFFy_U,486
621
- reconcile/typed_queries/quay.py,sha256=OvkSDDbS3o4a4W5MqVxTAVmo47p5XegeoEVNiuqsevg,242
622
+ reconcile/typed_queries/quay.py,sha256=3IMy9jjHF2f9t47EXZOQVA3p0nFkWFhaFhxhvib-71o,644
622
623
  reconcile/typed_queries/repos.py,sha256=8A93dKDt6igT4ClqMjt7YUTsoP4qh1Wnm0W3xsMgj48,824
623
624
  reconcile/typed_queries/reserved_networks.py,sha256=-f_CIrTn8u-dotj5VKFlAcD7TX1CSSuR7Ko2zC8OKEM,358
624
625
  reconcile/typed_queries/saas_files.py,sha256=lPJNh5F2ThJUjW2zvsCKPLm2DVNBnbHFbzWByqTg2uM,14012
@@ -806,7 +807,7 @@ reconcile/utils/runtime/sharding.py,sha256=r0ieUtNed7NvknSw6qQrCkKpVXE1shuHGnfFc
806
807
  reconcile/utils/saasherder/__init__.py,sha256=J3MBZBFa5YmhqYm08QsjBXz8mFcVOCiOCkyIcw41t7E,343
807
808
  reconcile/utils/saasherder/interfaces.py,sha256=C2wrw34OXypshVocAsPrVZsSHptgw4g9u7Haa2wulZQ,9087
808
809
  reconcile/utils/saasherder/models.py,sha256=z8ln03zi2a8cu716NcNUDHp8Dv1VcVbhqdWVxCl7x9A,10148
809
- reconcile/utils/saasherder/saasherder.py,sha256=8yKSNuwLVJaJnOxGOHjhFaRqEmEbJxKqBj1-phI618o,84863
810
+ reconcile/utils/saasherder/saasherder.py,sha256=vaTQtDrJdm5wU8z0ROqEI-ewbzCkKAlHsEpP01Royvg,85048
810
811
  reconcile/utils/terraform/__init__.py,sha256=zNbiyTWo35AT1sFTElL2j_AA0jJ_yWE_bfFn-nD2xik,250
811
812
  reconcile/utils/terraform/config.py,sha256=5UVrd563TMcvi4ooa5JvWVDW1I3bIWg484u79evfV_8,164
812
813
  reconcile/utils/terraform/config_client.py,sha256=gRL1rQ0AqvShei_rcGqC3HDYGskOFKE1nPrJyJE9yno,4676
@@ -857,8 +858,8 @@ tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jr
857
858
  tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
858
859
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
859
860
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
860
- qontract_reconcile-0.10.1rc1005.dist-info/METADATA,sha256=ghM_m_o_Ig_BZqOUBeZmvzWuu4Lj4lnA-XiPOnYv7mk,2263
861
- qontract_reconcile-0.10.1rc1005.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
862
- qontract_reconcile-0.10.1rc1005.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
863
- qontract_reconcile-0.10.1rc1005.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
864
- qontract_reconcile-0.10.1rc1005.dist-info/RECORD,,
861
+ qontract_reconcile-0.10.1rc1006.dist-info/METADATA,sha256=N8FEuHE8ofYd2AbKUrxdFAxGzP86kKKawj2bbGdt_QM,2263
862
+ qontract_reconcile-0.10.1rc1006.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
863
+ qontract_reconcile-0.10.1rc1006.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
864
+ qontract_reconcile-0.10.1rc1006.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
865
+ qontract_reconcile-0.10.1rc1006.dist-info/RECORD,,
@@ -0,0 +1,68 @@
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
+
21
+ DEFINITION = """
22
+ query QuayOrgs {
23
+ orgs: quay_orgs_v1 {
24
+ name
25
+ instance {
26
+ url
27
+ }
28
+ }
29
+ }
30
+ """
31
+
32
+
33
+ class ConfiguredBaseModel(BaseModel):
34
+ class Config:
35
+ smart_union=True
36
+ extra=Extra.forbid
37
+
38
+
39
+ class QuayInstanceV1(ConfiguredBaseModel):
40
+ url: str = Field(..., alias="url")
41
+
42
+
43
+ class QuayOrgV1(ConfiguredBaseModel):
44
+ name: str = Field(..., alias="name")
45
+ instance: QuayInstanceV1 = Field(..., alias="instance")
46
+
47
+
48
+ class QuayOrgsQueryData(ConfiguredBaseModel):
49
+ orgs: Optional[list[QuayOrgV1]] = Field(..., alias="orgs")
50
+
51
+
52
+ def query(query_func: Callable, **kwargs: Any) -> QuayOrgsQueryData:
53
+ """
54
+ This is a convenience function which queries and parses the data into
55
+ concrete types. It should be compatible with most GQL clients.
56
+ You do not have to use it to consume the generated data classes.
57
+ Alternatively, you can also mime and alternate the behavior
58
+ of this function in the caller.
59
+
60
+ Parameters:
61
+ query_func (Callable): Function which queries your GQL Server
62
+ kwargs: optional arguments that will be passed to the query function
63
+
64
+ Returns:
65
+ QuayOrgsQueryData: queried data parsed into generated classes
66
+ """
67
+ raw_data: dict[Any, Any] = query_func(DEFINITION, **kwargs)
68
+ return QuayOrgsQueryData(**raw_data)
@@ -7,6 +7,7 @@ from reconcile.status import ExitCodes
7
7
  from reconcile.typed_queries.app_interface_vault_settings import (
8
8
  get_app_interface_vault_settings,
9
9
  )
10
+ from reconcile.typed_queries.quay import get_quay_instances, get_quay_orgs
10
11
  from reconcile.typed_queries.repos import get_repos
11
12
  from reconcile.typed_queries.saas_files import (
12
13
  get_saas_files,
@@ -48,6 +49,18 @@ def run(dry_run: bool, defer: Callable | None = None) -> None:
48
49
  missing_repos = [r for r in saasherder.repo_urls if r not in app_int_repos]
49
50
  for r in missing_repos:
50
51
  logging.error(f"repo is missing from codeComponents: {r}")
52
+ app_int_quay_instances = {i.url for i in get_quay_instances()}
53
+ app_int_quay_orgs = {(o.instance.url, o.name) for o in get_quay_orgs()}
54
+ missing_image_patterns = [
55
+ p
56
+ for p in saasherder.image_patterns
57
+ if (parts := p.split("/"))
58
+ and parts[0] in app_int_quay_instances
59
+ and len(parts) >= 2
60
+ and (parts[0], parts[1]) not in app_int_quay_orgs
61
+ ]
62
+ for p in missing_image_patterns:
63
+ logging.error(f"image pattern is missing from quayOrgs: {p}")
51
64
  jjb: JJB = init_jjb(secret_reader)
52
65
  saasherder.validate_upstream_jobs(jjb)
53
66
  if not saasherder.valid or missing_repos:
@@ -910,6 +910,27 @@ class TestCollectRepoUrls(TestCase):
910
910
  self.assertEqual({repo_url}, saasherder.repo_urls)
911
911
 
912
912
 
913
+ @pytest.mark.usefixtures("inject_gql_class_factory")
914
+ class TestCollectImagePatterns(TestCase):
915
+ def setUp(self) -> None:
916
+ self.saas_file = self.gql_class_factory( # type: ignore[attr-defined] # it's set in the fixture
917
+ SaasFile, Fixtures("saasherder").get_anymarkup("saas.gql.yml")
918
+ )
919
+
920
+ def test_collect_image_patterns(self) -> None:
921
+ image_pattern = "quay.io/centos/centos:centos8"
922
+ saasherder = SaasHerder(
923
+ [self.saas_file],
924
+ secret_reader=MockSecretReader(),
925
+ thread_pool_size=1,
926
+ integration="",
927
+ integration_version="",
928
+ hash_length=7,
929
+ repo_url="https://repo-url.com",
930
+ )
931
+ self.assertEqual({image_pattern}, saasherder.image_patterns)
932
+
933
+
913
934
  @pytest.mark.usefixtures("inject_gql_class_factory")
914
935
  class TestGetSaasFileAttribute(TestCase):
915
936
  def setUp(self) -> None:
@@ -1,7 +1,23 @@
1
- from reconcile.gql_definitions.common.quay_instances import QuayInstanceV1, query
1
+ from reconcile.gql_definitions.common.quay_instances import (
2
+ QuayInstanceV1,
3
+ )
4
+ from reconcile.gql_definitions.common.quay_instances import (
5
+ query as quay_instances_query,
6
+ )
7
+ from reconcile.gql_definitions.common.quay_orgs import (
8
+ QuayOrgV1,
9
+ )
10
+ from reconcile.gql_definitions.common.quay_orgs import (
11
+ query as quay_orgs_query,
12
+ )
2
13
  from reconcile.utils import gql
3
14
 
4
15
 
5
16
  def get_quay_instances() -> list[QuayInstanceV1]:
6
- data = query(gql.get_api().query)
17
+ data = quay_instances_query(gql.get_api().query)
7
18
  return list(data.instances or [])
19
+
20
+
21
+ def get_quay_orgs() -> list[QuayOrgV1]:
22
+ data = quay_orgs_query(gql.get_api().query)
23
+ return list(data.orgs or [])
@@ -124,6 +124,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
124
124
  self.error_registered = False
125
125
  self.saas_files = saas_files
126
126
  self.repo_urls = self._collect_repo_urls()
127
+ self.image_patterns = self._collect_image_patterns()
127
128
  self.resolve_templated_parameters(self.saas_files)
128
129
  if validate:
129
130
  self._validate_saas_files()
@@ -707,6 +708,9 @@ class SaasHerder: # pylint: disable=too-many-public-methods
707
708
  for rt in saas_file.resource_templates
708
709
  }
709
710
 
711
+ def _collect_image_patterns(self) -> set[str]:
712
+ return {p for sf in self.saas_files for p in sf.image_patterns}
713
+
710
714
  @staticmethod
711
715
  def _get_file_contents_github(repo: Repository, path: str, commit_sha: str) -> str:
712
716
  f = repo.get_contents(path, commit_sha)