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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qontract-reconcile
3
- Version: 0.10.1rc708
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
@@ -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=aT8wqoXGyZEeXUA7Q6reaL9v5j5UnPLoYVe70D31HUg,2917
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=AmEgemURPRQhsleaVbwxmEcbuymC6SH_3DO09sHl-b0,9115
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=hjqsTf95evcZn3BBKpF9dUJVBhpy2tq6r_rEbaF6cy4,757
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=AdOUq_74y-s1nDbF6Yh0z1sTQ1r8yS3nPG9yP-slWfE,111846
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.1rc708.dist-info/METADATA,sha256=jj1NGE9JNFWbhjQyp5dY0QHogw8JrqpK0_hKDkxtbUU,2382
765
- qontract_reconcile-0.10.1rc708.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
766
- qontract_reconcile-0.10.1rc708.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
767
- qontract_reconcile-0.10.1rc708.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
768
- qontract_reconcile-0.10.1rc708.dist-info/RECORD,,
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,,
@@ -39,6 +39,7 @@ fragment CommonJumphostFields on ClusterJumpHost_v1 {
39
39
  fragment PipelineProviderRetention on PipelinesProviderRetention_v1 {
40
40
  days
41
41
  minimum
42
+ maximum
42
43
  }
43
44
 
44
45
  fragment ResourceLimitsRequirements on ResourceLimitsRequirements_v1 {
@@ -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)
@@ -27,3 +27,4 @@ class ConfiguredBaseModel(BaseModel):
27
27
  class PipelineProviderRetention(ConfiguredBaseModel):
28
28
  days: Optional[int] = Field(..., alias="days")
29
29
  minimum: Optional[int] = Field(..., alias="minimum")
30
+ maximum: Optional[int] = Field(..., alias="maximum")
@@ -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(resource: dict[str, Any], days: int) -> bool:
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
- if pp.retention.minimum:
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: