qontract-reconcile 0.10.1rc708__py3-none-any.whl → 0.10.1rc710__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.1rc708.dist-info → qontract_reconcile-0.10.1rc710.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc708.dist-info → qontract_reconcile-0.10.1rc710.dist-info}/RECORD +12 -9
- reconcile/gql_definitions/common/pipeline_providers.py +1 -0
- reconcile/gql_definitions/common/reserved_networks.py +94 -0
- reconcile/gql_definitions/fragments/pipeline_provider_retention.py +1 -0
- reconcile/openshift_saas_deploy_trigger_cleaner.py +28 -9
- reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py +65 -0
- reconcile/typed_queries/reserved_networks.py +14 -0
- tools/qontract_cli.py +46 -0
- {qontract_reconcile-0.10.1rc708.dist-info → qontract_reconcile-0.10.1rc710.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc708.dist-info → qontract_reconcile-0.10.1rc710.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc708.dist-info → qontract_reconcile-0.10.1rc710.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc708.dist-info → qontract_reconcile-0.10.1rc710.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.1rc710
|
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.1rc708.dist-info → qontract_reconcile-0.10.1rc710.dist-info}/RECORD
RENAMED
@@ -77,7 +77,7 @@ reconcile/openshift_routes.py,sha256=fXvuPSjcjVw1X3j2EQvUAdbOepmIFdKk-M3qP8QzPiw
|
|
77
77
|
reconcile/openshift_saas_deploy.py,sha256=fmhopPEbyZsGQHRPzyzpKEvoBXEGN3aPxFi7Utq0emU,12788
|
78
78
|
reconcile/openshift_saas_deploy_change_tester.py,sha256=fMmPDz-ZRO-WH8OIiDo4e4sBK4-zzpvFXmVCKGY1l-I,8837
|
79
79
|
reconcile/openshift_saas_deploy_trigger_base.py,sha256=p1Mv7dbw_K7TVFv-M-DDq6r1ltuW9VAF6PCNnEng_zM,14291
|
80
|
-
reconcile/openshift_saas_deploy_trigger_cleaner.py,sha256=
|
80
|
+
reconcile/openshift_saas_deploy_trigger_cleaner.py,sha256=gU226N1JUvgEbTgDf7ouJ6QzZGMI_BLwXdS67UCukRk,3554
|
81
81
|
reconcile/openshift_saas_deploy_trigger_configs.py,sha256=uWzUV5D5CW0frdi1ys7BObNg-rA-VZKlefd4TD_Z-pY,959
|
82
82
|
reconcile/openshift_saas_deploy_trigger_images.py,sha256=Yl4lMtxqab-c04I2Ju8isAJuYuNTbHN01Bk3dF9nTos,967
|
83
83
|
reconcile/openshift_saas_deploy_trigger_moving_commits.py,sha256=VqjwgRhA-yOSq0WFPqGIJVgYkdq_UrTHcVusBzOFgMY,973
|
@@ -234,7 +234,8 @@ reconcile/gql_definitions/common/ocm_env_telemeter.py,sha256=jW0Q9WazDQVOxh4u0LM
|
|
234
234
|
reconcile/gql_definitions/common/ocm_environments.py,sha256=2Szg8VSIM4a9ZbjktDjSY6I1enih2Cx1tjYXoUFiZX0,2002
|
235
235
|
reconcile/gql_definitions/common/pagerduty_instances.py,sha256=qcbOSUNwmeRcBetJ2FktUu6Mn4CPE2iNoevt3fY_xig,1988
|
236
236
|
reconcile/gql_definitions/common/pgp_reencryption_settings.py,sha256=NPLmO6J-zSu5B9QiYbDezLHY3TuOO9ihRBV-Zr84R9w,2259
|
237
|
-
reconcile/gql_definitions/common/pipeline_providers.py,sha256=
|
237
|
+
reconcile/gql_definitions/common/pipeline_providers.py,sha256=JJgmmghqLIwjKOdcWYHPnf4PDgAq4GF7046i0ozrqgI,9127
|
238
|
+
reconcile/gql_definitions/common/reserved_networks.py,sha256=yP9qSQCaSQcva-ZgTnZp09qH27ur5_qK080ToIs04MY,2560
|
238
239
|
reconcile/gql_definitions/common/saas_files.py,sha256=B7HE_jV5ky8AFxOCleSg2RYDrtUaV99DYa2If8wyvHs,15926
|
239
240
|
reconcile/gql_definitions/common/saas_target_namespaces.py,sha256=gcTU9jrsNq9-HX-oOkj-nEZKYFTRytDHLs4SpEs93aw,2755
|
240
241
|
reconcile/gql_definitions/common/saasherder_settings.py,sha256=nqQLcMwYxLseqq0BEcVvmrpIj2eQq0h8XDSpLN6GGCw,1793
|
@@ -262,7 +263,7 @@ reconcile/gql_definitions/fragments/membership_source.py,sha256=rVjAIAhhAoH0_fUf
|
|
262
263
|
reconcile/gql_definitions/fragments/minimal_ocm_organization.py,sha256=G7uEwGR2qjtXl3yUUMWAzbihNKor0jj1_fcSd9qQOjw,731
|
263
264
|
reconcile/gql_definitions/fragments/oc_connection_cluster.py,sha256=GO4v0q7urQt2G6fU6HJSgHmFOPxNCc3oO0zAwz9bU7o,1530
|
264
265
|
reconcile/gql_definitions/fragments/ocm_environment.py,sha256=mEbBooD-SAxe7l73sja0ELiByGkTiqxuca9vmxfIISw,1075
|
265
|
-
reconcile/gql_definitions/fragments/pipeline_provider_retention.py,sha256=
|
266
|
+
reconcile/gql_definitions/fragments/pipeline_provider_retention.py,sha256=nIGIaeuBDw5emBdDJvajl27pGULQ2fYG5SkQ0AYTr7E,814
|
266
267
|
reconcile/gql_definitions/fragments/prometheus_instance.py,sha256=12ltnV9kdEw6LnHgevdM6Ms-lCPY802RC-CrYOoRRgY,1575
|
267
268
|
reconcile/gql_definitions/fragments/resource_limits_requirements.py,sha256=ucskQ_a8RxvFl5-IWxz5kk3g4-5Pvh_W4N3nLmuKxi0,744
|
268
269
|
reconcile/gql_definitions/fragments/resource_requests_requirements.py,sha256=TFKO4YALFPanSvZvIJFz0dCioBU7i73Q6hkDtGMvs9I,736
|
@@ -468,6 +469,7 @@ reconcile/test/test_openshift_resource.py,sha256=lbTf48jX1q6rGnRiA5pPvfU0uPfY8zh
|
|
468
469
|
reconcile/test/test_openshift_resources_base.py,sha256=LtlR9x3o7KkSEw0JN0fZhinFeAAxBAQlB_9PpBnKwOM,14353
|
469
470
|
reconcile/test/test_openshift_saas_deploy.py,sha256=YLJGkc--u5aP0UkQ-b9ZGEFGS2gw25jjcSgknQdI3Ic,5892
|
470
471
|
reconcile/test/test_openshift_saas_deploy_change_tester.py,sha256=1yVe54Hx9YdVjn6qdnKge5Sa_s732c-8uZqCnuT1gGI,12871
|
472
|
+
reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py,sha256=cha3bUiXAWPCwrp8XwVC3RNJtJHLcsGTE-F8Zn6XxsU,2852
|
471
473
|
reconcile/test/test_openshift_tekton_resources.py,sha256=RtRWsdm51S13OSkENC9nY_rOH0QELSCaO5tjF0XqIDI,11222
|
472
474
|
reconcile/test/test_openshift_upgrade_watcher.py,sha256=0GDQ_YFHIX8DbkbDYSuLv9uZeeg4NwP1vlOqvSaZvN4,7183
|
473
475
|
reconcile/test/test_prometheus_rules_tester.py,sha256=Qc9J4k0lSVie361lGr_cOy0EaBTD5LDqGZf7CYVFKr8,5677
|
@@ -556,6 +558,7 @@ reconcile/typed_queries/namespaces.py,sha256=vItPrn7sfcHOix-VvkzQkf54_ljzI_ymyxh
|
|
556
558
|
reconcile/typed_queries/namespaces_minimal.py,sha256=rUtqNQ0ORXXUTQfnpsMURymAJ4gYtE77V-Lb3LiJFEY,278
|
557
559
|
reconcile/typed_queries/pagerduty_instances.py,sha256=QCHqEAakiH6eSob0Pnnn3IBd8Ga0zpEp1Z6Qu3v2uH4,733
|
558
560
|
reconcile/typed_queries/repos.py,sha256=RKBsf7IDS6NsXTtXxJ9Ol9G3bxG9sr3vW9QQ2bahEHo,512
|
561
|
+
reconcile/typed_queries/reserved_networks.py,sha256=SWukbbEeW6acyP89v0DYd1WgbcBlUDuo-y3e27eN_vs,390
|
559
562
|
reconcile/typed_queries/saas_files.py,sha256=4b6zhb5-y7HUyn9DDkJ9CRpvg7N-PnH6gtXtHyd-rzo,14136
|
560
563
|
reconcile/typed_queries/slo_documents.py,sha256=x2dg0cnMET-ImARzhDg7Q81MA9Zlm9alH8Rp5XkVR6s,407
|
561
564
|
reconcile/typed_queries/smtp.py,sha256=aSLglYa5bHKmlGwKkxq2RZqyMWuAf0a4S_mOuhDa084,542
|
@@ -743,7 +746,7 @@ tools/app_interface_metrics_exporter.py,sha256=zkwkxdAUAxjdc-pzx2_oJXG25fo0Fnyd5
|
|
743
746
|
tools/app_interface_reporter.py,sha256=upA-J-n-HXHKVDINRuMR7vTt-iJvQORKUVi9D3leQto,17738
|
744
747
|
tools/glitchtip_access_reporter.py,sha256=oPBnk_YoDuljU3v0FaChzOwwnk4vap1xEE67QEjzdqs,2948
|
745
748
|
tools/glitchtip_access_revalidation.py,sha256=8kbBJk04mkq28kWoRDDkfCGIF3GRg3pJrFAh1sW0dbk,2821
|
746
|
-
tools/qontract_cli.py,sha256=
|
749
|
+
tools/qontract_cli.py,sha256=v2kmMkmtM2Rep0nJ2pKHTGnFOx7R2yKgD8_AdRD8tT4,113417
|
747
750
|
tools/sd_app_sre_alert_report.py,sha256=e9vAdyenUz2f5c8-z-5WY0wv-SJ9aePKDH2r4IwB6pc,5063
|
748
751
|
tools/template_validation.py,sha256=-U-lTGeLaci8yWPEblCJeev2DOlY1jM9QOOh-O1zts8,3376
|
749
752
|
tools/cli_commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -761,8 +764,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
|
|
761
764
|
tools/test/test_qontract_cli.py,sha256=UEwAW7PA_GIrbqzaLxpkCxbuVjEFLNvnVG-6VyoCGIc,4147
|
762
765
|
tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
|
763
766
|
tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
|
764
|
-
qontract_reconcile-0.10.
|
765
|
-
qontract_reconcile-0.10.
|
766
|
-
qontract_reconcile-0.10.
|
767
|
-
qontract_reconcile-0.10.
|
768
|
-
qontract_reconcile-0.10.
|
767
|
+
qontract_reconcile-0.10.1rc710.dist-info/METADATA,sha256=vTg4hBYIAZQpJjjtLFoFZ8NJTlr0QSW2vZuxSUecHKU,2382
|
768
|
+
qontract_reconcile-0.10.1rc710.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
769
|
+
qontract_reconcile-0.10.1rc710.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
|
770
|
+
qontract_reconcile-0.10.1rc710.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
771
|
+
qontract_reconcile-0.10.1rc710.dist-info/RECORD,,
|
@@ -0,0 +1,94 @@
|
|
1
|
+
"""
|
2
|
+
Generated by qenerate plugin=pydantic_v1. DO NOT MODIFY MANUALLY!
|
3
|
+
"""
|
4
|
+
from collections.abc import Callable # noqa: F401 # pylint: disable=W0611
|
5
|
+
from datetime import datetime # noqa: F401 # pylint: disable=W0611
|
6
|
+
from enum import Enum # noqa: F401 # pylint: disable=W0611
|
7
|
+
from typing import ( # noqa: F401 # pylint: disable=W0611
|
8
|
+
Any,
|
9
|
+
Optional,
|
10
|
+
Union,
|
11
|
+
)
|
12
|
+
|
13
|
+
from pydantic import ( # noqa: F401 # pylint: disable=W0611
|
14
|
+
BaseModel,
|
15
|
+
Extra,
|
16
|
+
Field,
|
17
|
+
Json,
|
18
|
+
)
|
19
|
+
|
20
|
+
|
21
|
+
DEFINITION = """
|
22
|
+
query ReservedNetworks {
|
23
|
+
networks: network_v1 {
|
24
|
+
name
|
25
|
+
networkAddress
|
26
|
+
parentNetwork {
|
27
|
+
networkAddress
|
28
|
+
}
|
29
|
+
inUseBy {
|
30
|
+
vpc {
|
31
|
+
account {
|
32
|
+
name
|
33
|
+
uid
|
34
|
+
consoleUrl
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
"""
|
41
|
+
|
42
|
+
|
43
|
+
class ConfiguredBaseModel(BaseModel):
|
44
|
+
class Config:
|
45
|
+
smart_union=True
|
46
|
+
extra=Extra.forbid
|
47
|
+
|
48
|
+
|
49
|
+
class NetworkV1_NetworkV1(ConfiguredBaseModel):
|
50
|
+
network_address: str = Field(..., alias="networkAddress")
|
51
|
+
|
52
|
+
|
53
|
+
class AWSAccountV1(ConfiguredBaseModel):
|
54
|
+
name: str = Field(..., alias="name")
|
55
|
+
uid: str = Field(..., alias="uid")
|
56
|
+
console_url: str = Field(..., alias="consoleUrl")
|
57
|
+
|
58
|
+
|
59
|
+
class VPCRequestV1(ConfiguredBaseModel):
|
60
|
+
account: AWSAccountV1 = Field(..., alias="account")
|
61
|
+
|
62
|
+
|
63
|
+
class NetworkInUseByV1(ConfiguredBaseModel):
|
64
|
+
vpc: Optional[VPCRequestV1] = Field(..., alias="vpc")
|
65
|
+
|
66
|
+
|
67
|
+
class NetworkV1(ConfiguredBaseModel):
|
68
|
+
name: str = Field(..., alias="name")
|
69
|
+
network_address: str = Field(..., alias="networkAddress")
|
70
|
+
parent_network: Optional[NetworkV1_NetworkV1] = Field(..., alias="parentNetwork")
|
71
|
+
in_use_by: Optional[NetworkInUseByV1] = Field(..., alias="inUseBy")
|
72
|
+
|
73
|
+
|
74
|
+
class ReservedNetworksQueryData(ConfiguredBaseModel):
|
75
|
+
networks: Optional[list[NetworkV1]] = Field(..., alias="networks")
|
76
|
+
|
77
|
+
|
78
|
+
def query(query_func: Callable, **kwargs: Any) -> ReservedNetworksQueryData:
|
79
|
+
"""
|
80
|
+
This is a convenience function which queries and parses the data into
|
81
|
+
concrete types. It should be compatible with most GQL clients.
|
82
|
+
You do not have to use it to consume the generated data classes.
|
83
|
+
Alternatively, you can also mime and alternate the behavior
|
84
|
+
of this function in the caller.
|
85
|
+
|
86
|
+
Parameters:
|
87
|
+
query_func (Callable): Function which queries your GQL Server
|
88
|
+
kwargs: optional arguments that will be passed to the query function
|
89
|
+
|
90
|
+
Returns:
|
91
|
+
ReservedNetworksQueryData: queried data parsed into generated classes
|
92
|
+
"""
|
93
|
+
raw_data: dict[Any, Any] = query_func(DEFINITION, **kwargs)
|
94
|
+
return ReservedNetworksQueryData(**raw_data)
|
@@ -12,6 +12,9 @@ from typing import (
|
|
12
12
|
|
13
13
|
from dateutil import parser
|
14
14
|
|
15
|
+
from reconcile.gql_definitions.fragments.pipeline_provider_retention import (
|
16
|
+
PipelineProviderRetention,
|
17
|
+
)
|
15
18
|
from reconcile.typed_queries.app_interface_vault_settings import (
|
16
19
|
get_app_interface_vault_settings,
|
17
20
|
)
|
@@ -30,15 +33,36 @@ QONTRACT_INTEGRATION = "openshift-saas-deploy-trigger-cleaner"
|
|
30
33
|
QONTRACT_INTEGRATION_VERSION = make_semver(0, 1, 0)
|
31
34
|
|
32
35
|
|
33
|
-
def within_retention_days(
|
36
|
+
def within_retention_days(
|
37
|
+
resource: dict[str, Any], days: int, now_date: datetime
|
38
|
+
) -> bool:
|
34
39
|
metadata = resource["metadata"]
|
35
40
|
creation_date = parser.parse(metadata["creationTimestamp"])
|
36
|
-
now_date = datetime.now(timezone.utc)
|
37
41
|
interval = now_date.timestamp() - creation_date.timestamp()
|
38
42
|
|
39
43
|
return interval < timedelta(days=days).total_seconds()
|
40
44
|
|
41
45
|
|
46
|
+
def get_pipeline_runs_to_delete(
|
47
|
+
pipeline_runs: list[dict[str, Any]],
|
48
|
+
retention: PipelineProviderRetention,
|
49
|
+
now_date: datetime,
|
50
|
+
) -> list[dict[str, Any]]:
|
51
|
+
pipeline_runs_to_delete = []
|
52
|
+
if retention.minimum:
|
53
|
+
pipeline_runs = pipeline_runs[retention.minimum :]
|
54
|
+
elif retention.maximum:
|
55
|
+
pipeline_runs_to_delete = pipeline_runs[retention.maximum :]
|
56
|
+
pipeline_runs = pipeline_runs[: retention.maximum]
|
57
|
+
|
58
|
+
for pr in pipeline_runs:
|
59
|
+
if retention.days and within_retention_days(pr, retention.days, now_date):
|
60
|
+
continue
|
61
|
+
pipeline_runs_to_delete.append(pr)
|
62
|
+
|
63
|
+
return pipeline_runs_to_delete
|
64
|
+
|
65
|
+
|
42
66
|
@defer
|
43
67
|
def run(
|
44
68
|
dry_run: bool,
|
@@ -47,6 +71,7 @@ def run(
|
|
47
71
|
use_jump_host: bool = True,
|
48
72
|
defer: Optional[Callable] = None,
|
49
73
|
) -> None:
|
74
|
+
now_date = datetime.now(timezone.utc)
|
50
75
|
vault_settings = get_app_interface_vault_settings()
|
51
76
|
secret_reader = create_secret_reader(use_vault=vault_settings.vault)
|
52
77
|
pipeline_providers = get_tekton_pipeline_providers()
|
@@ -77,14 +102,8 @@ def run(
|
|
77
102
|
reverse=True,
|
78
103
|
)
|
79
104
|
|
80
|
-
|
81
|
-
pipeline_runs = pipeline_runs[pp.retention.minimum :]
|
82
|
-
|
83
|
-
for pr in pipeline_runs:
|
105
|
+
for pr in get_pipeline_runs_to_delete(pipeline_runs, pp.retention, now_date):
|
84
106
|
name = pr["metadata"]["name"]
|
85
|
-
if pp.retention.days and within_retention_days(pr, pp.retention.days):
|
86
|
-
continue
|
87
|
-
|
88
107
|
logging.info([
|
89
108
|
"delete_trigger",
|
90
109
|
pp.namespace.cluster.name,
|
@@ -0,0 +1,65 @@
|
|
1
|
+
from datetime import datetime, timezone
|
2
|
+
from typing import Any
|
3
|
+
|
4
|
+
import pytest
|
5
|
+
|
6
|
+
from reconcile.gql_definitions.fragments.pipeline_provider_retention import (
|
7
|
+
PipelineProviderRetention,
|
8
|
+
)
|
9
|
+
from reconcile.openshift_saas_deploy_trigger_cleaner import get_pipeline_runs_to_delete
|
10
|
+
|
11
|
+
from .fixtures import Fixtures
|
12
|
+
|
13
|
+
fxt = Fixtures("openshift_saas_deploy_trigger_cleaner")
|
14
|
+
|
15
|
+
|
16
|
+
@pytest.fixture
|
17
|
+
def now() -> datetime:
|
18
|
+
return datetime(2024, 4, 4, 0, 0, 0, 0, tzinfo=timezone.utc)
|
19
|
+
|
20
|
+
|
21
|
+
# A fixture simulating the output of getting PipelineRuns from a namespace, simplified
|
22
|
+
# as it contains only the fields relevant for get_pipeline_runs_to_delete, reversed
|
23
|
+
# sorted by creationTimestamp
|
24
|
+
@pytest.fixture
|
25
|
+
def pipeline_runs() -> list[dict[str, Any]]:
|
26
|
+
return fxt.get_anymarkup("pipeline_runs.yaml")
|
27
|
+
|
28
|
+
|
29
|
+
# No min/max settings, we go with whatever "days" says
|
30
|
+
def test_days(now: datetime, pipeline_runs: list[dict[str, Any]]) -> None:
|
31
|
+
retention = PipelineProviderRetention(days=1, minimum=None, maximum=None)
|
32
|
+
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 4
|
33
|
+
|
34
|
+
retention = PipelineProviderRetention(days=2, minimum=None, maximum=None)
|
35
|
+
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 2
|
36
|
+
|
37
|
+
|
38
|
+
# Minimum set, it takes precedence over "days"
|
39
|
+
def test_days_and_minimum(now: datetime, pipeline_runs: list[dict[str, Any]]) -> None:
|
40
|
+
retention = PipelineProviderRetention(days=1, minimum=5, maximum=None)
|
41
|
+
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 1
|
42
|
+
# We would have removed four from the "days" setting, we can only remove one
|
43
|
+
|
44
|
+
retention = PipelineProviderRetention(days=1, minimum=3, maximum=None)
|
45
|
+
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 3
|
46
|
+
# We would have removed four from the "days" setting, we can only remove three
|
47
|
+
|
48
|
+
retention = PipelineProviderRetention(days=1, minimum=1, maximum=None)
|
49
|
+
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 4
|
50
|
+
# Removing 4 we still have two, we're fine.
|
51
|
+
|
52
|
+
|
53
|
+
# Maximum set, it takes precedence over "days"
|
54
|
+
def test_days_and_maximum(now: datetime, pipeline_runs: list[dict[str, Any]]) -> None:
|
55
|
+
retention = PipelineProviderRetention(days=1, minimum=None, maximum=1)
|
56
|
+
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 5
|
57
|
+
# we have a max of 1, no matter what "days" says.
|
58
|
+
|
59
|
+
retention = PipelineProviderRetention(days=1, minimum=None, maximum=3)
|
60
|
+
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 4
|
61
|
+
# by removing 4 we comply with the max setting of three.
|
62
|
+
|
63
|
+
retention = PipelineProviderRetention(days=2, minimum=None, maximum=3)
|
64
|
+
assert len(get_pipeline_runs_to_delete(pipeline_runs, retention, now)) == 3
|
65
|
+
# We would have remove only two following "days", but max tells us otherwise.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
3
|
+
from reconcile.gql_definitions.common.reserved_networks import (
|
4
|
+
NetworkV1,
|
5
|
+
query,
|
6
|
+
)
|
7
|
+
from reconcile.utils import gql
|
8
|
+
from reconcile.utils.gql import GqlApi
|
9
|
+
|
10
|
+
|
11
|
+
def get_networks(gql_api: Optional[GqlApi] = None) -> list[NetworkV1]:
|
12
|
+
api = gql_api if gql_api else gql.get_api()
|
13
|
+
data = query(query_func=api.query)
|
14
|
+
return list(data.networks or [])
|
tools/qontract_cli.py
CHANGED
@@ -974,6 +974,52 @@ def clusters_network(ctx, name):
|
|
974
974
|
print_output(ctx.obj["options"], clusters, columns)
|
975
975
|
|
976
976
|
|
977
|
+
@get.command()
|
978
|
+
@click.pass_context
|
979
|
+
def network_reservations(ctx) -> None:
|
980
|
+
from reconcile.typed_queries.reserved_networks import get_networks
|
981
|
+
|
982
|
+
columns = [
|
983
|
+
"name",
|
984
|
+
"network Address",
|
985
|
+
"parent Network",
|
986
|
+
"Account Name",
|
987
|
+
"Account UID",
|
988
|
+
"Console Login URL",
|
989
|
+
]
|
990
|
+
network_table = []
|
991
|
+
|
992
|
+
def md_link(url) -> str:
|
993
|
+
if ctx.obj["options"]["output"] == "md":
|
994
|
+
return f"[{url}]({url})"
|
995
|
+
else:
|
996
|
+
return url
|
997
|
+
|
998
|
+
for network in get_networks():
|
999
|
+
parentAddress = "none"
|
1000
|
+
if network.parent_network:
|
1001
|
+
parentAddress = network.parent_network.network_address
|
1002
|
+
if network.in_use_by and network.in_use_by.vpc:
|
1003
|
+
network_table.append({
|
1004
|
+
"name": network.name,
|
1005
|
+
"network Address": network.network_address,
|
1006
|
+
"parent Network": parentAddress,
|
1007
|
+
"Account Name": network.in_use_by.vpc.account.name,
|
1008
|
+
"Account UID": network.in_use_by.vpc.account.uid,
|
1009
|
+
"Console Login URL": md_link(network.in_use_by.vpc.account.console_url),
|
1010
|
+
})
|
1011
|
+
else:
|
1012
|
+
network_table.append({
|
1013
|
+
"name": network.name,
|
1014
|
+
"network Address": network.network_address,
|
1015
|
+
"parent Network": parentAddress,
|
1016
|
+
"Account Name": "Unclaimed network",
|
1017
|
+
"Account UID": "Unclaimed network",
|
1018
|
+
"Console Login URL": "Unclaimed network",
|
1019
|
+
})
|
1020
|
+
print_output(ctx.obj["options"], network_table, columns)
|
1021
|
+
|
1022
|
+
|
977
1023
|
@get.command()
|
978
1024
|
@click.pass_context
|
979
1025
|
def cidr_blocks(ctx) -> None:
|
File without changes
|
File without changes
|
{qontract_reconcile-0.10.1rc708.dist-info → qontract_reconcile-0.10.1rc710.dist-info}/top_level.txt
RENAMED
File without changes
|