qontract-reconcile 0.10.1rc1097__py3-none-any.whl → 0.10.1rc1099__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.1rc1097
3
+ Version: 0.10.1rc1099
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
@@ -160,11 +160,11 @@ reconcile/aws_version_sync/merge_request_manager/merge_request.py,sha256=2FbqLLd
160
160
  reconcile/aws_version_sync/merge_request_manager/merge_request_manager.py,sha256=3bRpw7DluiYw3daRg0yAyCSGYf39Ru0d8lUjoepDSpU,5525
161
161
  reconcile/change_owners/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
162
162
  reconcile/change_owners/approver.py,sha256=Z3_11vnK2WNOxjEEXVDh0224-_-qbt9d6mBeVE-7fsc,2259
163
- reconcile/change_owners/bundle.py,sha256=ZIlXRo6Z2raeWSCUqYsexBdol-q-r9kWJs5O_YPaEYk,5273
164
- reconcile/change_owners/change_log_tracking.py,sha256=tGN-z1HGf0EjC3BSqs54WhQwIb7bhXEeTBm2v2Q2ju0,7075
163
+ reconcile/change_owners/bundle.py,sha256=h30fU-JmLH5a-rCAovpzTeTkkkgZztsZ5A2raee0YuU,5355
164
+ reconcile/change_owners/change_log_tracking.py,sha256=qA51PpR7CZYPIAalswyOqJLto3qhgHNXYWR1iz64_Xg,7329
165
165
  reconcile/change_owners/change_owners.py,sha256=0HRJhDm0oW3uYJFgzynqA1gA0lbhalhSkmWOiQmr-NM,17062
166
166
  reconcile/change_owners/change_types.py,sha256=HEsoBduhcczAXZHwT26mr5sVPxtf8J6tsvjSDDI1ceI,32077
167
- reconcile/change_owners/changes.py,sha256=pa3cNAL-Xawh700ARJJQjY0p09NA1J2329RcE0F0MHM,17224
167
+ reconcile/change_owners/changes.py,sha256=IO2va8RZ1UsC_iosQR7qiQir7UwGuMQfFwceoU0utCI,18162
168
168
  reconcile/change_owners/decision.py,sha256=iUJcIc_N_RqXIAY8D10RZqPMC2OinsHTMcqI6f6uylE,7606
169
169
  reconcile/change_owners/diff.py,sha256=0vyu29xCL24ZhUa7hqBni0NaxoCYRXLwvA-h8V23YQ4,9009
170
170
  reconcile/change_owners/implicit_ownership.py,sha256=6BehZvx4IjrphmOt_LLLk9_02Fl5BY5jd00Wuz_PBZk,4234
@@ -292,7 +292,7 @@ reconcile/gql_definitions/endpoints_discovery/namespaces.py,sha256=FqJ0H7NdsIm5B
292
292
  reconcile/gql_definitions/external_resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
293
293
  reconcile/gql_definitions/external_resources/aws_accounts.py,sha256=XR69j9dpTQ0gv8y-AZN7AJ0dPvO-wbHscyCDgrax6Bk,2046
294
294
  reconcile/gql_definitions/external_resources/external_resources_modules.py,sha256=HFOQjmNbNxk0j5nChxppQeCnJjeDsqibJkPgA7R1zRw,2417
295
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py,sha256=6WiI1exSzyEel_vOeVH3zitroGXI7JqDkDSKav_SzT4,42483
295
+ reconcile/gql_definitions/external_resources/external_resources_namespaces.py,sha256=5aQaNJC73cT-EqiDZ8rq5zaxUAX5dcbyuRp-YEBADwI,42533
296
296
  reconcile/gql_definitions/external_resources/external_resources_settings.py,sha256=Hw9n_90BPG6Lnt2PT3mHc6p0KEm2CxKxvSGRFc_Dhus,2982
297
297
  reconcile/gql_definitions/fragments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
