qontract-reconcile 0.9.1rc273__py3-none-any.whl → 0.9.1rc275__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.1rc273.dist-info → qontract_reconcile-0.9.1rc275.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.9.1rc273.dist-info → qontract_reconcile-0.9.1rc275.dist-info}/RECORD +15 -14
- reconcile/saas_auto_promotions_manager/integration.py +2 -18
- reconcile/saas_auto_promotions_manager/subscriber.py +9 -0
- reconcile/terraform_tgw_attachments.py +239 -128
- reconcile/test/saas_auto_promotions_manager/subscriber/conftest.py +6 -24
- reconcile/test/saas_auto_promotions_manager/subscriber/test_diff.py +93 -0
- reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_config_hash.py +88 -45
- reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_moving_ref.py +88 -45
- reconcile/test/saas_auto_promotions_manager/subscriber/test_single_channel_with_single_publisher.py +91 -56
- reconcile/test/test_terraform_tgw_attachments.py +298 -91
- reconcile/utils/terrascript_aws_client.py +2 -2
- {qontract_reconcile-0.9.1rc273.dist-info → qontract_reconcile-0.9.1rc275.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.9.1rc273.dist-info → qontract_reconcile-0.9.1rc275.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.9.1rc273.dist-info → qontract_reconcile-0.9.1rc275.dist-info}/top_level.txt +0 -0
@@ -1,87 +1,168 @@
|
|
1
|
+
from collections.abc import (
|
2
|
+
Callable,
|
3
|
+
Iterable,
|
4
|
+
Mapping,
|
5
|
+
)
|
6
|
+
from typing import Optional
|
7
|
+
|
1
8
|
import pytest
|
9
|
+
from pytest_mock import MockerFixture
|
2
10
|
|
3
11
|
import reconcile.terraform_tgw_attachments as integ
|
4
12
|
|
5
13
|
|
6
14
|
@pytest.fixture
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
def peering_connection_builder() -> Callable[..., dict]:
|
16
|
+
def builder(
|
17
|
+
name: str,
|
18
|
+
provider: str,
|
19
|
+
manage_routes: bool = False,
|
20
|
+
account_name: Optional[str] = None,
|
21
|
+
account_uid: Optional[str] = None,
|
22
|
+
terraform_username: Optional[str] = None,
|
23
|
+
assume_role: Optional[str] = None,
|
24
|
+
cidr_block: Optional[str] = None,
|
25
|
+
deleted: Optional[bool] = None,
|
26
|
+
) -> dict:
|
27
|
+
return {
|
28
|
+
"name": name,
|
29
|
+
"provider": provider,
|
30
|
+
"manageRoutes": manage_routes,
|
31
|
+
"account": {
|
32
|
+
"name": account_name,
|
33
|
+
"uid": account_uid,
|
34
|
+
"terraformUsername": terraform_username,
|
35
|
+
},
|
36
|
+
"assumeRole": assume_role,
|
37
|
+
"cidrBlock": cidr_block,
|
38
|
+
"deleted": deleted,
|
39
|
+
}
|
40
|
+
|
41
|
+
return builder
|
21
42
|
|
22
43
|
|
23
44
|
@pytest.fixture
|
24
|
-
def
|
25
|
-
return
|
26
|
-
|
27
|
-
|
28
|
-
|
45
|
+
def account_tgw_connection(peering_connection_builder: Callable[..., dict]) -> dict:
|
46
|
+
return peering_connection_builder(
|
47
|
+
name="account_tgw_connection",
|
48
|
+
provider="account-tgw",
|
49
|
+
manage_routes=True,
|
50
|
+
account_name="tgw_account",
|
51
|
+
account_uid="a-uid",
|
52
|
+
terraform_username="tf-user",
|
53
|
+
assume_role=None,
|
54
|
+
cidr_block="172.16.0.0/16",
|
55
|
+
deleted=False,
|
56
|
+
)
|
29
57
|
|
30
58
|
|
31
59
|
@pytest.fixture
|
32
|
-
def
|
33
|
-
return
|
34
|
-
|
35
|
-
"
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
60
|
+
def account_vpc_connection(peering_connection_builder: Callable[..., dict]) -> dict:
|
61
|
+
return peering_connection_builder(
|
62
|
+
name="account_vpc_connection",
|
63
|
+
provider="account-vpc",
|
64
|
+
)
|
65
|
+
|
66
|
+
|
67
|
+
@pytest.fixture
|
68
|
+
def cluster_builder() -> Callable[..., dict]:
|
69
|
+
def builder(
|
70
|
+
name: str,
|
71
|
+
ocm: dict,
|
72
|
+
region: str,
|
73
|
+
vpc_cidr: str,
|
74
|
+
peering: dict,
|
75
|
+
) -> dict:
|
76
|
+
return {
|
77
|
+
"name": name,
|
78
|
+
"ocm": ocm,
|
79
|
+
"spec": {
|
80
|
+
"region": region,
|
81
|
+
},
|
82
|
+
"network": {"vpc": vpc_cidr},
|
83
|
+
"peering": peering,
|
84
|
+
}
|
85
|
+
|
86
|
+
return builder
|
87
|
+
|
88
|
+
|
89
|
+
@pytest.fixture
|
90
|
+
def cluster_with_tgw_connection(
|
91
|
+
cluster_builder: Callable[..., dict],
|
92
|
+
account_tgw_connection: dict,
|
93
|
+
) -> dict:
|
94
|
+
return cluster_builder(
|
95
|
+
name="cluster_with_tgw_connection",
|
96
|
+
ocm={"name": "cluster_with_tgw_connection-ocm"},
|
97
|
+
region="us-east-1",
|
98
|
+
vpc_cidr="10.0.0.0/16",
|
99
|
+
peering={
|
41
100
|
"connections": [
|
42
101
|
account_tgw_connection,
|
43
102
|
]
|
44
103
|
},
|
45
|
-
|
104
|
+
)
|
46
105
|
|
47
106
|
|
48
107
|
@pytest.fixture
|
49
|
-
def
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
108
|
+
def cluster_with_duplicate_tgw_connections(
|
109
|
+
cluster_builder: Callable[..., dict],
|
110
|
+
account_tgw_connection: dict,
|
111
|
+
) -> dict:
|
112
|
+
return cluster_builder(
|
113
|
+
name="cluster_with_duplicate_tgw_connections",
|
114
|
+
ocm={"name": "cluster_with_duplicate_tgw_connections-ocm"},
|
115
|
+
region="us-east-1",
|
116
|
+
vpc_cidr="10.0.0.0/16",
|
117
|
+
peering={
|
118
|
+
"connections": [
|
119
|
+
account_tgw_connection,
|
120
|
+
account_tgw_connection,
|
121
|
+
]
|
55
122
|
},
|
56
|
-
|
57
|
-
|
123
|
+
)
|
124
|
+
|
125
|
+
|
126
|
+
@pytest.fixture
|
127
|
+
def cluster_with_vpc_connection(
|
128
|
+
cluster_builder: Callable[..., dict],
|
129
|
+
account_vpc_connection: Mapping,
|
130
|
+
) -> dict:
|
131
|
+
return cluster_builder(
|
132
|
+
name="cluster_with_vpc_connection",
|
133
|
+
ocm={"name": "cluster_with_vpc_connection-ocm"},
|
134
|
+
region="us-east-1",
|
135
|
+
vpc_cidr="10.0.0.1/16",
|
136
|
+
peering={
|
58
137
|
"connections": [
|
59
138
|
account_vpc_connection,
|
60
139
|
]
|
61
140
|
},
|
62
|
-
|
141
|
+
)
|
63
142
|
|
64
143
|
|
65
144
|
@pytest.fixture
|
66
|
-
def cluster_with_mixed_connections(
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
"
|
145
|
+
def cluster_with_mixed_connections(
|
146
|
+
cluster_builder: Callable[..., dict],
|
147
|
+
account_tgw_connection: Mapping,
|
148
|
+
account_vpc_connection: Mapping,
|
149
|
+
) -> dict:
|
150
|
+
return cluster_builder(
|
151
|
+
name="cluster_with_mixed_connections",
|
152
|
+
ocm={"name": "cluster_with_mixed_connections-ocm"},
|
153
|
+
region="us-east-1",
|
154
|
+
vpc_cidr="10.0.0.2/16",
|
155
|
+
peering={
|
75
156
|
"connections": [
|
76
157
|
account_tgw_connection,
|
77
158
|
account_vpc_connection,
|
78
159
|
]
|
79
160
|
},
|
80
|
-
|
161
|
+
)
|
81
162
|
|
82
163
|
|
83
164
|
@pytest.fixture
|
84
|
-
def tgw():
|
165
|
+
def tgw() -> dict:
|
85
166
|
return {
|
86
167
|
"tgw_id": "tgw-1",
|
87
168
|
"tgw_arn": "tgw-arn-1",
|
@@ -93,7 +174,7 @@ def tgw():
|
|
93
174
|
|
94
175
|
|
95
176
|
@pytest.fixture
|
96
|
-
def vpc_details():
|
177
|
+
def vpc_details() -> dict:
|
97
178
|
return {
|
98
179
|
"vpc_id": "vpc-id-1",
|
99
180
|
"route_table_ids": ["rtb-1"],
|
@@ -102,24 +183,36 @@ def vpc_details():
|
|
102
183
|
|
103
184
|
|
104
185
|
@pytest.fixture
|
105
|
-
def assume_role():
|
186
|
+
def assume_role() -> str:
|
106
187
|
return "some-role"
|
107
188
|
|
108
189
|
|
109
190
|
def _setup_mocks(
|
110
|
-
mocker
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
mocker.patch("reconcile.queries
|
191
|
+
mocker: MockerFixture,
|
192
|
+
clusters: Optional[Iterable] = None,
|
193
|
+
accounts: Optional[Iterable] = None,
|
194
|
+
vpc_details: Optional[Mapping] = None,
|
195
|
+
tgws: Optional[Iterable] = None,
|
196
|
+
assume_role: Optional[str] = None,
|
197
|
+
) -> dict:
|
198
|
+
mocked_queries = mocker.patch("reconcile.terraform_tgw_attachments.queries")
|
199
|
+
mocked_queries.get_secret_reader_settings.return_value = {}
|
200
|
+
mocked_queries.get_clusters_with_peering_settings.return_value = clusters or []
|
201
|
+
mocked_queries.get_aws_accounts.return_value = accounts or []
|
118
202
|
mocked_aws_api = mocker.patch(
|
119
203
|
"reconcile.terraform_tgw_attachments.AWSApi", autospec=True
|
120
204
|
).return_value
|
121
205
|
with mocked_aws_api as aws_api:
|
122
|
-
|
206
|
+
vpc = (
|
207
|
+
(
|
208
|
+
vpc_details["vpc_id"],
|
209
|
+
vpc_details["route_table_ids"],
|
210
|
+
vpc_details["subnets_id_az"],
|
211
|
+
)
|
212
|
+
if vpc_details is not None
|
213
|
+
else (None, None, None)
|
214
|
+
)
|
215
|
+
aws_api.get_cluster_vpc_details.return_value = vpc
|
123
216
|
aws_api.get_tgws_details.return_value = tgws or []
|
124
217
|
mocked_ocm = mocker.patch(
|
125
218
|
"reconcile.terraform_tgw_attachments.OCMMap", autospec=True
|
@@ -140,43 +233,50 @@ def _setup_mocks(
|
|
140
233
|
return {
|
141
234
|
"tf": mocked_tf,
|
142
235
|
"ts": mocked_ts,
|
236
|
+
"queries": mocked_queries,
|
143
237
|
}
|
144
238
|
|
145
239
|
|
146
|
-
def test_dry_run(mocker):
|
240
|
+
def test_dry_run(mocker: MockerFixture) -> None:
|
147
241
|
mocks = _setup_mocks(mocker)
|
148
242
|
|
149
243
|
integ.run(True, enable_deletion=False)
|
150
244
|
|
245
|
+
mocks["queries"].get_secret_reader_settings.assert_called_once_with()
|
246
|
+
mocks["queries"].get_clusters_with_peering_settings.assert_called_once_with()
|
247
|
+
mocks["queries"].get_aws_accounts.assert_called_once_with(
|
248
|
+
terraform_state=True, ecrs=False
|
249
|
+
)
|
151
250
|
mocks["tf"].plan.assert_called_once_with(False)
|
152
251
|
mocks["tf"].apply.assert_not_called()
|
153
252
|
|
154
253
|
|
155
|
-
def test_non_dry_run(mocker):
|
254
|
+
def test_non_dry_run(mocker: MockerFixture) -> None:
|
156
255
|
mocks = _setup_mocks(mocker)
|
157
256
|
|
158
257
|
integ.run(False, enable_deletion=False)
|
159
258
|
|
259
|
+
mocks["queries"].get_secret_reader_settings.assert_called_once_with()
|
260
|
+
mocks["queries"].get_clusters_with_peering_settings.assert_called_once_with()
|
261
|
+
mocks["queries"].get_aws_accounts.assert_called_once_with(
|
262
|
+
terraform_state=True, ecrs=False
|
263
|
+
)
|
160
264
|
mocks["tf"].plan.assert_called_once_with(False)
|
161
265
|
mocks["tf"].apply.assert_called_once()
|
162
266
|
|
163
267
|
|
164
268
|
def test_run_when_cluster_with_tgw_connection(
|
165
|
-
mocker,
|
166
|
-
cluster_with_tgw_connection,
|
167
|
-
account_tgw_connection,
|
168
|
-
tgw,
|
169
|
-
vpc_details,
|
170
|
-
assume_role,
|
171
|
-
):
|
269
|
+
mocker: MockerFixture,
|
270
|
+
cluster_with_tgw_connection: Mapping,
|
271
|
+
account_tgw_connection: Mapping,
|
272
|
+
tgw: Mapping,
|
273
|
+
vpc_details: Mapping,
|
274
|
+
assume_role: str,
|
275
|
+
) -> None:
|
172
276
|
mocks = _setup_mocks(
|
173
277
|
mocker,
|
174
278
|
clusters=[cluster_with_tgw_connection],
|
175
|
-
|
176
|
-
vpc_details["vpc_id"],
|
177
|
-
vpc_details["route_table_ids"],
|
178
|
-
vpc_details["subnets_id_az"],
|
179
|
-
),
|
279
|
+
vpc_details=vpc_details,
|
180
280
|
tgws=[tgw],
|
181
281
|
assume_role=assume_role,
|
182
282
|
)
|
@@ -193,7 +293,7 @@ def test_run_when_cluster_with_tgw_connection(
|
|
193
293
|
}
|
194
294
|
|
195
295
|
mocks["ts"].populate_additional_providers.assert_called_once_with(
|
196
|
-
[expected_tgw_account
|
296
|
+
[expected_tgw_account]
|
197
297
|
)
|
198
298
|
mocks["ts"].populate_tgw_attachments.assert_called_once_with(
|
199
299
|
[
|
@@ -225,21 +325,17 @@ def test_run_when_cluster_with_tgw_connection(
|
|
225
325
|
|
226
326
|
|
227
327
|
def test_run_when_cluster_with_mixed_connections(
|
228
|
-
mocker,
|
229
|
-
cluster_with_mixed_connections,
|
230
|
-
account_tgw_connection,
|
231
|
-
tgw,
|
232
|
-
vpc_details,
|
233
|
-
assume_role,
|
234
|
-
):
|
328
|
+
mocker: MockerFixture,
|
329
|
+
cluster_with_mixed_connections: Mapping,
|
330
|
+
account_tgw_connection: Mapping,
|
331
|
+
tgw: Mapping,
|
332
|
+
vpc_details: Mapping,
|
333
|
+
assume_role: str,
|
334
|
+
) -> None:
|
235
335
|
mocks = _setup_mocks(
|
236
336
|
mocker,
|
237
337
|
clusters=[cluster_with_mixed_connections],
|
238
|
-
|
239
|
-
vpc_details["vpc_id"],
|
240
|
-
vpc_details["route_table_ids"],
|
241
|
-
vpc_details["subnets_id_az"],
|
242
|
-
),
|
338
|
+
vpc_details=vpc_details,
|
243
339
|
tgws=[tgw],
|
244
340
|
assume_role=assume_role,
|
245
341
|
)
|
@@ -256,7 +352,7 @@ def test_run_when_cluster_with_mixed_connections(
|
|
256
352
|
}
|
257
353
|
|
258
354
|
mocks["ts"].populate_additional_providers.assert_called_once_with(
|
259
|
-
[expected_tgw_account
|
355
|
+
[expected_tgw_account]
|
260
356
|
)
|
261
357
|
mocks["ts"].populate_tgw_attachments.assert_called_once_with(
|
262
358
|
[
|
@@ -288,9 +384,9 @@ def test_run_when_cluster_with_mixed_connections(
|
|
288
384
|
|
289
385
|
|
290
386
|
def test_run_when_cluster_with_vpc_connection_only(
|
291
|
-
mocker,
|
292
|
-
cluster_with_vpc_connection,
|
293
|
-
):
|
387
|
+
mocker: MockerFixture,
|
388
|
+
cluster_with_vpc_connection: Mapping,
|
389
|
+
) -> None:
|
294
390
|
mocks = _setup_mocks(
|
295
391
|
mocker,
|
296
392
|
clusters=[cluster_with_vpc_connection],
|
@@ -300,3 +396,114 @@ def test_run_when_cluster_with_vpc_connection_only(
|
|
300
396
|
|
301
397
|
mocks["ts"].populate_additional_providers.assert_called_once_with([])
|
302
398
|
mocks["ts"].populate_tgw_attachments.assert_called_once_with([])
|
399
|
+
|
400
|
+
|
401
|
+
def test_duplicate_tgw_connection_names(
|
402
|
+
mocker: MockerFixture,
|
403
|
+
cluster_with_duplicate_tgw_connections: Mapping,
|
404
|
+
tgw: Mapping,
|
405
|
+
vpc_details: Mapping,
|
406
|
+
assume_role: str,
|
407
|
+
) -> None:
|
408
|
+
_setup_mocks(
|
409
|
+
mocker,
|
410
|
+
clusters=[cluster_with_duplicate_tgw_connections],
|
411
|
+
vpc_details=vpc_details,
|
412
|
+
tgws=[tgw],
|
413
|
+
assume_role=assume_role,
|
414
|
+
)
|
415
|
+
|
416
|
+
with pytest.raises(integ.ValidationError) as e:
|
417
|
+
integ.run(True)
|
418
|
+
|
419
|
+
assert "duplicate tgw connection names found" == str(e.value)
|
420
|
+
|
421
|
+
|
422
|
+
def test_missing_vpc_id(
|
423
|
+
mocker: MockerFixture,
|
424
|
+
cluster_with_tgw_connection: Mapping,
|
425
|
+
tgw: Mapping,
|
426
|
+
vpc_details: Mapping,
|
427
|
+
assume_role: str,
|
428
|
+
) -> None:
|
429
|
+
_setup_mocks(
|
430
|
+
mocker,
|
431
|
+
clusters=[cluster_with_tgw_connection],
|
432
|
+
vpc_details=None,
|
433
|
+
tgws=[tgw],
|
434
|
+
assume_role=assume_role,
|
435
|
+
)
|
436
|
+
|
437
|
+
with pytest.raises(RuntimeError) as e:
|
438
|
+
integ.run(True)
|
439
|
+
|
440
|
+
assert "Could not find VPC ID for cluster" == str(e.value)
|
441
|
+
|
442
|
+
|
443
|
+
def test_error_in_tf_plan(
|
444
|
+
mocker: MockerFixture,
|
445
|
+
cluster_with_tgw_connection: Mapping,
|
446
|
+
account_tgw_connection: Mapping,
|
447
|
+
tgw: Mapping,
|
448
|
+
vpc_details: Mapping,
|
449
|
+
assume_role: str,
|
450
|
+
) -> None:
|
451
|
+
mocks = _setup_mocks(
|
452
|
+
mocker,
|
453
|
+
clusters=[cluster_with_tgw_connection],
|
454
|
+
vpc_details=vpc_details,
|
455
|
+
tgws=[tgw],
|
456
|
+
assume_role=assume_role,
|
457
|
+
)
|
458
|
+
mocks["tf"].plan.return_value = (False, True)
|
459
|
+
|
460
|
+
with pytest.raises(RuntimeError) as e:
|
461
|
+
integ.run(True)
|
462
|
+
|
463
|
+
assert "Error running terraform plan" == str(e.value)
|
464
|
+
|
465
|
+
|
466
|
+
def test_disabled_deletions_detected_in_tf_plan(
|
467
|
+
mocker: MockerFixture,
|
468
|
+
cluster_with_tgw_connection: Mapping,
|
469
|
+
account_tgw_connection: Mapping,
|
470
|
+
tgw: Mapping,
|
471
|
+
vpc_details: Mapping,
|
472
|
+
assume_role: str,
|
473
|
+
) -> None:
|
474
|
+
mocks = _setup_mocks(
|
475
|
+
mocker,
|
476
|
+
clusters=[cluster_with_tgw_connection],
|
477
|
+
vpc_details=vpc_details,
|
478
|
+
tgws=[tgw],
|
479
|
+
assume_role=assume_role,
|
480
|
+
)
|
481
|
+
mocks["tf"].plan.return_value = (True, False)
|
482
|
+
|
483
|
+
with pytest.raises(RuntimeError) as e:
|
484
|
+
integ.run(True)
|
485
|
+
|
486
|
+
assert "Disabled deletions detected running terraform plan" == str(e.value)
|
487
|
+
|
488
|
+
|
489
|
+
def test_error_in_terraform_apply(
|
490
|
+
mocker: MockerFixture,
|
491
|
+
cluster_with_tgw_connection: Mapping,
|
492
|
+
account_tgw_connection: Mapping,
|
493
|
+
tgw: Mapping,
|
494
|
+
vpc_details: Mapping,
|
495
|
+
assume_role: str,
|
496
|
+
) -> None:
|
497
|
+
mocks = _setup_mocks(
|
498
|
+
mocker,
|
499
|
+
clusters=[cluster_with_tgw_connection],
|
500
|
+
vpc_details=vpc_details,
|
501
|
+
tgws=[tgw],
|
502
|
+
assume_role=assume_role,
|
503
|
+
)
|
504
|
+
mocks["tf"].apply.return_value = True
|
505
|
+
|
506
|
+
with pytest.raises(RuntimeError) as e:
|
507
|
+
integ.run(False)
|
508
|
+
|
509
|
+
assert "Error running terraform apply" == str(e.value)
|
@@ -328,7 +328,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
328
328
|
integration: str,
|
329
329
|
integration_prefix: str,
|
330
330
|
thread_pool_size: int,
|
331
|
-
accounts:
|
331
|
+
accounts: Iterable[dict[str, Any]],
|
332
332
|
settings: Optional[Mapping[str, Any]] = None,
|
333
333
|
prefetch_resources_by_schemas: Optional[list[str]] = None,
|
334
334
|
) -> None:
|
@@ -837,7 +837,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
837
837
|
alias = self.get_alias_name_from_assume_role(assume_role)
|
838
838
|
ts = self.tss[account_name]
|
839
839
|
config = self.configs[account_name]
|
840
|
-
existing_provider_aliases =
|
840
|
+
existing_provider_aliases = {p.get("alias") for p in ts["provider"]["aws"]}
|
841
841
|
if alias not in existing_provider_aliases:
|
842
842
|
ts += provider.aws(
|
843
843
|
access_key=config["aws_access_key_id"],
|
File without changes
|
{qontract_reconcile-0.9.1rc273.dist-info → qontract_reconcile-0.9.1rc275.dist-info}/entry_points.txt
RENAMED
File without changes
|
{qontract_reconcile-0.9.1rc273.dist-info → qontract_reconcile-0.9.1rc275.dist-info}/top_level.txt
RENAMED
File without changes
|