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.
- {qontract_reconcile-0.9.1rc162.dist-info → qontract_reconcile-0.9.1rc164.dist-info}/METADATA +2 -2
- {qontract_reconcile-0.9.1rc162.dist-info → qontract_reconcile-0.9.1rc164.dist-info}/RECORD +21 -30
- reconcile/glitchtip_project_dsn/integration.py +3 -0
- reconcile/jenkins_job_builder.py +2 -5
- reconcile/openshift_base.py +11 -11
- reconcile/openshift_saas_deploy.py +52 -57
- reconcile/openshift_saas_deploy_trigger_base.py +48 -55
- reconcile/openshift_saas_deploy_trigger_cleaner.py +2 -2
- reconcile/openshift_tekton_resources.py +1 -1
- reconcile/saas_file_validator.py +10 -23
- reconcile/slack_base.py +2 -5
- reconcile/test/conftest.py +0 -11
- reconcile/test/test_auto_promoter.py +42 -199
- reconcile/test/test_saasherder.py +463 -398
- reconcile/test/test_saasherder_allowed_secret_paths.py +36 -87
- reconcile/utils/mr/auto_promoter.py +50 -58
- reconcile/utils/mr/base.py +2 -6
- reconcile/utils/{saasherder/saasherder.py → saasherder.py} +736 -656
- reconcile/gql_definitions/common/app_code_component_repos.py +0 -68
- reconcile/gql_definitions/common/saas_files.py +0 -542
- reconcile/gql_definitions/common/saasherder_settings.py +0 -62
- reconcile/gql_definitions/fragments/oc_connection_cluster.py +0 -47
- reconcile/typed_queries/repos.py +0 -17
- reconcile/typed_queries/saas_files.py +0 -61
- reconcile/utils/saasherder/__init__.py +0 -17
- reconcile/utils/saasherder/interfaces.py +0 -404
- reconcile/utils/saasherder/models.py +0 -203
- {qontract_reconcile-0.9.1rc162.dist-info → qontract_reconcile-0.9.1rc164.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.9.1rc162.dist-info → qontract_reconcile-0.9.1rc164.dist-info}/entry_points.txt +0 -0
- {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
|
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
|
33
|
-
|
34
|
-
|
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
|
24
|
+
def __init__(self, data):
|
41
25
|
self.jobs = data
|
42
26
|
|
43
|
-
def get_all_jobs(self, job_types
|
27
|
+
def get_all_jobs(self, job_types):
|
44
28
|
return self.jobs
|
45
29
|
|
46
30
|
@staticmethod
|
47
|
-
def get_repo_url(job
|
31
|
+
def get_repo_url(job):
|
48
32
|
return JJB.get_repo_url(job)
|
49
33
|
|
50
34
|
@staticmethod
|
51
|
-
def get_ref(job
|
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)
|
89
|
-
self.
|
90
|
-
|
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)
|
121
|
+
def test_check_saas_file_env_combo_unique(self):
|
121
122
|
saasherder = SaasHerder(
|
122
|
-
|
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
|
-
|
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)
|
134
|
-
self.
|
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
|
-
|
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
|
-
|
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)
|
149
|
-
self.
|
150
|
-
|
151
|
-
|
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
|
-
|
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
|
-
|
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)
|
171
|
-
self.
|
172
|
-
self.
|
173
|
-
|
174
|
-
|
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
|
-
|
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
|
-
|
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)
|
183
|
+
def test_check_saas_file_upstream_not_used_with_commit_sha(self):
|
191
184
|
saasherder = SaasHerder(
|
192
|
-
|
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
|
-
|
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)
|
205
|
-
self.
|
206
|
-
|
207
|
-
]
|
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
|
-
|
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
|
-
|
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)
|
222
|
-
self.
|
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
|
-
|
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
|
-
|
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)
|
241
|
-
self.
|
242
|
-
|
243
|
-
]
|
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
|
-
|
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
|
-
|
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)
|
263
|
-
self.
|
264
|
-
"
|
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
|
-
|
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
|
-
|
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)
|
280
|
-
self.
|
281
|
-
|
282
|
-
]
|
283
|
-
self.
|
284
|
-
"
|
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
|
-
|
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
|
-
|
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)
|
277
|
+
def test_validate_upstream_jobs_valid(self):
|
300
278
|
saasherder = SaasHerder(
|
301
|
-
|
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
|
-
|
307
|
-
repo_url="https://repo-url.com",
|
284
|
+
settings={},
|
308
285
|
validate=True,
|
309
286
|
)
|
310
|
-
saasherder.validate_upstream_jobs(self.jjb)
|
287
|
+
saasherder.validate_upstream_jobs(self.jjb)
|
311
288
|
self.assertTrue(saasherder.valid)
|
312
289
|
|
313
|
-
def test_validate_upstream_jobs_invalid(self)
|
290
|
+
def test_validate_upstream_jobs_invalid(self):
|
314
291
|
saasherder = SaasHerder(
|
315
|
-
|
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
|
-
|
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)
|
301
|
+
saasherder.validate_upstream_jobs(jjb)
|
326
302
|
self.assertFalse(saasherder.valid)
|
327
303
|
|
328
|
-
def test_check_saas_file_promotion_same_source(self)
|
329
|
-
|
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
|
-
"
|
339
|
-
"
|
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
|
-
"
|
365
|
-
"
|
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": "
|
337
|
+
"auto": "true",
|
378
338
|
"subscribe": ["channel-1"],
|
379
339
|
},
|
380
340
|
}
|
381
341
|
],
|
382
342
|
},
|
383
343
|
]
|
384
|
-
|
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
|
-
|
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
|
-
|
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)
|
407
|
-
self.
|
408
|
-
|
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)
|
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)
|
415
|
+
def test_get_moving_commits_diff_saas_file_all_fine(self):
|
429
416
|
saasherder = SaasHerder(
|
430
|
-
|
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
|
-
|
436
|
-
|
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
|
-
|
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.
|
445
|
-
env_name="
|
431
|
+
saas_file_name=self.saas_files[0]["name"],
|
432
|
+
env_name="env1",
|
446
433
|
timeout=None,
|
447
|
-
|
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
|
-
|
453
|
-
|
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.
|
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
|
-
|
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
|
-
|
472
|
-
|
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.
|
482
|
-
env_name="
|
476
|
+
saas_file_name=self.saas_files[0]["name"],
|
477
|
+
env_name="env1",
|
483
478
|
timeout=None,
|
484
|
-
|
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
|
-
|
490
|
-
|
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.
|
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)
|
506
|
+
def test_get_moving_commits_diff_saas_file_bad_sha1(self):
|
500
507
|
saasherder = SaasHerder(
|
501
|
-
|
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
|
-
|
507
|
-
|
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.
|
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)
|
529
|
+
def setUp(self):
|
530
|
+
saas_files = []
|
523
531
|
self.fxts = Fixtures("saasherder_populate_desired")
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
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
|
-
|
531
|
-
secret_reader=MockSecretReader(),
|
537
|
+
saas_files,
|
532
538
|
thread_pool_size=1,
|
539
|
+
gitlab=None,
|
533
540
|
integration="",
|
534
541
|
integration_version="",
|
535
|
-
|
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
|
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)
|
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
|
-
|
580
|
-
|
581
|
-
# spec = {"delete": True}
|
583
|
+
def test_populate_desired_state_saas_file_delete(self):
|
584
|
+
spec = {"delete": True}
|
582
585
|
|
583
|
-
|
584
|
-
|
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)
|
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
|
615
|
-
|
616
|
-
|
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
|
-
|
623
|
-
secret_reader=MockSecretReader(),
|
627
|
+
saas_files,
|
624
628
|
thread_pool_size=1,
|
629
|
+
gitlab=None,
|
625
630
|
integration="",
|
626
631
|
integration_version="",
|
627
|
-
|
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
|
636
|
-
|
637
|
-
|
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
|
-
|
643
|
-
secret_reader=MockSecretReader(),
|
649
|
+
saas_files,
|
644
650
|
thread_pool_size=1,
|
651
|
+
gitlab=None,
|
645
652
|
integration="",
|
646
653
|
integration_version="",
|
647
|
-
|
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
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
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
|
-
|
669
|
-
secret_reader=MockSecretReader(),
|
671
|
+
saas_files,
|
670
672
|
thread_pool_size=1,
|
673
|
+
gitlab=None,
|
671
674
|
integration="",
|
672
675
|
integration_version="",
|
673
|
-
|
674
|
-
repo_url="https://repo-url.com",
|
676
|
+
settings={},
|
675
677
|
)
|
676
|
-
att = saasherder._get_saas_file_feature_enabled("
|
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)
|
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
|
-
|
682
|
-
secret_reader=MockSecretReader(),
|
692
|
+
saas_files,
|
683
693
|
thread_pool_size=1,
|
694
|
+
gitlab=None,
|
684
695
|
integration="",
|
685
696
|
integration_version="",
|
686
|
-
|
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)
|
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
|
-
|
695
|
-
secret_reader=MockSecretReader(),
|
714
|
+
saas_files,
|
696
715
|
thread_pool_size=1,
|
716
|
+
gitlab=None,
|
697
717
|
integration="",
|
698
718
|
integration_version="",
|
699
|
-
|
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)
|
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
|
-
|
710
|
-
secret_reader=MockSecretReader(),
|
742
|
+
saas_files,
|
711
743
|
thread_pool_size=1,
|
744
|
+
gitlab=None,
|
712
745
|
integration="",
|
713
746
|
integration_version="",
|
714
|
-
|
715
|
-
repo_url="https://repo-url.com",
|
747
|
+
settings={},
|
716
748
|
)
|
717
|
-
self.assertFalse(saasherder._get_saas_file_feature_enabled("
|
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
|
-
|
722
|
-
secret_reader=MockSecretReader(),
|
770
|
+
saas_files,
|
723
771
|
thread_pool_size=1,
|
772
|
+
gitlab=None,
|
724
773
|
integration="",
|
725
774
|
integration_version="",
|
726
|
-
|
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)
|
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.
|
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(
|
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
|
-
|
829
|
+
gitlab=None,
|
780
830
|
integration="",
|
781
831
|
integration_version="",
|
782
|
-
|
783
|
-
|
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)
|
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
|
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
|
810
|
-
|
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)
|
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
|
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
|
826
|
-
|
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)
|
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)
|
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
|
851
|
-
|
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]
|
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)
|
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.
|
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(
|
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
|
-
|
966
|
+
gitlab=None,
|
905
967
|
integration="",
|
906
968
|
integration_version="",
|
907
|
-
|
908
|
-
|
969
|
+
initialise_state=True,
|
970
|
+
settings={"hashLength": 24},
|
909
971
|
)
|
910
972
|
|
911
|
-
def tearDown(self)
|
973
|
+
def tearDown(self):
|
912
974
|
self.state_patcher.stop()
|
913
975
|
|
914
|
-
def test_same_configs_do_not_trigger(self)
|
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)
|
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.
|
924
|
-
|
925
|
-
|
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)
|
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)
|
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)
|
1007
|
+
def testNoneValue(self):
|
943
1008
|
input = None
|
944
|
-
expected
|
1009
|
+
expected = {}
|
945
1010
|
res = SaasHerder.remove_none_values(input)
|
946
1011
|
self.assertEqual(res, expected)
|