298
298
  reconcile/gql_definitions/fragments/aus_organization.py,sha256=uBKbTuBa3CZmTXR5HOcGhRcu2U9kM93KbYmoWTxcpB0,4767
@@ -332,7 +332,7 @@ reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py,sha256=P
332
332
  reconcile/gql_definitions/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
333
333
  reconcile/gql_definitions/integrations/integrations.py,sha256=HosEgRUlAkxLNoj2cnq3mrTdWDn9UvbNmtz6OcweIYk,11668
334
334
  reconcile/gql_definitions/jenkins_configs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
335
- reconcile/gql_definitions/jenkins_configs/jenkins_configs.py,sha256=0nMkH0G-AjQwu53fqHykth6X6jjbHdW2hBp5n7N-r24,2766
335
+ reconcile/gql_definitions/jenkins_configs/jenkins_configs.py,sha256=kr1RwKcSpmpBkotl8rR0cOZ02Co5FAbE1he80CCFbTc,2961
336
336
  reconcile/gql_definitions/jenkins_configs/jenkins_instances.py,sha256=b3gYVzQavxeLe4jSM5ZxrO77Vvs7kOljVOXEkTO943U,2165
337
337
  reconcile/gql_definitions/jira/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
338
338
  reconcile/gql_definitions/jira/jira_servers.py,sha256=N7mvIdqoXT-90abkiaC2bxz2ZjW3d826qVV5OL8_TAM,2223
@@ -574,7 +574,7 @@ reconcile/test/test_terraform_vpc_peerings.py,sha256=bpjCjhmic07cw3XKSHf-2JvmLuW
574
574
  reconcile/test/test_terraform_vpc_peerings_build_desired_state.py,sha256=cHmr1_yhRgfdqlFX6TMw-aiKXebaRv0szl16M9YRJic,49988
575
575
  reconcile/test/test_three_way_diff_strategy.py,sha256=v3rNkQFNy5e1uyfeNSlNBA07fvrPGD0aXD91Lgv8oxc,4062
576
576
  reconcile/test/test_utils_jinja2.py,sha256=rKugJEPl0qFC9joenJBXyk2qe-9md31-4EdxvQ2h5cs,4058
577
- reconcile/test/test_vault_replication.py,sha256=wlc4jm9f8P641UvvxIFFFc5_unJysNkOVrKJscjhQr0,16867
577
+ reconcile/test/test_vault_replication.py,sha256=rMx-opCpC8GobL2vDj_yYYuSgX0crQuncyvrKul1xoM,16998
578
578
  reconcile/test/test_vault_utils.py,sha256=vbJnc89XAuE07qbTuWxHM5o9F6R9SO5aHXA38fwxT7A,1122
579
579
  reconcile/test/test_version_bump.py,sha256=q6-3Y1roriI6YWpFwaHOMN7emEP3yL33sh_0VdbmG7E,511
580
580
  reconcile/test/test_vpc_peerings_validator.py,sha256=dFSmjc_dMN2GqMbntCFpa7PUZmyYuQ9DKffh-T5wmxM,6639
@@ -621,7 +621,7 @@ reconcile/typed_queries/get_state_aws_account.py,sha256=CSJjVPWsUZ2rkGIt8ehoQt7h
621
621
  reconcile/typed_queries/github_orgs.py,sha256=UZhoPl8qvA_tcO7CZlN8GuMKckt3ywd47Suu61rgHsc,258
622
622
  reconcile/typed_queries/gitlab_instances.py,sha256=ZVQHy2W9xIp53f5qYkjKLHLHgOVtQpxTfcmM1C2046g,291
623
623
  reconcile/typed_queries/glitchtip.py,sha256=fYHIT3rXWlqTloRH5zjNFb3N4HCumfHwBPBFlS6KDG4,277
