qontract-reconcile 0.10.1rc428__py3-none-any.whl → 0.10.1rc429__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qontract_reconcile-0.10.1rc428.dist-info → qontract_reconcile-0.10.1rc429.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc428.dist-info → qontract_reconcile-0.10.1rc429.dist-info}/RECORD +7 -7
- reconcile/database_access_manager.py +39 -20
- reconcile/test/test_database_access_manager.py +45 -6
- {qontract_reconcile-0.10.1rc428.dist-info → qontract_reconcile-0.10.1rc429.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc428.dist-info → qontract_reconcile-0.10.1rc429.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc428.dist-info → qontract_reconcile-0.10.1rc429.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc428.dist-info → qontract_reconcile-0.10.1rc429.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.
|
3
|
+
Version: 0.10.1rc429
|
4
4
|
Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
|
5
5
|
Home-page: https://github.com/app-sre/qontract-reconcile
|
6
6
|
Author: Red Hat App-SRE Team
|
{qontract_reconcile-0.10.1rc428.dist-info → qontract_reconcile-0.10.1rc429.dist-info}/RECORD
RENAMED
@@ -16,7 +16,7 @@ reconcile/dashdotdb_cso.py,sha256=FoXrWGpOwXG5jf0eklN84tjJVUAYzKat7rtq_28JMlQ,36
|
|
16
16
|
reconcile/dashdotdb_dora.py,sha256=FINH-8dU3_r8EgUOMiF_fbxD9fKs6LFDxe6rufQ9XcM,17214
|
17
17
|
reconcile/dashdotdb_dvo.py,sha256=YXqpI6fBQAql-ybGI0grj9gWMzmKiAvPE__pNju6obk,8996
|
18
18
|
reconcile/dashdotdb_slo.py,sha256=bf1WSh5JP9obHVQsMy0OO71_VTYZgwAopElFZM6DmRo,6714
|
19
|
-
reconcile/database_access_manager.py,sha256=
|
19
|
+
reconcile/database_access_manager.py,sha256=pbf3n-8f2sxitMbj9Y2g0G_U7yfHiJaNX4lverxPnX8,21758
|
20
20
|
reconcile/dynatrace_token_provider.py,sha256=HWItJ_LavPcUJlpYz5fmfnfOpP2-0Qjkar0EAzBJ5Cw,16602
|
21
21
|
reconcile/email_sender.py,sha256=-5L-Ag_jaEYSzYRoMr52KQBRXz1E8yx9GqLbg2X4XFU,3533
|
22
22
|
reconcile/gabi_authorized_users.py,sha256=rCosZv8Iu9jhWG88YiwK-gftX475aJ1R-PYIJYp_svY,4342
|
@@ -368,7 +368,7 @@ reconcile/test/test_checkpoint.py,sha256=sbDtqTbfw5yMZ_mCltMXxkyyGueVLGUjTDtcWhP
|
|
368
368
|
reconcile/test/test_cli.py,sha256=qx_iBwh4Z-YkK3sbjK1wEziPTgn060EN-baf9DNvR3k,1096
|
369
369
|
reconcile/test/test_closedbox_endpoint_monitoring.py,sha256=isMHYwRWMFARU2nbJgbl69kD6H0eA86noCM4MPVI1fo,7151
|
370
370
|
reconcile/test/test_dashdotdb_dora.py,sha256=XDMdnLDvup8sSqQEynxdPhXQZAafYbd2IUo9flSRJ8I,7917
|
371
|
-
reconcile/test/test_database_access_manager.py,sha256=
|
371
|
+
reconcile/test/test_database_access_manager.py,sha256=gevaMDgOrpnrzYy7JrcJsYf1ZnyvBA2RB5G96JxJYn4,13278
|
372
372
|
reconcile/test/test_gabi_authorized_users.py,sha256=6XnV5Q9inxP81ktGMVKyWucjBTUj8Imy2L0HG3YHyUE,2496
|
373
373
|
reconcile/test/test_github_org.py,sha256=j3KeB4OnSln1gm2hidce49xdMru-j75NS3cM-AEgzZc,4511
|
374
374
|
reconcile/test/test_github_repo_invites.py,sha256=QJ0VFk5B59rx4XtHoT6XOGWw9xRIZMen_cgtviN_Vi8,3419
|
@@ -637,8 +637,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=dmEcNwZltP1rd_4DbxIYakO
|
|
637
637
|
tools/test/test_qontract_cli.py,sha256=awwTHEc2DWlykuqGIYM0WOBoSL0KRnOraCLk3C7izis,1401
|
638
638
|
tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
|
639
639
|
tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
|
640
|
-
qontract_reconcile-0.10.
|
641
|
-
qontract_reconcile-0.10.
|
642
|
-
qontract_reconcile-0.10.
|
643
|
-
qontract_reconcile-0.10.
|
644
|
-
qontract_reconcile-0.10.
|
640
|
+
qontract_reconcile-0.10.1rc429.dist-info/METADATA,sha256=IlUDMzAOQmNRBNLh7JrCttTiTIiQiuy-cCb8gLp4gNk,2347
|
641
|
+
qontract_reconcile-0.10.1rc429.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
|
642
|
+
qontract_reconcile-0.10.1rc429.dist-info/entry_points.txt,sha256=rTjAv28I_CHLM8ID3OPqMI_suoQ9s7tFbim4aYjn9kk,376
|
643
|
+
qontract_reconcile-0.10.1rc429.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
644
|
+
qontract_reconcile-0.10.1rc429.dist-info/RECORD,,
|
@@ -9,6 +9,7 @@ from typing import (
|
|
9
9
|
Any,
|
10
10
|
Callable,
|
11
11
|
Optional,
|
12
|
+
TypedDict,
|
12
13
|
)
|
13
14
|
|
14
15
|
from pydantic import BaseModel
|
@@ -67,6 +68,7 @@ class DatabaseConnectionParameters(BaseModel):
|
|
67
68
|
class PSQLScriptGenerator(BaseModel):
|
68
69
|
db_access: DatabaseAccessV1
|
69
70
|
connection_parameter: DatabaseConnectionParameters
|
71
|
+
admin_connection_parameter: DatabaseConnectionParameters
|
70
72
|
engine: str
|
71
73
|
|
72
74
|
def _get_db(self) -> str:
|
@@ -92,7 +94,7 @@ select 'CREATE ROLE "{self._get_user()}" WITH LOGIN PASSWORD ''{self.connection
|
|
92
94
|
WHERE NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '{self._get_db()}');\\gexec
|
93
95
|
|
94
96
|
-- rds specific, grant role to admin or create schema fails
|
95
|
-
|
97
|
+
GRANT "{self._get_user()}" to "{self.admin_connection_parameter.user}";
|
96
98
|
CREATE SCHEMA IF NOT EXISTS "{self._get_user()}" AUTHORIZATION "{self._get_user()}";"""
|
97
99
|
|
98
100
|
def _generate_db_access(self) -> str:
|
@@ -357,7 +359,8 @@ def _populate_resources(
|
|
357
359
|
admin_secret_name: str,
|
358
360
|
resource_prefix: str,
|
359
361
|
settings: dict[Any, Any],
|
360
|
-
|
362
|
+
user_connection: DatabaseConnectionParameters,
|
363
|
+
admin_connection: DatabaseConnectionParameters,
|
361
364
|
) -> list[DBAMResource]:
|
362
365
|
managed_resources: list[DBAMResource] = []
|
363
366
|
# create service account
|
@@ -371,7 +374,8 @@ def _populate_resources(
|
|
371
374
|
# create script secret
|
372
375
|
generator = PSQLScriptGenerator(
|
373
376
|
db_access=db_access,
|
374
|
-
connection_parameter=
|
377
|
+
connection_parameter=user_connection,
|
378
|
+
admin_connection_parameter=admin_connection,
|
375
379
|
engine=engine,
|
376
380
|
)
|
377
381
|
script_secret_name = f"{resource_prefix}-script"
|
@@ -387,7 +391,7 @@ def _populate_resources(
|
|
387
391
|
# create user secret
|
388
392
|
managed_resources.append(
|
389
393
|
DBAMResource(
|
390
|
-
resource=generate_user_secret_spec(resource_prefix,
|
394
|
+
resource=generate_user_secret_spec(resource_prefix, user_connection),
|
391
395
|
clean_up=False,
|
392
396
|
)
|
393
397
|
)
|
@@ -433,13 +437,18 @@ def _generate_password() -> str:
|
|
433
437
|
return "".join(choices(ascii_letters + digits, k=32))
|
434
438
|
|
435
439
|
|
440
|
+
class _DBDonnections(TypedDict):
|
441
|
+
user: DatabaseConnectionParameters
|
442
|
+
admin: DatabaseConnectionParameters
|
443
|
+
|
444
|
+
|
436
445
|
def _create_database_connection_parameter(
|
437
446
|
db_access: DatabaseAccessV1,
|
438
447
|
namespace_name: str,
|
439
448
|
oc: OCClient,
|
440
449
|
admin_secret_name: str,
|
441
450
|
user_secret_name: str,
|
442
|
-
) ->
|
451
|
+
) -> _DBDonnections:
|
443
452
|
def _decode_secret_value(value: str) -> str:
|
444
453
|
return base64.b64decode(value).decode("utf-8")
|
445
454
|
|
@@ -449,6 +458,13 @@ def _create_database_connection_parameter(
|
|
449
458
|
user_secret_name,
|
450
459
|
allow_not_found=True,
|
451
460
|
)
|
461
|
+
admin_secret = oc.get(
|
462
|
+
namespace_name,
|
463
|
+
"Secret",
|
464
|
+
admin_secret_name,
|
465
|
+
allow_not_found=False,
|
466
|
+
)
|
467
|
+
|
452
468
|
if user_secret:
|
453
469
|
password = _decode_secret_value(user_secret["data"]["db.password"])
|
454
470
|
host = _decode_secret_value(user_secret["data"]["db.host"])
|
@@ -456,25 +472,27 @@ def _create_database_connection_parameter(
|
|
456
472
|
port = _decode_secret_value(user_secret["data"]["db.port"])
|
457
473
|
database = _decode_secret_value(user_secret["data"]["db.name"])
|
458
474
|
else:
|
459
|
-
admin_secret = oc.get(
|
460
|
-
namespace_name,
|
461
|
-
"Secret",
|
462
|
-
admin_secret_name,
|
463
|
-
allow_not_found=False,
|
464
|
-
)
|
465
475
|
host = _decode_secret_value(admin_secret["data"]["db.host"])
|
466
476
|
port = _decode_secret_value(admin_secret["data"]["db.port"])
|
467
477
|
user = db_access.username
|
468
478
|
password = _generate_password()
|
469
479
|
database = db_access.database
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
480
|
+
return _DBDonnections(
|
481
|
+
user=DatabaseConnectionParameters(
|
482
|
+
host=host,
|
483
|
+
port=port,
|
484
|
+
user=user,
|
485
|
+
password=password,
|
486
|
+
database=database,
|
487
|
+
),
|
488
|
+
admin=DatabaseConnectionParameters(
|
489
|
+
host=_decode_secret_value(admin_secret["data"]["db.host"]),
|
490
|
+
port=_decode_secret_value(admin_secret["data"]["db.port"]),
|
491
|
+
user=_decode_secret_value(admin_secret["data"]["db.user"]),
|
492
|
+
password=_decode_secret_value(admin_secret["data"]["db.password"]),
|
493
|
+
database=_decode_secret_value(admin_secret["data"]["db.name"]),
|
494
|
+
),
|
476
495
|
)
|
477
|
-
return database_connection
|
478
496
|
|
479
497
|
|
480
498
|
class JobFailedError(Exception):
|
@@ -506,7 +524,7 @@ def _process_db_access(
|
|
506
524
|
) as oc_map:
|
507
525
|
oc = oc_map.get_cluster(cluster_name, False)
|
508
526
|
|
509
|
-
|
527
|
+
connections = _create_database_connection_parameter(
|
510
528
|
db_access,
|
511
529
|
namespace_name,
|
512
530
|
oc,
|
@@ -526,7 +544,8 @@ def _process_db_access(
|
|
526
544
|
admin_secret_name,
|
527
545
|
resource_prefix,
|
528
546
|
settings,
|
529
|
-
|
547
|
+
connections["user"],
|
548
|
+
connections["admin"],
|
530
549
|
)
|
531
550
|
|
532
551
|
# create job, delete old, failed job first
|
@@ -16,6 +16,7 @@ from reconcile.database_access_manager import (
|
|
16
16
|
JobStatusCondition,
|
17
17
|
PSQLScriptGenerator,
|
18
18
|
_create_database_connection_parameter,
|
19
|
+
_DBDonnections,
|
19
20
|
_generate_password,
|
20
21
|
_populate_resources,
|
21
22
|
_process_db_access,
|
@@ -87,6 +88,17 @@ def db_connection_parameter():
|
|
87
88
|
)
|
88
89
|
|
89
90
|
|
91
|
+
@pytest.fixture
|
92
|
+
def db_admin_connection_parameter():
|
93
|
+
return DatabaseConnectionParameters(
|
94
|
+
host="localhost",
|
95
|
+
port="5432",
|
96
|
+
user="admin",
|
97
|
+
password="adminpw", # notsecret
|
98
|
+
database="test",
|
99
|
+
)
|
100
|
+
|
101
|
+
|
90
102
|
@pytest.fixture
|
91
103
|
def db_secret_dict() -> dict[str, dict[str, str]]:
|
92
104
|
return {
|
@@ -118,6 +130,7 @@ def _assert_create_script(script: str) -> None:
|
|
118
130
|
assert "REVOKE ALL ON DATABASE" in script
|
119
131
|
assert 'CREATE ROLE "test" WITH LOGIN PASSWORD' in script
|
120
132
|
assert "CREATE SCHEMA IF NOT EXISTS" in script
|
133
|
+
assert 'GRANT "test" to "admin";' in script
|
121
134
|
|
122
135
|
|
123
136
|
def _assert_grant_access(script: str) -> None:
|
@@ -125,11 +138,14 @@ def _assert_grant_access(script: str) -> None:
|
|
125
138
|
|
126
139
|
|
127
140
|
def test_generate_create_user(
|
128
|
-
db_access: DatabaseAccessV1,
|
141
|
+
db_access: DatabaseAccessV1,
|
142
|
+
db_connection_parameter: DatabaseConnectionParameters,
|
143
|
+
db_admin_connection_parameter: DatabaseConnectionParameters,
|
129
144
|
) -> None:
|
130
145
|
s = PSQLScriptGenerator(
|
131
146
|
db_access=db_access,
|
132
147
|
connection_parameter=db_connection_parameter,
|
148
|
+
admin_connection_parameter=db_admin_connection_parameter,
|
133
149
|
engine="postgres",
|
134
150
|
)
|
135
151
|
script = s._generate_create_user()
|
@@ -140,12 +156,14 @@ def test_generate_access(
|
|
140
156
|
db_access: DatabaseAccessV1,
|
141
157
|
db_access_access: DatabaseAccessAccessV1,
|
142
158
|
db_connection_parameter: DatabaseConnectionParameters,
|
159
|
+
db_admin_connection_parameter: DatabaseConnectionParameters,
|
143
160
|
):
|
144
161
|
db_access.access = [db_access_access]
|
145
162
|
|
146
163
|
s = PSQLScriptGenerator(
|
147
164
|
db_access=db_access,
|
148
165
|
connection_parameter=db_connection_parameter,
|
166
|
+
admin_connection_parameter=db_connection_parameter,
|
149
167
|
engine="postgres",
|
150
168
|
)
|
151
169
|
script = s._generate_db_access()
|
@@ -155,10 +173,12 @@ def test_generate_access(
|
|
155
173
|
def test_generate_complete(
|
156
174
|
db_access_complete: DatabaseAccessV1,
|
157
175
|
db_connection_parameter: DatabaseConnectionParameters,
|
176
|
+
db_admin_connection_parameter: DatabaseConnectionParameters,
|
158
177
|
):
|
159
178
|
s = PSQLScriptGenerator(
|
160
179
|
db_access=db_access_complete,
|
161
180
|
connection_parameter=db_connection_parameter,
|
181
|
+
admin_connection_parameter=db_admin_connection_parameter,
|
162
182
|
engine="postgres",
|
163
183
|
)
|
164
184
|
script = s.generate_script()
|
@@ -185,6 +205,7 @@ def test_populate_resources(
|
|
185
205
|
mocker: MockerFixture,
|
186
206
|
db_access: DatabaseAccessV1,
|
187
207
|
db_connection_parameter: DatabaseConnectionParameters,
|
208
|
+
db_admin_connection_parameter: DatabaseConnectionParameters,
|
188
209
|
openshift_resource_secet: OpenshiftResource,
|
189
210
|
):
|
190
211
|
mocker.patch(
|
@@ -205,7 +226,8 @@ def test_populate_resources(
|
|
205
226
|
admin_secret_name="db-secret",
|
206
227
|
resource_prefix="dbam-foo",
|
207
228
|
settings={"foo": "bar"},
|
208
|
-
|
229
|
+
user_connection=db_connection_parameter,
|
230
|
+
admin_connection=db_admin_connection_parameter,
|
209
231
|
)
|
210
232
|
|
211
233
|
r_kinds = [r.resource.kind for r in reources]
|
@@ -226,7 +248,7 @@ def test__create_database_connection_parameter_user_exists(
|
|
226
248
|
admin_secret_name="db-secret",
|
227
249
|
user_secret_name="db-user-secret",
|
228
250
|
)
|
229
|
-
|
251
|
+
conn = DatabaseConnectionParameters(
|
230
252
|
host="localhost",
|
231
253
|
port="5432",
|
232
254
|
user="test",
|
@@ -234,6 +256,10 @@ def test__create_database_connection_parameter_user_exists(
|
|
234
256
|
database="test",
|
235
257
|
)
|
236
258
|
|
259
|
+
assert p["user"] == conn
|
260
|
+
assert p["admin"] == conn
|
261
|
+
assert oc.get.call_count == 2
|
262
|
+
|
237
263
|
|
238
264
|
def test__create_database_connection_parameter_user_missing(
|
239
265
|
db_access: DatabaseAccessV1,
|
@@ -254,7 +280,7 @@ def test__create_database_connection_parameter_user_missing(
|
|
254
280
|
admin_secret_name="db-secret",
|
255
281
|
user_secret_name="db-user-secret",
|
256
282
|
)
|
257
|
-
|
283
|
+
conn = DatabaseConnectionParameters(
|
258
284
|
host="localhost",
|
259
285
|
port="5432",
|
260
286
|
user="test",
|
@@ -262,6 +288,13 @@ def test__create_database_connection_parameter_user_missing(
|
|
262
288
|
database="test",
|
263
289
|
)
|
264
290
|
|
291
|
+
admin_conn = conn.copy()
|
292
|
+
admin_conn.password = "hduhsdfuhsdf"
|
293
|
+
|
294
|
+
assert p["user"] == conn
|
295
|
+
assert p["admin"] == admin_conn
|
296
|
+
assert oc.get.call_count == 2
|
297
|
+
|
265
298
|
|
266
299
|
def test_generate_password():
|
267
300
|
assert len(_generate_password()) == 32
|
@@ -275,12 +308,18 @@ def dbam_state(mocker: MockerFixture) -> MockerFixture:
|
|
275
308
|
|
276
309
|
@pytest.fixture
|
277
310
|
def dbam_process_mocks(
|
278
|
-
openshift_resource_secet: OpenshiftResource,
|
311
|
+
openshift_resource_secet: OpenshiftResource,
|
312
|
+
mocker: MockerFixture,
|
313
|
+
db_connection_parameter: DatabaseConnectionParameters,
|
314
|
+
db_admin_connection_parameter: DatabaseConnectionParameters,
|
279
315
|
) -> DBAMResource:
|
280
316
|
expected_resource = DBAMResource(resource=openshift_resource_secet, clean_up=True)
|
281
317
|
mocker.patch(
|
282
318
|
"reconcile.database_access_manager._create_database_connection_parameter",
|
283
|
-
return_value=
|
319
|
+
return_value=_DBDonnections(
|
320
|
+
user=db_connection_parameter,
|
321
|
+
admin=db_admin_connection_parameter,
|
322
|
+
),
|
284
323
|
)
|
285
324
|
mocker.patch(
|
286
325
|
"reconcile.database_access_manager._populate_resources",
|
File without changes
|
File without changes
|
{qontract_reconcile-0.10.1rc428.dist-info → qontract_reconcile-0.10.1rc429.dist-info}/top_level.txt
RENAMED
File without changes
|