qontract-reconcile 0.9.1rc162__py3-none-any.whl → 0.9.1rc164__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.
Files changed (30) hide show
  1. {qontract_reconcile-0.9.1rc162.dist-info → qontract_reconcile-0.9.1rc164.dist-info}/METADATA +2 -2
  2. {qontract_reconcile-0.9.1rc162.dist-info → qontract_reconcile-0.9.1rc164.dist-info}/RECORD +21 -30
  3. reconcile/glitchtip_project_dsn/integration.py +3 -0
  4. reconcile/jenkins_job_builder.py +2 -5
  5. reconcile/openshift_base.py +11 -11
  6. reconcile/openshift_saas_deploy.py +52 -57
  7. reconcile/openshift_saas_deploy_trigger_base.py +48 -55
  8. reconcile/openshift_saas_deploy_trigger_cleaner.py +2 -2
  9. reconcile/openshift_tekton_resources.py +1 -1
  10. reconcile/saas_file_validator.py +10 -23
  11. reconcile/slack_base.py +2 -5
  12. reconcile/test/conftest.py +0 -11
  13. reconcile/test/test_auto_promoter.py +42 -199
  14. reconcile/test/test_saasherder.py +463 -398
  15. reconcile/test/test_saasherder_allowed_secret_paths.py +36 -87
  16. reconcile/utils/mr/auto_promoter.py +50 -58
  17. reconcile/utils/mr/base.py +2 -6
  18. reconcile/utils/{saasherder/saasherder.py → saasherder.py} +736 -656
  19. reconcile/gql_definitions/common/app_code_component_repos.py +0 -68
  20. reconcile/gql_definitions/common/saas_files.py +0 -542
  21. reconcile/gql_definitions/common/saasherder_settings.py +0 -62
  22. reconcile/gql_definitions/fragments/oc_connection_cluster.py +0 -47
  23. reconcile/typed_queries/repos.py +0 -17
  24. reconcile/typed_queries/saas_files.py +0 -61
  25. reconcile/utils/saasherder/__init__.py +0 -17
  26. reconcile/utils/saasherder/interfaces.py +0 -404
  27. reconcile/utils/saasherder/models.py +0 -203
  28. {qontract_reconcile-0.9.1rc162.dist-info → qontract_reconcile-0.9.1rc164.dist-info}/WHEEL +0 -0
  29. {qontract_reconcile-0.9.1rc162.dist-info → qontract_reconcile-0.9.1rc164.dist-info}/entry_points.txt +0 -0
  30. {qontract_reconcile-0.9.1rc162.dist-info → qontract_reconcile-0.9.1rc164.dist-info}/top_level.txt +0 -0
@@ -1,351 +1,319 @@
1
- from collections.abc import (
2
- Callable,
3
- Iterable,
4
- MutableMapping,
5
- )
6
- from typing import (
7
- Any,
8
- Optional,
9
- )
1
+ from typing import Any
10
2
  from unittest import TestCase
11
3
  from unittest.mock import (
12
4
  MagicMock,
13
5
  patch,
14
6
  )
15
7
 
16
- import pytest
17
8
  import yaml
18
- from github import (
19
- Github,
20
- GithubException,
21
- )
22
- from pydantic import BaseModel
9
+ from github import GithubException
23
10
 
24
- from reconcile.gql_definitions.common.saas_files import (
25
- SaasFileV2,
26
- SaasResourceTemplateTargetImageV1,
27
- SaasResourceTemplateTargetPromotionV1,
28
- SaasResourceTemplateV2,
29
- )
30
11
  from reconcile.utils.jjb_client import JJB
31
12
  from reconcile.utils.openshift_resource import ResourceInventory
32
- from reconcile.utils.saasherder import SaasHerder
33
- from reconcile.utils.saasherder.models import TriggerSpecMovingCommit
34
- from reconcile.utils.secret_reader import SecretReaderBase
13
+ from reconcile.utils.saasherder import (
14
+ TARGET_CONFIG_HASH,
15
+ SaasHerder,
16
+ TriggerSpecConfig,
17
+ TriggerSpecMovingCommit,
18
+ )
35
19
 
36
20
  from .fixtures import Fixtures
37
21
 
38
22
 
39
23
  class MockJJB:
40
- def __init__(self, data: dict[str, list[dict]]) -> None:
24
+ def __init__(self, data):
41
25
  self.jobs = data
42
26
 
43
- def get_all_jobs(self, job_types: Iterable[str]) -> dict[str, list[dict]]:
27
+ def get_all_jobs(self, job_types):
44
28
  return self.jobs
45
29
 
46
30
  @staticmethod
47
- def get_repo_url(job: dict[str, Any]) -> str:
31
+ def get_repo_url(job):
48
32
  return JJB.get_repo_url(job)
49
33
 
50
34
  @staticmethod
51
- def get_ref(job: dict[str, Any]) -> str:
35
+ def get_ref(job):
52
36
  return JJB.get_ref(job)
53
37
 
54
38
 
55
- class MockSecretReader(SecretReaderBase):
56
- """
57
- Read secrets from a config file
58
- """
59
-
60
- def _read(
61
- self, path: str, field: str, format: Optional[str], version: Optional[int]
62
- ) -> str:
63
- return "secret"
64
-
65
- def _read_all(
66
- self, path: str, field: str, format: Optional[str], version: Optional[int]
67
- ) -> dict[str, str]:
68
- return {"param": "secret"}
69
-
70
-
71
- @pytest.fixture()
72
- def inject_gql_class_factory(
73
- request: pytest.FixtureRequest,
74
- gql_class_factory: Callable[..., SaasFileV2],
75
- ) -> None:
76
- def _gql_class_factory(
77
- self: Any,
78
- klass: type[BaseModel],
79
- data: Optional[MutableMapping[str, Any]] = None,
80
- ) -> BaseModel:
81
- return gql_class_factory(klass, data)
82
-
83
- request.cls.gql_class_factory = _gql_class_factory
84
-
85
-
86
- @pytest.mark.usefixtures("inject_gql_class_factory")
87
39
  class TestSaasFileValid(TestCase):
88
- def setUp(self) -> None:
89
- self.saas_file = self.gql_class_factory( # type: ignore[attr-defined] # it's set in the fixture
90
- SaasFileV2, Fixtures("saasherder").get_anymarkup("saas.gql.yml")
91
- )
40
+ def setUp(self):
41
+ self.saas_files = [
42
+ {
43
+ "path": "path1",
44
+ "name": "a1",
45
+ "managedResourceTypes": [],
46
+ "resourceTemplates": [
47
+ {
48
+ "name": "rt",
49
+ "url": "url",
50
+ "targets": [
51
+ {
52
+ "namespace": {
53
+ "name": "ns",
54
+ "environment": {"name": "env1", "parameters": "{}"},
55
+ "cluster": {"name": "cluster"},
56
+ },
57
+ "ref": "main",
58
+ "upstream": {"instance": {"name": "ci"}, "name": "job"},
59
+ "parameters": {},
60
+ },
61
+ {
62
+ "namespace": {
63
+ "name": "ns",
64
+ "environment": {"name": "env2", "parameters": "{}"},
65
+ "cluster": {"name": "cluster"},
66
+ },
67
+ "ref": "master",
68
+ "upstream": {"instance": {"name": "ci"}, "name": "job"},
69
+ "parameters": {},
70
+ },
71
+ {
72
+ "namespace": {
73
+ "name": "ns",
74
+ "environment": {"name": "env3", "parameters": "{}"},
75
+ "cluster": {"name": "cluster"},
76
+ },
77
+ "ref": "master",
78
+ "image": {
79
+ "org": {
80
+ "name": "org1",
81
+ "instance": {"name": "q1"},
82
+ },
83
+ "name": "image",
84
+ },
85
+ "parameters": {},
86
+ },
87
+ {
88
+ "namespace": {
89
+ "name": "ns",
90
+ "environment": {"name": "env4", "parameters": "{}"},
91
+ "cluster": {"name": "cluster"},
92
+ },
93
+ "ref": "2637b6c41bda7731b1bcaaf18b4a50d7c5e63e30",
94
+ "parameters": {},
95
+ },
96
+ ],
97
+ }
98
+ ],
99
+ "roles": [{"users": [{"org_username": "myname"}]}],
100
+ "selfServiceRoles": [
101
+ {"users": [{"org_username": "theirname"}], "bots": []}
102
+ ],
103
+ }
104
+ ]
92
105
  jjb_mock_data = {
93
106
  "ci": [
94
107
  {
95
108
  "name": "job",
96
- "properties": [
97
- {
98
- "github": {
99
- "url": "https://github.com/app-sre/test-saas-deployments"
100
- }
101
- }
102
- ],
109
+ "properties": [{"github": {"url": "url"}}],
103
110
  "scm": [{"git": {"branches": ["main"]}}],
104
111
  },
105
112
  {
106
113
  "name": "job",
107
- "properties": [
108
- {
109
- "github": {
110
- "url": "https://github.com/app-sre/test-saas-deployments"
111
- }
112
- }
113
- ],
114
+ "properties": [{"github": {"url": "url"}}],
114
115
  "scm": [{"git": {"branches": ["master"]}}],
115
116
  },
116
117
  ]
117
118
  }
118
119
  self.jjb = MockJJB(jjb_mock_data)
119
120
 
120
- def test_check_saas_file_env_combo_unique(self) -> None:
121
+ def test_check_saas_file_env_combo_unique(self):
121
122
  saasherder = SaasHerder(
122
- [self.saas_file],
123
- secret_reader=MockSecretReader(),
123
+ self.saas_files,
124
124
  thread_pool_size=1,
125
+ gitlab=None,
125
126
  integration="",
126
127
  integration_version="",
127
- hash_length=7,
128
- repo_url="https://repo-url.com",
128
+ settings={},
129
129
  validate=True,
130
130
  )
131
+
131
132
  self.assertTrue(saasherder.valid)
132
133
 
133
- def test_check_saas_file_env_combo_not_unique(self) -> None:
134
- self.saas_file.name = "long-name-which-is-too-long-to-produce-unique-combo"
134
+ def test_check_saas_file_env_combo_not_unique(self):
135
+ self.saas_files[0][
136
+ "name"
137
+ ] = "long-name-which-is-too-long-to-produce-unique-combo"
135
138
  saasherder = SaasHerder(
136
- [self.saas_file],
137
- secret_reader=MockSecretReader(),
139
+ self.saas_files,
138
140
  thread_pool_size=1,
141
+ gitlab=None,
139
142
  integration="",
140
143
  integration_version="",
141
- hash_length=7,
142
- repo_url="https://repo-url.com",
144
+ settings={},
143
145
  validate=True,
144
146
  )
145
147
 
146
148
  self.assertFalse(saasherder.valid)
147
149
 
148
- def test_saas_file_auto_promotion_used_with_commit_sha(self) -> None:
149
- self.saas_file.resource_templates[0].targets[
150
- 1
151
- ].ref = "1234567890123456789012345678901234567890"
152
- self.saas_file.resource_templates[0].targets[
153
- 1
154
- ].promotion = SaasResourceTemplateTargetPromotionV1(
155
- auto=True, publish=None, subscribe=None, promotion_data=None
156
- )
150
+ def test_saas_file_auto_promotion_used_with_commit_sha(self):
151
+ self.saas_files[0]["resourceTemplates"][0]["targets"][3]["promotion"] = {
152
+ "auto": True
153
+ }
157
154
  saasherder = SaasHerder(
158
- [self.saas_file],
159
- secret_reader=MockSecretReader(),
155
+ self.saas_files,
160
156
  thread_pool_size=1,
157
+ gitlab=None,
161
158
  integration="",
162
159
  integration_version="",
163
- hash_length=7,
164
- repo_url="https://repo-url.com",
160
+ settings={},
165
161
  validate=True,
166
162
  )
167
163
 
168
164
  self.assertTrue(saasherder.valid)
169
165
 
170
- def test_saas_file_auto_promotion_not_used_with_commit_sha(self) -> None:
171
- self.saas_file.resource_templates[0].targets[1].ref = "main"
172
- self.saas_file.resource_templates[0].targets[
173
- 1
174
- ].promotion = SaasResourceTemplateTargetPromotionV1(
175
- auto=True, publish=None, subscribe=None, promotion_data=None
176
- )
166
+ def test_saas_file_auto_promotion_not_used_with_commit_sha(self):
167
+ self.saas_files[0]["resourceTemplates"][0]["targets"][2]["ref"] = "main"
168
+ self.saas_files[0]["resourceTemplates"][0]["targets"][2]["promotion"] = {
169
+ "auto": True
170
+ }
177
171
  saasherder = SaasHerder(
178
- [self.saas_file],
179
- secret_reader=MockSecretReader(),
172
+ self.saas_files,
180
173
  thread_pool_size=1,
174
+ gitlab=None,
181
175
  integration="",
182
176
  integration_version="",
183
- hash_length=7,
184
- repo_url="https://repo-url.com",
177
+ settings={},
185
178
  validate=True,
186
179
  )
187
180
 
188
181
  self.assertFalse(saasherder.valid)
189
182
 
190
- def test_check_saas_file_upstream_not_used_with_commit_sha(self) -> None:
183
+ def test_check_saas_file_upstream_not_used_with_commit_sha(self):
191
184
  saasherder = SaasHerder(
192
- [self.saas_file],
193
- secret_reader=MockSecretReader(),
185
+ self.saas_files,
194
186
  thread_pool_size=1,
187
+ gitlab=None,
195
188
  integration="",
196
189
  integration_version="",
197
- hash_length=7,
198
- repo_url="https://repo-url.com",
190
+ settings={},
199
191
  validate=True,
200
192
  )
201
193
 
202
194
  self.assertTrue(saasherder.valid)
203
195
 