624
- reconcile/typed_queries/jenkins.py,sha256=1XnCwpSXsuFpPhtZruGKncxEIceZNx334Jv5h0rbS78,296
624
+ reconcile/typed_queries/jenkins.py,sha256=Pus8Rhsb04F92Iqh31xe-rW1TLiEziIWd0UAthvLYkY,794
625
625
  reconcile/typed_queries/jira.py,sha256=jq6-ERCr_Fh96_3i9A9UKfpAAstoc4Iz6Irl-_0IUkw,235
626
626
  reconcile/typed_queries/jira_settings.py,sha256=i0ddx5xxHrM1v-9mtL_6OB-jBFLw7-HS6xenpIDjrkw,570
627
627
  reconcile/typed_queries/jiralert_settings.py,sha256=y59S5xvYmuaGxszzfKhVLjbCyDwKiaSIlajocbK5MDE,793
@@ -870,8 +870,8 @@ tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jr
870
870
  tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
871
871
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
872
872
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
873
- qontract_reconcile-0.10.1rc1097.dist-info/METADATA,sha256=8Jqb-Z_PMsD3CfIqD_cm6fq0u-dRW_cmhM8xey-gj6k,2213
874
- qontract_reconcile-0.10.1rc1097.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
875
- qontract_reconcile-0.10.1rc1097.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
876
- qontract_reconcile-0.10.1rc1097.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
877
- qontract_reconcile-0.10.1rc1097.dist-info/RECORD,,
873
+ qontract_reconcile-0.10.1rc1099.dist-info/METADATA,sha256=XIDqAEaqXoUt0g5mfRtTjElTwRDzvydPiVGOZL4D3so,2213
874
+ qontract_reconcile-0.10.1rc1099.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
875
+ qontract_reconcile-0.10.1rc1099.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
876
+ qontract_reconcile-0.10.1rc1099.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
877
+ qontract_reconcile-0.10.1rc1099.dist-info/RECORD,,
@@ -32,6 +32,7 @@ class FileRef:
32
32
  file_type: BundleFileType
33
33
  path: str
34
34
  schema: str | None
35
+ json_path: str | None = None
35
36
 
36
37
  def __str__(self) -> str:
37
38
  return f"{self.file_type.value}:{self.path}"
@@ -106,6 +107,7 @@ class QontractServerResourcefileBackref(BaseModel):
106
107
 
107
108
  path: str
108
109
  datafileschema: str = Field(..., alias="datafileSchema")
110
+ jsonpath: str = Field(..., alias="jsonpath")
109
111
 
110
112
 
111
113
  class QontractServerResourcefileDiffState(BaseModel):
@@ -12,9 +12,14 @@ from reconcile.change_owners.change_owners import (
12
12
  init_gitlab,
13
13
  )
14
14
  from reconcile.change_owners.change_types import ChangeTypeContext
15
- from reconcile.change_owners.changes import aggregate_file_moves, parse_bundle_changes
15
+ from reconcile.change_owners.changes import (
16
+ aggregate_file_moves,
17
+ aggregate_resource_changes,
18
+ parse_bundle_changes,
19
+ )
16
20
  from reconcile.typed_queries.apps import get_apps
17
21
  from reconcile.typed_queries.external_resources import get_namespaces
22
+ from reconcile.typed_queries.jenkins import get_jenkins_configs
18
23
  from reconcile.utils import gql
19
24
  from reconcile.utils.defer import defer
20
25
  from reconcile.utils.gitlab_api import MRState