204
- def test_check_saas_file_upstream_used_with_commit_sha(self) -> None:
205
- self.saas_file.resource_templates[0].targets[
206
- 0
207
- ].ref = "2637b6c41bda7731b1bcaaf18b4a50d7c5e63e30"
196
+ def test_check_saas_file_upstream_used_with_commit_sha(self):
197
+ self.saas_files[0]["resourceTemplates"][0]["targets"][0][
198
+ "ref"
199
+ ] = "2637b6c41bda7731b1bcaaf18b4a50d7c5e63e30"
208
200
  saasherder = SaasHerder(
209
- [self.saas_file],
210
- secret_reader=MockSecretReader(),
201
+ self.saas_files,
211
202
  thread_pool_size=1,
203
+ gitlab=None,
212
204
  integration="",
213
205
  integration_version="",
214
- hash_length=7,
215
- repo_url="https://repo-url.com",
206
+ settings={},
216
207
  validate=True,
217
208
  )
218
209
 
219
210
  self.assertFalse(saasherder.valid)
220
211
 
221
- def test_check_saas_file_upstream_used_with_image(self) -> None:
222
- self.saas_file.resource_templates[0].targets[
223
- 0
224
- ].image = SaasResourceTemplateTargetImageV1(
225
- **{"name": "image", "org": {"name": "org", "instance": {"url": "url"}}}
226
- )
212
+ def test_check_saas_file_upstream_used_with_image(self):
213
+ self.saas_files[0]["resourceTemplates"][0]["targets"][0]["image"] = "here"
227
214
  saasherder = SaasHerder(
228
- [self.saas_file],
229
- secret_reader=MockSecretReader(),
215
+ self.saas_files,
230
216
  thread_pool_size=1,
217
+ gitlab=None,
231
218
  integration="",
232
219
  integration_version="",
233
- hash_length=7,
234
- repo_url="https://repo-url.com",
220
+ settings={},
235
221
  validate=True,
236
222
  )
237
223
 
238
224
  self.assertFalse(saasherder.valid)
239
225
 
240
- def test_check_saas_file_image_used_with_commit_sha(self) -> None:
241
- self.saas_file.resource_templates[0].targets[
242
- 0
243
- ].ref = "2637b6c41bda7731b1bcaaf18b4a50d7c5e63e30"
244
- self.saas_file.resource_templates[0].targets[
245
- 0
246
- ].image = SaasResourceTemplateTargetImageV1(
247
- **{"name": "image", "org": {"name": "org", "instance": {"url": "url"}}}
248
- )
226
+ def test_check_saas_file_image_used_with_commit_sha(self):
227
+ self.saas_files[0]["resourceTemplates"][0]["targets"][2][
228
+ "ref"
229
+ ] = "2637b6c41bda7731b1bcaaf18b4a50d7c5e63e30"
249
230
  saasherder = SaasHerder(
250
- [self.saas_file],
251
- secret_reader=MockSecretReader(),
231
+ self.saas_files,
252
232
  thread_pool_size=1,
233
+ gitlab=None,
253
234
  integration="",
254
235
  integration_version="",
255
- hash_length=7,
256
- repo_url="https://repo-url.com",
236
+ settings={},
257
237
  validate=True,
258
238
  )
259
239
 
260
240
  self.assertFalse(saasherder.valid)
261
241
 
262
- def test_validate_image_tag_not_equals_ref_valid(self) -> None:
263
- self.saas_file.resource_templates[0].targets[0].parameters = {
264
- "IMAGE_TAG": "2637b6c"
265
- }
242
+ def test_validate_image_tag_not_equals_ref_valid(self):
243
+ self.saas_files[0]["resourceTemplates"][0]["targets"][0][
244
+ "parameters"
245
+ ] = '{"IMAGE_TAG": "2637b6c"}'
266
246
  saasherder = SaasHerder(
267
- [self.saas_file],
268
- secret_reader=MockSecretReader(),
247
+ self.saas_files,
269
248
  thread_pool_size=1,
249
+ gitlab=None,
270
250
  integration="",
271
251
  integration_version="",
272
- hash_length=7,
273
- repo_url="https://repo-url.com",
252
+ settings={},
274
253
  validate=True,
275
254
  )
276
255
 
277
256
  self.assertTrue(saasherder.valid)
278
257
 
279
- def test_validate_image_tag_not_equals_ref_invalid(self) -> None:
280
- self.saas_file.resource_templates[0].targets[
281
- 0
282
- ].ref = "2637b6c41bda7731b1bcaaf18b4a50d7c5e63e30"
283
- self.saas_file.resource_templates[0].targets[0].parameters = {
284
- "IMAGE_TAG": "2637b6c"
285
- }
258
+ def test_validate_image_tag_not_equals_ref_invalid(self):
259
+ self.saas_files[0]["resourceTemplates"][0]["targets"][0][
260
+ "ref"
261
+ ] = "2637b6c41bda7731b1bcaaf18b4a50d7c5e63e30"
262
+ self.saas_files[0]["resourceTemplates"][0]["targets"][0][
263
+ "parameters"
264
+ ] = '{"IMAGE_TAG": "2637b6c"}'
286
265
  saasherder = SaasHerder(
287
- [self.saas_file],
288
- secret_reader=MockSecretReader(),
266
+ self.saas_files,
289
267
  thread_pool_size=1,
268
+ gitlab=None,
290
269
  integration="",
291
270
  integration_version="",
292
- hash_length=7,
293
- repo_url="https://repo-url.com",
271
+ settings={},
294
272
  validate=True,
295
273
  )
296
274
 
297
275
  self.assertFalse(saasherder.valid)
298
276
 
299
- def test_validate_upstream_jobs_valid(self) -> None:
277
+ def test_validate_upstream_jobs_valid(self):
300
278
  saasherder = SaasHerder(
301
- [self.saas_file],
302
- secret_reader=MockSecretReader(),
279
+ self.saas_files,
303
280
  thread_pool_size=1,
281
+ gitlab=None,
304
282
  integration="",
305
283
  integration_version="",
306
- hash_length=7,
307
- repo_url="https://repo-url.com",
284
+ settings={},
308
285
  validate=True,
309
286
  )
310
- saasherder.validate_upstream_jobs(self.jjb) # type: ignore
287
+ saasherder.validate_upstream_jobs(self.jjb)
311
288
  self.assertTrue(saasherder.valid)
312
289
 
313
- def test_validate_upstream_jobs_invalid(self) -> None:
290
+ def test_validate_upstream_jobs_invalid(self):
314
291
  saasherder = SaasHerder(
315
- [self.saas_file],
316
- secret_reader=MockSecretReader(),
292
+ self.saas_files,
317
293
  thread_pool_size=1,
294
+ gitlab=None,
318
295
  integration="",
319
296
  integration_version="",
320
- hash_length=7,
321
- repo_url="https://repo-url.com",
297
+ settings={},
322
298
  validate=True,
323
299
  )
324
300
  jjb = MockJJB({"ci": []})
325
- saasherder.validate_upstream_jobs(jjb) # type: ignore
301
+ saasherder.validate_upstream_jobs(jjb)
326
302
  self.assertFalse(saasherder.valid)
327
303
 