@@ -73,6 +78,7 @@ class ChangeLogIntegration(QontractReconcileIntegration[ChangeLogIntegrationPara
73
78
  cluster = ns.cluster.name
74
79
  app = ns.app.name
75
80
  app_names_by_cluster_name[cluster].add(app)
81
+ jenkins_configs = get_jenkins_configs()
76
82
 
77
83
  integration_state = init_state(
78
84
  integration=self.name,
@@ -127,7 +133,10 @@ class ChangeLogIntegration(QontractReconcileIntegration[ChangeLogIntegrationPara
127
133
  change_log_item.error = True
128
134
  continue
129
135
  diff = QontractServerDiff(**obj)
130
- changes = aggregate_file_moves(parse_bundle_changes(diff))
136
+ changes = aggregate_resource_changes(
137
+ aggregate_file_moves(parse_bundle_changes(diff)),
138
+ {c.path: c.dict() for c in namespaces + jenkins_configs},
139
+ )
131
140
  for change in changes:
132
141
  logging.debug(f"Processing change {change}")
133
142
  change_versions = filter(None, [change.old, change.new])
@@ -171,15 +180,15 @@ class ChangeLogIntegration(QontractReconcileIntegration[ChangeLogIntegrationPara
171
180
  if ctp.name not in change_log_item.change_types:
172
181
  change_log_item.change_types.append(ctp.name)
173
182
 
174
- change_log_item.change_types.extend(
175
- special_dir
176
- for special_dir in ("docs", "hack")
177
- if any(
178
- path.startswith(special_dir)
179
- for gl_diff in gl_commit.diff()
180
- for path in (gl_diff["old_path"], gl_diff["new_path"])
181
- )
183
+ change_log_item.change_types.extend(
184
+ special_dir
185
+ for special_dir in ("docs", "hack")
186
+ if any(
187
+ path.startswith(special_dir)
188
+ for gl_diff in gl_commit.diff()
189
+ for path in (gl_diff["old_path"], gl_diff["new_path"])
182
190
  )
191
+ )
183
192
 
184
193
  change_log.items = sorted(
185
194
  change_log.items, key=lambda i: i.merged_at, reverse=True
@@ -10,6 +10,7 @@ from dataclasses import (
10
10
  from typing import Any
11
11
 
12
12
  import anymarkup
13
+ import jsonpath_ng
13
14
 
14
15
  from reconcile.change_owners.bundle import (
15
16
  DATAFILE_PATH_FIELD_NAME,
@@ -434,6 +435,7 @@ def parse_bundle_changes(
434
435
  file_type=BundleFileType.DATAFILE,
435
436
  path=br.path,
436
437
  schema=br.datafileschema,
438
+ json_path=br.jsonpath,
437
439
  )
438
440
  for br in (rf.old.backrefs if rf.old and rf.old.backrefs else [])
439
441
  ],
@@ -442,6 +444,7 @@ def parse_bundle_changes(
442
444
  file_type=BundleFileType.DATAFILE,
443
445
  path=br.path,
444
446
  schema=br.datafileschema,
447
+ json_path=br.jsonpath,
445
448
  )
446
449
  for br in (rf.new.backrefs if rf.new and rf.new.backrefs else [])
447
450
  ],
@@ -454,3 +457,31 @@ def parse_bundle_changes(
454
457
  )
455
458
 
456
459
  return change_list
460
+
461
+
462
+ def aggregate_resource_changes(
463
+ bundle_changes: list[BundleFileChange],
464
+ content_store: dict[str, Any],
465
+ ) -> list[BundleFileChange]:
466
+ resource_changes = [
467
+ BundleFileChange(
468
+ fileref=file_ref,
469
+ old=file_content,
470
+ new=file_content,
471
+ old_content_sha="",
472
+ new_content_sha="",
473
+ diffs=[
474
+ Diff(
475
+ path=jsonpath_ng.parse(file_ref.json_path),
476
+ diff_type=DiffType.CHANGED,
477
+ old=file_content,
478
+ new=file_content,
479
+ )
480
+ ],
481
+ )
482
+ for change in bundle_changes
483
+ for file_ref in change.old_backrefs | change.new_backrefs
484
+ if (file_content := content_store[file_ref.path])
485
+ ]
486
+
487
+ return bundle_changes + resource_changes
@@ -62,6 +62,7 @@ fragment VaultSecret on VaultSecret_v1 {
62
62
 
63
63
  query ExternalResourcesNamespaces {
64
64
  namespaces: namespaces_v1 {
65
+ path
65
66
  name
66
67
  delete
67
68
  clusterAdmin
@@ -1044,6 +1045,7 @@ class NamespaceV1_ClusterV1(ConfiguredBaseModel):
1044
1045
 
1045
1046
 
1046
1047
  class NamespaceV1(ConfiguredBaseModel):
1048
+ path: str = Field(..., alias="path")
1047
1049
  name: str = Field(..., alias="name")
1048
1050
  delete: Optional[bool] = Field(..., alias="delete")
1049
1051
  cluster_admin: Optional[bool] = Field(..., alias="clusterAdmin")
@@ -30,7 +30,11 @@ fragment VaultSecret on VaultSecret_v1 {
30
30
 
31
31
  query JenkinsConfigs {
32
32
  jenkins_configs: jenkins_configs_v1 {
33
+ path
33
34
  name
35
+ app {
36
+ name
37
+ }
34
38
  ...on JenkinsConfig_v1 {
35
39
  instance {
36
40
  name
@@ -57,8 +61,14 @@ class ConfiguredBaseModel(BaseModel):
57
61
  extra=Extra.forbid
58
62
 
59
63
 
64
+ class AppV1(ConfiguredBaseModel):
65
+ name: str = Field(..., alias="name")
66
+
67
+
60
68
  class JenkinsConfigV1(ConfiguredBaseModel):
69
+ path: str = Field(..., alias="path")
61
70
  name: str = Field(..., alias="name")
71
+ app: AppV1 = Field(..., alias="app")
62
72
 
63
73
 
64
74
  class JenkinsInstanceV1(ConfiguredBaseModel):
@@ -5,6 +5,7 @@ import pytest
5
5
  import reconcile.vault_replication as integ
6
6
  from reconcile.gql_definitions.fragments.vault_secret import VaultSecret
7
7
  from reconcile.gql_definitions.jenkins_configs.jenkins_configs import (
8
+ AppV1,
8
9
  JenkinsConfigsQueryData,
9
10
  JenkinsConfigV1_JenkinsConfigV1,
10
11
  JenkinsInstanceV1,
@@ -32,7 +33,11 @@ def jenkins_config_query_data() -> JenkinsConfigsQueryData:
32
33
  return JenkinsConfigsQueryData(
33
34
  jenkins_configs=[
34
35
  JenkinsConfigV1_JenkinsConfigV1(
36
+ path="path/to/config",
35
37
  name="jenkins-secrets-config",
38
+ app=AppV1(
39
+ name="my-app",
40
+ ),
36
41
  instance=JenkinsInstanceV1(
37
42
  name="jenkins-instance",
38
43
  serverUrl="https://test.net",
@@ -1,11 +1,25 @@
1
+ from reconcile.gql_definitions.jenkins_configs.jenkins_configs import (
2
+ JenkinsConfigV1,
3
+ )
4
+ from reconcile.gql_definitions.jenkins_configs.jenkins_configs import (
5
+ query as jenkins_configs_query,
6
+ )
1
7
  from reconcile.gql_definitions.jenkins_configs.jenkins_instances import (
2
8
  JenkinsInstanceV1,
3
- query,
9
+ )
10
+ from reconcile.gql_definitions.jenkins_configs.jenkins_instances import (
11
+ query as jenkins_instances_query,
4
12
  )
5
13
  from reconcile.utils import gql
6
14
 
7
15
 
8
16
  def get_jenkins_instances() -> list[JenkinsInstanceV1]:
9
17
  gqlapi = gql.get_api()
10
- data = query(gqlapi.query)
18
+ data = jenkins_instances_query(gqlapi.query)
11
19
  return list(data.instances or [])
20
+
21
+
22
+ def get_jenkins_configs() -> list[JenkinsConfigV1]:
23
+ gqlapi = gql.get_api()
24
+ data = jenkins_configs_query(gqlapi.query)
25
+ return list(data.jenkins_configs or [])