328
- def test_check_saas_file_promotion_same_source(self) -> None:
329
- raw_rts = [
304
+ def test_check_saas_file_promotion_same_source(self):
305
+ rts = [
330
306
  {
331
307
  "name": "rt_publisher",
332
308
  "url": "repo_publisher",
333
- "path": "path",
334
309
  "targets": [
335
310
  {
336
311
  "namespace": {
337
312
  "name": "ns",
338
- "app": {"name": "app"},
339
- "environment": {
340
- "name": "env1",
341
- },
342
- "cluster": {
343
- "name": "appsres03ue1",
344
- "serverUrl": "https://url",
345
- "internal": True,
346
- },
313
+ "environment": {"name": "env1"},
314
+ "cluster": {"name": "cluster"},
347
315
  },
348
- "parameters": "{}",
316
+ "parameters": {},
349
317
  "ref": "0000000000000",
350
318
  "promotion": {
351
319
  "publish": ["channel-1"],
@@ -356,184 +324,222 @@ class TestSaasFileValid(TestCase):
356
324
  {
357
325
  "name": "rt_subscriber",
358
326
  "url": "this-repo-will-not-match-the-publisher",
359
- "path": "path",
360
327
  "targets": [
361
328
  {
362
329
  "namespace": {
363
330
  "name": "ns2",
364
- "app": {"name": "app"},
365
- "environment": {
366
- "name": "env1",
367
- },
368
- "cluster": {
369
- "name": "appsres03ue1",
370
- "serverUrl": "https://url",
371
- "internal": True,
372
- },
331
+ "environment": {"name": "env1"},
332
+ "cluster": {"name": "cluster"},
373
333
  },
374
- "parameters": "{}",
334
+ "parameters": {},
375
335
  "ref": "0000000000000",
376
336
  "promotion": {
377
- "auto": "True",
337
+ "auto": "true",
378
338
  "subscribe": ["channel-1"],
379
339
  },
380
340
  }
381
341
  ],
382
342
  },
383
343
  ]
384
- rts = [
385
- self.gql_class_factory( # type: ignore[attr-defined] # it's set in the fixture
386
- SaasResourceTemplateV2, rt
387
- )
388
- for rt in raw_rts
389
- ]
390
- self.saas_file.resource_templates = rts
344
+ self.saas_files[0]["resourceTemplates"] = rts
391
345
  saasherder = SaasHerder(
392
- [self.saas_file],
393
- secret_reader=MockSecretReader(),
346
+ self.saas_files,
394
347
  thread_pool_size=1,
348
+ gitlab=None,
395
349
  integration="",
396
350
  integration_version="",
397
- hash_length=7,
398
- repo_url="https://repo-url.com",
351
+ settings={},
399
352
  validate=True,
400
353
  )
401
354
  self.assertFalse(saasherder.valid)
402
355
 
403
356
 
404
- @pytest.mark.usefixtures("inject_gql_class_factory")
405
357
  class TestGetMovingCommitsDiffSaasFile(TestCase):
406
- def setUp(self) -> None:
407
- self.saas_file = self.gql_class_factory( # type: ignore[attr-defined] # it's set in the fixture
408
- SaasFileV2, Fixtures("saasherder").get_anymarkup("saas.gql.yml")
409
- )
410
-
358
+ def setUp(self):
359
+ self.saas_files = [
360
+ {
361
+ "path": "path1",
362
+ "name": "a1",
363
+ "managedResourceTypes": [],
364
+ "resourceTemplates": [
365
+ {
366
+ "name": "rt",
367
+ "url": "http://github.com/user/repo",
368
+ "targets": [
369
+ {
370
+ "namespace": {
371
+ "name": "ns",
372
+ "environment": {"name": "env1"},
373
+ "cluster": {"name": "cluster1"},
374
+ },
375
+ "parameters": {},
376
+ "ref": "main",
377
+ },
378
+ {
379
+ "namespace": {
380
+ "name": "ns",
381
+ "environment": {"name": "env2"},
382
+ "cluster": {"name": "cluster2"},
383
+ },
384
+ "parameters": {},
385
+ "ref": "secondary",
386
+ },
387
+ ],
388
+ }
389
+ ],
390
+ "roles": [{"users": [{"org_username": "myname"}]}],
391
+ }
392
+ ]
411
393
  self.initiate_gh_patcher = patch.object(
412
394
  SaasHerder, "_initiate_github", autospec=True
413
395
  )
396
+ self.get_pipelines_provider_patcher = patch.object(
397
+ SaasHerder, "_get_pipelines_provider"
398
+ )
414
399
  self.get_commit_sha_patcher = patch.object(
415
400
  SaasHerder, "_get_commit_sha", autospec=True
416
401
  )
417
402
  self.initiate_gh = self.initiate_gh_patcher.start()
403
+ self.get_pipelines_provider = self.get_pipelines_provider_patcher.start()
418
404
  self.get_commit_sha = self.get_commit_sha_patcher.start()
419
405
  self.maxDiff = None
420
406
 
421
- def tearDown(self) -> None:
407
+ def tearDown(self):
422
408
  for p in (
423
409
  self.initiate_gh_patcher,
410
+ self.get_pipelines_provider_patcher,
424
411
  self.get_commit_sha_patcher,
425
412
  ):
426
413
  p.stop()
427
414
 
428
- def test_get_moving_commits_diff_saas_file_all_fine(self) -> None:
415
+ def test_get_moving_commits_diff_saas_file_all_fine(self):
429
416
  saasherder = SaasHerder(
430
- [self.saas_file],
431
- secret_reader=MockSecretReader(),
417
+ self.saas_files,
432
418
  thread_pool_size=1,
419
+ gitlab=None,
433
420
  integration="",
434
421
  integration_version="",
435
- hash_length=7,
436
- repo_url="https://repo-url.com",
422
+ settings={},
423
+ validate=False,
437
424
  )
438
425
  saasherder.state = MagicMock()
439
426
  saasherder.state.get.return_value = "asha"
440
- self.get_commit_sha.side_effect = ("abcd4242",)
441
- # 2nd target is the one that will be promoted
427
+ self.get_commit_sha.side_effect = ("abcd4242", "4242efg")
428
+ self.get_pipelines_provider.return_value = "apipelineprovider"
442
429
  expected = [
443
430
  TriggerSpecMovingCommit(
444
- saas_file_name=self.saas_file.name,
445
- env_name="App-SRE",
431
+ saas_file_name=self.saas_files[0]["name"],
432
+ env_name="env1",
446
433
  timeout=None,
447
- pipelines_provider=self.saas_file.pipelines_provider,
448
- resource_template_name="test-saas-deployments",
449
- cluster_name="appsres03ue1",
450
- namespace_name="test-ns-subscriber",
434
+ ref="main",
451
435
  state_content="abcd4242",
452
- ref="1234567890123456789012345678901234567890",
453
- reason=None,
454
- )
436
+ cluster_name="cluster1",
437
+ pipelines_provider="apipelineprovider",
438
+ namespace_name="ns",
439
+ resource_template_name="rt",
440
+ ),
441
+ TriggerSpecMovingCommit(
442
+ saas_file_name=self.saas_files[0]["name"],
443
+ env_name="env2",
444
+ timeout=None,
445
+ ref="secondary",
446
+ state_content="4242efg",
447
+ cluster_name="cluster2",
448
+ pipelines_provider="apipelineprovider",
449
+ namespace_name="ns",
450
+ resource_template_name="rt",
451
+ ),
455
452
  ]
456
453
 
457
454
  self.assertEqual(
458
- saasherder.get_moving_commits_diff_saas_file(self.saas_file, True),
455
+ saasherder.get_moving_commits_diff_saas_file(self.saas_files[0], True),
459
456
  expected,
460
457
  )
461
458
 
462
- def test_get_moving_commits_diff_saas_file_all_fine_include_trigger_trace(
463
- self,
464
- ) -> None:
459
+ def test_get_moving_commits_diff_saas_file_all_fine_include_trigger_trace(self):
465
460
  saasherder = SaasHerder(
466
- [self.saas_file],
467
- secret_reader=MockSecretReader(),
461
+ self.saas_files,
468
462
  thread_pool_size=1,
463
+ gitlab=None,
469
464
  integration="",
470
465
  integration_version="",
471
- hash_length=7,
472
- repo_url="https://repo-url.com",
466
+ settings={},
467
+ validate=False,
473
468
  include_trigger_trace=True,
474
469
  )
475
-
476
470
  saasherder.state = MagicMock()
477
471
  saasherder.state.get.return_value = "asha"
478
472
  self.get_commit_sha.side_effect = ("abcd4242", "4242efg")
473
+ self.get_pipelines_provider.return_value = "apipelineprovider"
479
474
  expected = [
480
475
  TriggerSpecMovingCommit(
481
- saas_file_name=self.saas_file.name,
482
- env_name="App-SRE",
476
+ saas_file_name=self.saas_files[0]["name"],
477
+ env_name="env1",
483
478
  timeout=None,
484
- pipelines_provider=self.saas_file.pipelines_provider,
485
- resource_template_name="test-saas-deployments",
486
- cluster_name="appsres03ue1",
487
- namespace_name="test-ns-subscriber",
479
+ ref="main",
488
480
  state_content="abcd4242",
489
- ref="1234567890123456789012345678901234567890",
490
- reason="https://github.com/app-sre/test-saas-deployments/commit/abcd4242",
481
+ cluster_name="cluster1",
482
+ pipelines_provider="apipelineprovider",
483
+ namespace_name="ns",
484
+ resource_template_name="rt",
485
+ reason="http://github.com/user/repo/commit/abcd4242",
486
+ ),
487
+ TriggerSpecMovingCommit(
488
+ saas_file_name=self.saas_files[0]["name"],
489
+ env_name="env2",
490
+ timeout=None,
491
+ ref="secondary",
492
+ state_content="4242efg",
493
+ cluster_name="cluster2",
494
+ pipelines_provider="apipelineprovider",
495
+ namespace_name="ns",
496
+ resource_template_name="rt",
497
+ reason="http://github.com/user/repo/commit/4242efg",
491
498
  ),
492
499
  ]
493
500
 
494
501
  self.assertEqual(
495
- saasherder.get_moving_commits_diff_saas_file(self.saas_file, True),
502
+ saasherder.get_moving_commits_diff_saas_file(self.saas_files[0], True),
496
503
  expected,
497
504
  )
498
505
 
499
- def test_get_moving_commits_diff_saas_file_bad_sha1(self) -> None:
506
+ def test_get_moving_commits_diff_saas_file_bad_sha1(self):
500
507
  saasherder = SaasHerder(
501
- [self.saas_file],
502
- secret_reader=MockSecretReader(),
508
+ self.saas_files,
503
509
  thread_pool_size=1,
510
+ gitlab=None,
504
511
  integration="",
505
512
  integration_version="",
506
- hash_length=7,
507
- repo_url="https://repo-url.com",
513
+ settings={},
514
+ validate=False,
508
515
  )
509
516
  saasherder.state = MagicMock()
510
517
  saasherder.state.get.return_value = "asha"
518
+ self.get_pipelines_provider.return_value = "apipelineprovider"
511
519
  self.get_commit_sha.side_effect = GithubException(
512
520
  401, "somedata", {"aheader": "avalue"}
513
521
  )
514
522
  # At least we don't crash!
515
523
  self.assertEqual(
516
- saasherder.get_moving_commits_diff_saas_file(self.saas_file, True), []
524
+ saasherder.get_moving_commits_diff_saas_file(self.saas_files[0], True), []
517
525
  )
518
526
 
519
527
 
520
- @pytest.mark.usefixtures("inject_gql_class_factory")
521
528
  class TestPopulateDesiredState(TestCase):
522
- def setUp(self) -> None:
529
+ def setUp(self):
530
+ saas_files = []
523
531
  self.fxts = Fixtures("saasherder_populate_desired")
524
- raw_saas_file = self.fxts.get_anymarkup("saas_remote_openshift_template.yaml")
525
- del raw_saas_file["_placeholders"]
526
- saas_file = self.gql_class_factory( # type: ignore[attr-defined] # it's set in the fixture
527
- SaasFileV2, raw_saas_file
528
- )
532
+ for file in [self.fxts.get("saas_remote_openshift_template.yaml")]:
533
+ saas_files.append(yaml.safe_load(file))
534
+
535
+ self.assertEqual(1, len(saas_files))
529
536
  self.saasherder = SaasHerder(
530
- [saas_file],
531
- secret_reader=MockSecretReader(),
537
+ saas_files,
532
538
  thread_pool_size=1,
539
+ gitlab=None,
533
540
  integration="",
534
541
  integration_version="",
535
- hash_length=7,
536
- repo_url="https://repo-url.com",
542
+ settings={"hashLength": 7},
537
543
  )
538
544
 
539
545
  # Mock GitHub interactions.
@@ -560,15 +566,13 @@ class TestPopulateDesiredState(TestCase):
560
566
  )
561
567
  self.get_check_images_patcher.start()
562
568
 
563
- def fake_get_file_contents(
564
- self, url: str, path: str, ref: str, github: Github, hash_length: int
565
- ) -> tuple[Any, str, str]:
566
- self.assertEqual("https://github.com/rhobs/configuration", url)
569
+ def fake_get_file_contents(self, options):
570
+ self.assertEqual("https://github.com/rhobs/configuration", options["url"])
567
571
 
568
- content = self.fxts.get(ref + (path.replace("/", "_")))
569
- return yaml.safe_load(content), "yolo", ref
572
+ content = self.fxts.get(options["ref"] + (options["path"].replace("/", "_")))
573
+ return yaml.safe_load(content), "yolo", options["ref"]
570
574
 
571
- def tearDown(self) -> None:
575
+ def tearDown(self):
572
576
  for p in (
573
577
  self.initiate_gh_patcher,
574
578
  self.get_file_contents_patcher,
@@ -576,14 +580,13 @@ class TestPopulateDesiredState(TestCase):
576
580
  ):
577
581
  p.stop()
578
582
 
579
- # TODO: fix this test
580
- # def test_populate_desired_state_saas_file_delete(self) -> None:
581
- # spec = {"delete": True}
583
+ def test_populate_desired_state_saas_file_delete(self):
584
+ spec = {"delete": True}
582
585
 
583
- # desired_state = self.saasherder.populate_desired_state_saas_file(spec, None)
584
- # self.assertIsNone(desired_state)
586
+ desired_state = self.saasherder.populate_desired_state_saas_file(spec, None)
587
+ self.assertIsNone(desired_state)
585
588
 
586
- def test_populate_desired_state_cases(self) -> None:
589
+ def test_populate_desired_state_cases(self):
587
590
  ri = ResourceInventory()
588
591
  for resource_type in (
589
592
  "Deployment",
@@ -606,131 +609,175 @@ class TestPopulateDesiredState(TestCase):
606
609
  cnt += 1
607
610
 
608
611
  self.assertEqual(5, cnt, "expected 5 resources, found less")
609
- self.assertEqual(self.saasherder.promotions, [None, None, None, None])
610
612
 
611
613
 
612
- @pytest.mark.usefixtures("inject_gql_class_factory")
613
614
  class TestCollectRepoUrls(TestCase):
614
- def setUp(self) -> None:
615
- self.saas_file = self.gql_class_factory( # type: ignore[attr-defined] # it's set in the fixture
616
- SaasFileV2, Fixtures("saasherder").get_anymarkup("saas.gql.yml")
617
- )
615
+ def test_collect_repo_urls(self):
616
+ repo_url = "git-repo"
617
+ saas_files = [
618
+ {
619
+ "path": "path1",
620
+ "name": "name1",
621
+ "managedResourceTypes": [],
622
+ "resourceTemplates": [{"name": "name", "url": repo_url, "targets": []}],
623
+ }
624
+ ]
618
625
 
619
- def test_collect_repo_urls(self) -> None:
620
- repo_url = "https://github.com/app-sre/test-saas-deployments"
621
626
  saasherder = SaasHerder(
622
- [self.saas_file],
623
- secret_reader=MockSecretReader(),
627
+ saas_files,
624
628
  thread_pool_size=1,
629
+ gitlab=None,
625
630
  integration="",
626
631
  integration_version="",
627
- hash_length=7,
628
- repo_url="https://repo-url.com",
632
+ settings={},
629
633
  )
630
634
  self.assertEqual({repo_url}, saasherder.repo_urls)
631
635
 
632
636
 
633
- @pytest.mark.usefixtures("inject_gql_class_factory")
634
637
  class TestGetSaasFileAttribute(TestCase):
635
- def setUp(self) -> None:
636
- self.saas_file = self.gql_class_factory( # type: ignore[attr-defined] # it's set in the fixture
637
- SaasFileV2, Fixtures("saasherder").get_anymarkup("saas.gql.yml")
638
- )
638
+ def test_attribute_none(self):
639
+ saas_files = [
640
+ {
641
+ "path": "path1",
642
+ "name": "name1",
643
+ "managedResourceTypes": [],
644
+ "resourceTemplates": [],
645
+ }
646
+ ]
639
647
 
640
- def test_no_such_attribute(self) -> None:
641
648
  saasherder = SaasHerder(
642
- [self.saas_file],
643
- secret_reader=MockSecretReader(),
649
+ saas_files,
644
650
  thread_pool_size=1,
651
+ gitlab=None,
645
652
  integration="",
646
653
  integration_version="",
647
- hash_length=7,
648
- repo_url="https://repo-url.com",
654
+ settings={},
649
655
  )
650
656
  att = saasherder._get_saas_file_feature_enabled("no_such_attribute")
651
657
  self.assertEqual(att, None)
652
658
 
653
- def test_attribute_none(self) -> None:
654
- saasherder = SaasHerder(
655
- [self.saas_file],
656
- secret_reader=MockSecretReader(),
657
- thread_pool_size=1,
658
- integration="",
659
- integration_version="",
660
- hash_length=7,
661
- repo_url="https://repo-url.com",
662
- )
663
- att = saasherder._get_saas_file_feature_enabled("takeover")
664
- self.assertEqual(att, None)
659
+ def test_attribute_not_none(self):
660
+ saas_files = [
661
+ {
662
+ "path": "path1",
663
+ "name": "name1",
664
+ "managedResourceTypes": [],
665
+ "resourceTemplates": [],
666
+ "attrib": True,
667
+ }
668
+ ]
665
669
 
666
- def test_attribute_not_none(self) -> None:
667
670
  saasherder = SaasHerder(
668
- [self.saas_file],
669
- secret_reader=MockSecretReader(),
671
+ saas_files,
670
672
  thread_pool_size=1,
673
+ gitlab=None,
671
674
  integration="",
672
675
  integration_version="",
673
- hash_length=7,
674
- repo_url="https://repo-url.com",
676
+ settings={},
675
677
  )
676
- att = saasherder._get_saas_file_feature_enabled("publish_job_logs")
678
+ att = saasherder._get_saas_file_feature_enabled("attrib")
677
679
  self.assertEqual(att, True)
678
680
 
679
- def test_attribute_none_with_default(self) -> None:
681
+ def test_attribute_none_with_default(self):
682
+ saas_files = [
683
+ {
684
+ "path": "path1",
685
+ "name": "name1",
686
+ "managedResourceTypes": [],
687
+ "resourceTemplates": [],
688
+ }
689
+ ]
690
+
680
691
  saasherder = SaasHerder(
681
- [self.saas_file],
682
- secret_reader=MockSecretReader(),
692
+ saas_files,
683
693
  thread_pool_size=1,
694
+ gitlab=None,
684
695
  integration="",
685
696
  integration_version="",
686
- hash_length=7,
687
- repo_url="https://repo-url.com",
697
+ settings={},
688
698
  )
689
699
  att = saasherder._get_saas_file_feature_enabled("no_such_att", default=True)
690
700
  self.assertEqual(att, True)
691
701
 
692
- def test_attribute_not_none_with_default(self) -> None:
702
+ def test_attribute_not_none_with_default(self):
703
+ saas_files = [
704
+ {
705
+ "path": "path1",
706
+ "name": "name1",
707
+ "managedResourceTypes": [],
708
+ "resourceTemplates": [],
709
+ "attrib": True,
710
+ }
711
+ ]
712
+
693
713
  saasherder = SaasHerder(
694
- [self.saas_file],
695
- secret_reader=MockSecretReader(),
714
+ saas_files,
696
715
  thread_pool_size=1,
716
+ gitlab=None,
697
717
  integration="",
698
718
  integration_version="",
699
- hash_length=7,
700
- repo_url="https://repo-url.com",
701
- )
702
- att = saasherder._get_saas_file_feature_enabled(
703
- "publish_job_logs", default=False
719
+ settings={},
704
720
  )
721
+ att = saasherder._get_saas_file_feature_enabled("attrib", default=False)
705
722
  self.assertEqual(att, True)
706
723
 
707
- def test_attribute_multiple_saas_files_return_false(self) -> None:
724
+ def test_attribute_multiple_saas_files_return_false(self):
725
+ saas_files = [
726
+ {
727
+ "path": "path1",
728
+ "name": "name1",
729
+ "managedResourceTypes": [],
730
+ "resourceTemplates": [],
731
+ "attrib": True,
732
+ },
733
+ {
734
+ "path": "path2",
735
+ "name": "name2",
736
+ "managedResourceTypes": [],
737
+ "resourceTemplates": [],
738
+ },
739
+ ]
740
+
708
741
  saasherder = SaasHerder(
709
- [self.saas_file, self.saas_file],
710
- secret_reader=MockSecretReader(),
742
+ saas_files,
711
743
  thread_pool_size=1,
744
+ gitlab=None,
712
745
  integration="",
713
746
  integration_version="",
714
- hash_length=7,
715
- repo_url="https://repo-url.com",
747
+ settings={},
716
748
  )
717
- self.assertFalse(saasherder._get_saas_file_feature_enabled("publish_job_logs"))
749
+ self.assertFalse(saasherder._get_saas_file_feature_enabled("attrib"))
750
+
751
+ def test_attribute_multiple_saas_files_with_default_return_false(self):
752
+ saas_files = [
753
+ {
754
+ "path": "path1",
755
+ "name": "name1",
756
+ "managedResourceTypes": [],
757
+ "resourceTemplates": [],
758
+ "attrib": True,
759
+ },
760
+ {
761
+ "path": "path2",
762
+ "name": "name2",
763
+ "managedResourceTypes": [],
764
+ "resourceTemplates": [],
765
+ "attrib": True,
766
+ },
767
+ ]
718
768
 
719
- def test_attribute_multiple_saas_files_with_default_return_false(self) -> None:
720
769
  saasherder = SaasHerder(
721
- [self.saas_file, self.saas_file],
722
- secret_reader=MockSecretReader(),
770
+ saas_files,
723
771
  thread_pool_size=1,
772
+ gitlab=None,
724
773
  integration="",
725
774
  integration_version="",
726
- hash_length=7,
727
- repo_url="https://repo-url.com",
775
+ settings={},
728
776
  )
729
777
  att = saasherder._get_saas_file_feature_enabled("attrib", default=True)
730
778
  self.assertFalse(att)
731
779
 
732
780
 
733
- @pytest.mark.usefixtures("inject_gql_class_factory")
734
781
  class TestConfigHashPromotionsValidation(TestCase):
735
782
  """TestCase to test SaasHerder promotions validation. SaasHerder is
736
783
  initialized with ResourceInventory population. Like is done in
@@ -742,18 +789,17 @@ class TestConfigHashPromotionsValidation(TestCase):
742
789
  template: Any
743
790
 
744
791
  @classmethod
745
- def setUpClass(cls) -> None:
792
+ def setUpClass(cls):
746
793
  cls.fxt = Fixtures("saasherder")
747
794
  cls.cluster = "test-cluster"
748
795
  cls.template = cls.fxt.get_anymarkup("template_1.yml")
749
796
 
750
797
  def setUp(self) -> None:
751
- self.saas_file = self.gql_class_factory( # type: ignore[attr-defined] # it's set in the fixture
752
- SaasFileV2, Fixtures("saasherder").get_anymarkup("saas.gql.yml")
753
- )
754
- self.all_saas_files = [self.saas_file]
798
+ self.all_saas_files = [self.fxt.get_anymarkup("saas.gql.yml")]
755
799
 
756
- self.state_patcher = patch("reconcile.utils.state.State", autospec=True)
800
+ self.state_patcher = patch(
801
+ "reconcile.utils.saasherder.init_state", autospec=True
802
+ )
757
803
  self.state_mock = self.state_patcher.start().return_value
758
804
 
759
805
  self.ig_patcher = patch.object(SaasHerder, "_initiate_github", autospec=True)
@@ -764,6 +810,11 @@ class TestConfigHashPromotionsValidation(TestCase):
764
810
 
765
811
  self.gfc_patcher = patch.object(SaasHerder, "_get_file_contents", autospec=True)
766
812
  gfc_mock = self.gfc_patcher.start()
813
+
814
+ self.saas_file = self.fxt.get_anymarkup("saas.gql.yml")
815
+ # ApiVersion is set in the saas gql query method in queries module
816
+ self.saas_file["apiVersion"] = "v2"
817
+
767
818
  gfc_mock.return_value = (self.template, "url", "ahash")
768
819
 
769
820
  self.deploy_current_state_fxt = self.fxt.get_anymarkup("saas_deploy.state.json")
@@ -774,13 +825,12 @@ class TestConfigHashPromotionsValidation(TestCase):
774
825
 
775
826
  self.saasherder = SaasHerder(
776
827
  [self.saas_file],
777
- secret_reader=MockSecretReader(),
778
828
  thread_pool_size=1,
779
- state=self.state_mock,
829
+ gitlab=None,
780
830
  integration="",
781
831
  integration_version="",
782
- hash_length=24,
783
- repo_url="https://repo-url.com",
832
+ initialise_state=True,
833
+ settings={"hashLength": 24},
784
834
  )
785
835
 
786
836
  # IMPORTANT: Populating desired state modify self.saas_files within
@@ -794,42 +844,55 @@ class TestConfigHashPromotionsValidation(TestCase):
794
844
  if self.ri.has_error_registered():
795
845
  raise Exception("Errors registered in Resourceinventory")
796
846
 
797
- def tearDown(self) -> None:
847
+ def tearDown(self):
798
848
  self.state_patcher.stop()
799
849
  self.ig_patcher.stop()
800
850
  self.gfc_patcher.stop()
801
851
 
802
- def test_promotion_state_config_hash_match_validates(self) -> None:
852
+ def test_config_hash_is_filled(self) -> None:
853
+ """Ensures the get_config_diff_saas_file fills the promotion data
854
+ on the publisher target. This data is used in publish_promotions
855
+ method to add the hash to subscribed targets.
856
+ IMPORTANT: This is not the promotion_data within promotion. This
857
+ fields are set by _process_template method in saasherder
858
+ """
859
+ trigger_spec: TriggerSpecConfig = self.saasherder.get_configs_diff_saas_file(
860
+ self.saas_file
861
+ )[0]
862
+ promotion = trigger_spec.state_content["promotion"]
863
+ self.assertIsNotNone(promotion[TARGET_CONFIG_HASH])
864
+
865
+ def test_promotion_state_config_hash_match_validates(self):
803
866
  """A promotion is valid if the parent target config_hash set in
804
867
  the state is equal to the one set in the subscriber target
805
868
  promotion data. This is the happy path.
806
869
  """
807
870
  publisher_state = {
808
871
  "success": True,
809
- "saas_file": self.saas_file.name,
810
- "target_config_hash": "ed2af38cf21f268c",
872
+ "saas_file": self.saas_file["name"],
873
+ TARGET_CONFIG_HASH: "ed2af38cf21f268c",
811
874
  }
812
875
  self.state_mock.get.return_value = publisher_state
813
876
  result = self.saasherder.validate_promotions()
814
877
  self.assertTrue(result)
815
878
 
816
- def test_promotion_state_config_hash_not_match_no_validates(self) -> None:
879
+ def test_promotion_state_config_hash_not_match_no_validates(self):
817
880
  """Promotion is not valid if the parent target config hash set in
818
- the state does not match with the one set in the subscriber target
881
+ the state does not match with the one set in the subsriber target
819
882
  promotion_data. This could happen if the parent target has run again
820
883
  with the same ref before before the subscriber target promotion MR is
821
884
  merged.
822
885
  """
823
886
  publisher_state = {
824
887
  "success": True,
825
- "saas_file": self.saas_file.name,
826
- "target_config_hash": "will_not_match",
888
+ "saas_file": self.saas_file["name"],
889
+ TARGET_CONFIG_HASH: "will_not_match",
827
890
  }
828
891
  self.state_mock.get.return_value = publisher_state
829
892
  result = self.saasherder.validate_promotions()
830
893
  self.assertFalse(result)
831
894
 
832
- def test_promotion_without_state_config_hash_validates(self) -> None:
895
+ def test_promotion_without_state_config_hash_validates(self):
833
896
  """Existent states won't have promotion data. If there is an ongoing
834
897
  promotion, this ensures it will happen.
835
898
  """
@@ -840,28 +903,25 @@ class TestConfigHashPromotionsValidation(TestCase):
840
903
  result = self.saasherder.validate_promotions()
841
904
  self.assertTrue(result)
842
905
 
843
- def test_promotion_without_promotion_data_validates(self) -> None:
906
+ def test_promotion_without_promotion_data_validates(self):
844
907
  """A manual promotion might be required, subsribed targets without
845
908
  promotion_data should validate if the parent target job has succed
846
909
  with the same ref.
847
910
  """
848
911
  publisher_state = {
849
912
  "success": True,
850
- "saas_file": self.saas_file.name,
851
- "target_config_hash": "whatever",
913
+ "saas_file": self.saas_file["name"],
914
+ TARGET_CONFIG_HASH: "whatever",
852
915
  }
853
916
 
854
- self.assertEqual(len(self.saasherder.promotions), 2)
855
- self.assertIsNotNone(self.saasherder.promotions[1])
856
917
  # Remove promotion_data on the promoted target
857
- self.saasherder.promotions[1].promotion_data = None # type: ignore
918
+ self.saasherder.promotions[1]["promotion_data"] = None
858
919
 
859
920
  self.state_mock.get.return_value = publisher_state
860
921
  result = self.saasherder.validate_promotions()
861
922
  self.assertTrue(result)
862
923
 
863
924
 
864
- @pytest.mark.usefixtures("inject_gql_class_factory")
865
925
  class TestConfigHashTrigger(TestCase):
866
926
  """TestCase to test Openshift SAAS deploy configs trigger. SaasHerder is
867
927
  initialized WITHOUT ResourceInventory population. Like is done in the
@@ -873,19 +933,22 @@ class TestConfigHashTrigger(TestCase):
873
933
  template: Any
874
934
 
875
935
  @classmethod
876
- def setUpClass(cls) -> None:
936
+ def setUpClass(cls):
877
937
  cls.fxt = Fixtures("saasherder")
878
938
  cls.cluster = "test-cluster"
879
939
 
880
940
  def setUp(self) -> None:
881
- self.saas_file = self.gql_class_factory( # type: ignore[attr-defined] # it's set in the fixture
882
- SaasFileV2, Fixtures("saasherder").get_anymarkup("saas.gql.yml")
883
- )
884
- self.all_saas_files = [self.saas_file]
941
+ self.all_saas_files = [self.fxt.get_anymarkup("saas.gql.yml")]
885
942
 
886
- self.state_patcher = patch("reconcile.utils.state.State", autospec=True)
943
+ self.state_patcher = patch(
944
+ "reconcile.utils.saasherder.init_state", autospec=True
945
+ )
887
946
  self.state_mock = self.state_patcher.start().return_value
888
947
 
948
+ self.saas_file = self.fxt.get_anymarkup("saas.gql.yml")
949
+ # ApiVersion is set in the saas gql query method in queries module
950
+ self.saas_file["apiVersion"] = "v2"
951
+
889
952
  self.deploy_current_state_fxt = self.fxt.get_anymarkup("saas_deploy.state.json")
890
953
 
891
954
  self.post_deploy_current_state_fxt = self.fxt.get_anymarkup(
@@ -899,48 +962,50 @@ class TestConfigHashTrigger(TestCase):
899
962
 
900
963
  self.saasherder = SaasHerder(
901
964
  [self.saas_file],
902
- secret_reader=MockSecretReader(),
903
965
  thread_pool_size=1,
904
- state=self.state_mock,
966
+ gitlab=None,
905
967
  integration="",
906
968
  integration_version="",
907
- hash_length=24,
908
- repo_url="https://repo-url.com",
969
+ initialise_state=True,
970
+ settings={"hashLength": 24},
909
971
  )
910
972
 
911
- def tearDown(self) -> None:
973
+ def tearDown(self):
912
974
  self.state_patcher.stop()
913
975
 
914
- def test_same_configs_do_not_trigger(self) -> None:
976
+ def test_same_configs_do_not_trigger(self):
915
977
  """Ensures that if the same config is found, no job is triggered
916
978
  current Config is fetched from the state
917
979
  """
918
980
  trigger_specs = self.saasherder.get_configs_diff_saas_file(self.saas_file)
919
981
  self.assertListEqual(trigger_specs, [])
920
982
 
921
- def test_config_hash_change_do_trigger(self) -> None:
983
+ def test_config_hash_change_do_trigger(self):
922
984
  """Ensures a new job is triggered if the parent config hash changes"""
923
- self.saasherder.saas_files[0].resource_templates[0].targets[ # type: ignore
924
- 1
925
- ].promotion.promotion_data[0].data[0].target_config_hash = "Changed"
985
+ configs = self.saasherder.get_saas_targets_config_trigger_specs(self.saas_file)
986
+
987
+ desired_tc = list(configs.values())[1].state_content
988
+ desired_promo_data = desired_tc["promotion"]["promotion_data"]
989
+ desired_promo_data[0]["data"][0][TARGET_CONFIG_HASH] = "Changed"
990
+
926
991
  trigger_specs = self.saasherder.get_configs_diff_saas_file(self.saas_file)
927
992
  self.assertEqual(len(trigger_specs), 1)
928
993
 
929
- def test_non_existent_config_triggers(self) -> None:
994
+ def test_non_existent_config_triggers(self):
930
995
  self.state_mock.get.side_effect = [self.deploy_current_state_fxt, None]
931
996
  trigger_specs = self.saasherder.get_configs_diff_saas_file(self.saas_file)
932
997
  self.assertEqual(len(trigger_specs), 1)
933
998
 
934
999
 
935
1000
  class TestRemoveNoneAttributes(TestCase):
936
- def testSimpleDict(self) -> None:
1001
+ def testSimpleDict(self):
937
1002
  input = {"a": 1, "b": {}, "d": None, "e": {"aa": "aa", "bb": None}}
938
1003
  expected = {"a": 1, "b": {}, "e": {"aa": "aa"}}
939
1004
  res = SaasHerder.remove_none_values(input)
940
1005
  self.assertEqual(res, expected)
941
1006
 
942
- def testNoneValue(self) -> None:
1007
+ def testNoneValue(self):
943
1008
  input = None
944
- expected: dict[Any, Any] = {}
1009
+ expected = {}
945
1010
  res = SaasHerder.remove_none_values(input)
946
1011
  self.assertEqual(res, expected)