qontract-reconcile 0.10.1rc879__py3-none-any.whl → 0.10.1rc894__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.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/RECORD +291 -284
- reconcile/acs_rbac.py +1 -2
- reconcile/aus/advanced_upgrade_service.py +14 -14
- reconcile/aus/aus_label_source.py +1 -2
- reconcile/aus/base.py +23 -26
- reconcile/aus/cluster_version_data.py +4 -4
- reconcile/aus/models.py +2 -3
- reconcile/aus/version_gate_approver.py +2 -6
- reconcile/aus/version_gates/__init__.py +1 -3
- reconcile/aus/version_gates/sts_version_gate_handler.py +2 -3
- reconcile/aws_account_manager/integration.py +9 -14
- reconcile/aws_account_manager/reconciler.py +51 -1
- reconcile/aws_account_manager/utils.py +3 -0
- reconcile/aws_ami_cleanup/integration.py +3 -4
- reconcile/aws_iam_password_reset.py +2 -5
- reconcile/aws_version_sync/integration.py +2 -2
- reconcile/blackbox_exporter_endpoint_monitoring.py +2 -5
- reconcile/change_owners/approver.py +4 -5
- reconcile/change_owners/bundle.py +20 -22
- reconcile/change_owners/change_types.py +23 -24
- reconcile/change_owners/changes.py +13 -16
- reconcile/change_owners/decision.py +2 -5
- reconcile/change_owners/diff.py +11 -15
- reconcile/change_owners/self_service_roles.py +1 -2
- reconcile/change_owners/tester.py +7 -10
- reconcile/checkpoint.py +2 -5
- reconcile/cli.py +26 -12
- reconcile/closedbox_endpoint_monitoring_base.py +8 -11
- reconcile/cluster_deployment_mapper.py +2 -5
- reconcile/cna/assets/asset.py +4 -7
- reconcile/cna/assets/null.py +2 -5
- reconcile/cna/integration.py +2 -3
- reconcile/cna/state.py +2 -5
- reconcile/dashdotdb_base.py +8 -11
- reconcile/dashdotdb_cso.py +3 -6
- reconcile/dashdotdb_dora.py +10 -14
- reconcile/dashdotdb_dvo.py +10 -13
- reconcile/dashdotdb_slo.py +5 -8
- reconcile/database_access_manager.py +5 -6
- reconcile/dynatrace_token_provider/integration.py +3 -6
- reconcile/dynatrace_token_provider/integration_v2.py +20 -0
- reconcile/dynatrace_token_provider/meta.py +1 -0
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +4 -4
- reconcile/external_resources/model.py +3 -3
- reconcile/external_resources/secrets_sync.py +5 -5
- reconcile/external_resources/state.py +5 -5
- reconcile/gabi_authorized_users.py +3 -6
- reconcile/gcr_mirror.py +1 -1
- reconcile/github_org.py +1 -3
- reconcile/github_repo_invites.py +2 -5
- reconcile/gitlab_housekeeping.py +7 -11
- reconcile/gitlab_labeler.py +1 -2
- reconcile/gitlab_members.py +2 -5
- reconcile/gitlab_permissions.py +1 -3
- reconcile/glitchtip/integration.py +5 -8
- reconcile/glitchtip_project_alerts/integration.py +57 -33
- reconcile/glitchtip_project_dsn/integration.py +8 -11
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +6 -0
- reconcile/gql_definitions/fragments/aws_account_managed.py +8 -0
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +4 -4
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +27 -7
- reconcile/integrations_manager.py +5 -8
- reconcile/jenkins/types.py +5 -6
- reconcile/jenkins_job_builder.py +9 -12
- reconcile/jenkins_roles.py +1 -1
- reconcile/jira_watcher.py +2 -2
- reconcile/ldap_groups/integration.py +2 -5
- reconcile/ocm/types.py +21 -26
- reconcile/ocm_addons_upgrade_tests_trigger.py +3 -6
- reconcile/ocm_clusters.py +8 -8
- reconcile/ocm_internal_notifications/integration.py +1 -2
- reconcile/ocm_labels/integration.py +2 -5
- reconcile/ocm_machine_pools.py +11 -15
- reconcile/ocm_upgrade_scheduler_org_updater.py +2 -5
- reconcile/openshift_base.py +29 -30
- reconcile/openshift_groups.py +15 -20
- reconcile/openshift_namespace_labels.py +8 -14
- reconcile/openshift_namespaces.py +5 -8
- reconcile/openshift_network_policies.py +2 -4
- reconcile/openshift_resources_base.py +19 -29
- reconcile/openshift_saas_deploy.py +9 -10
- reconcile/openshift_saas_deploy_change_tester.py +7 -10
- reconcile/openshift_saas_deploy_trigger_base.py +4 -7
- reconcile/openshift_saas_deploy_trigger_cleaner.py +5 -8
- reconcile/openshift_saas_deploy_trigger_configs.py +1 -2
- reconcile/openshift_saas_deploy_trigger_images.py +1 -2
- reconcile/openshift_saas_deploy_trigger_moving_commits.py +1 -2
- reconcile/openshift_saas_deploy_trigger_upstream_jobs.py +1 -2
- reconcile/openshift_tekton_resources.py +7 -11
- reconcile/openshift_upgrade_watcher.py +10 -13
- reconcile/openshift_users.py +8 -11
- reconcile/oum/base.py +3 -4
- reconcile/oum/labelset.py +1 -2
- reconcile/oum/metrics.py +2 -2
- reconcile/oum/models.py +1 -2
- reconcile/oum/standalone.py +2 -3
- reconcile/prometheus_rules_tester/integration.py +6 -9
- reconcile/quay_membership.py +1 -2
- reconcile/quay_mirror.py +12 -13
- reconcile/quay_mirror_org.py +10 -10
- reconcile/queries.py +4 -7
- reconcile/resource_scraper.py +3 -4
- reconcile/rhidp/common.py +2 -2
- reconcile/saas_auto_promotions_manager/integration.py +5 -6
- reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py +1 -2
- reconcile/saas_auto_promotions_manager/publisher.py +5 -6
- reconcile/saas_auto_promotions_manager/subscriber.py +36 -15
- reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +8 -0
- reconcile/saas_file_validator.py +2 -5
- reconcile/signalfx_endpoint_monitoring.py +2 -5
- reconcile/skupper_network/integration.py +3 -6
- reconcile/skupper_network/models.py +3 -5
- reconcile/slack_base.py +4 -7
- reconcile/slack_usergroups.py +15 -17
- reconcile/sql_query.py +5 -9
- reconcile/status_board.py +4 -5
- reconcile/statuspage/atlassian.py +14 -15
- reconcile/statuspage/integrations/maintenances.py +3 -3
- reconcile/statuspage/page.py +8 -8
- reconcile/statuspage/state.py +4 -5
- reconcile/statuspage/status.py +7 -8
- reconcile/templating/lib/rendering.py +8 -8
- reconcile/templating/renderer.py +10 -11
- reconcile/templating/validator.py +4 -4
- reconcile/terraform_aws_route53.py +3 -6
- reconcile/terraform_cloudflare_dns.py +9 -12
- reconcile/terraform_cloudflare_resources.py +9 -11
- reconcile/terraform_cloudflare_users.py +8 -11
- reconcile/terraform_init/integration.py +2 -2
- reconcile/terraform_repo.py +11 -14
- reconcile/terraform_resources.py +20 -21
- reconcile/terraform_tgw_attachments.py +32 -36
- reconcile/terraform_users.py +6 -7
- reconcile/terraform_vpc_resources/integration.py +6 -6
- reconcile/test/conftest.py +7 -10
- reconcile/test/fixtures.py +1 -1
- reconcile/test/saas_auto_promotions_manager/conftest.py +3 -2
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +2 -2
- reconcile/test/test_database_access_manager.py +3 -6
- reconcile/test/test_gitlab_labeler.py +2 -5
- reconcile/test/test_jump_host.py +5 -8
- reconcile/test/test_ocm_machine_pools.py +1 -4
- reconcile/test/test_openshift_base.py +3 -6
- reconcile/test/test_openshift_cluster_bots.py +5 -5
- reconcile/test/test_openshift_namespace_labels.py +2 -3
- reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py +2 -2
- reconcile/test/test_saasherder.py +9 -12
- reconcile/test/test_slack_base.py +4 -6
- reconcile/test/test_status_board.py +4 -7
- reconcile/test/test_terraform_tgw_attachments.py +14 -20
- reconcile/typed_queries/alerting_services_settings.py +1 -2
- reconcile/typed_queries/app_interface_custom_messages.py +2 -3
- reconcile/typed_queries/app_interface_deadmanssnitch_settings.py +1 -3
- reconcile/typed_queries/app_interface_repo_url.py +1 -2
- reconcile/typed_queries/app_interface_state_settings.py +1 -3
- reconcile/typed_queries/app_interface_vault_settings.py +1 -2
- reconcile/typed_queries/aws_vpc_requests.py +1 -3
- reconcile/typed_queries/aws_vpcs.py +1 -3
- reconcile/typed_queries/clusters.py +2 -4
- reconcile/typed_queries/clusters_minimal.py +1 -3
- reconcile/typed_queries/clusters_with_dms.py +1 -3
- reconcile/typed_queries/dynatrace_environments.py +14 -0
- reconcile/typed_queries/external_resources.py +3 -4
- reconcile/typed_queries/pagerduty_instances.py +1 -2
- reconcile/typed_queries/repos.py +2 -3
- reconcile/typed_queries/reserved_networks.py +1 -3
- reconcile/typed_queries/saas_files.py +49 -59
- reconcile/typed_queries/slo_documents.py +1 -3
- reconcile/typed_queries/status_board.py +3 -7
- reconcile/typed_queries/tekton_pipeline_providers.py +1 -2
- reconcile/typed_queries/terraform_namespaces.py +1 -2
- reconcile/typed_queries/terraform_tgw_attachments/aws_accounts.py +1 -3
- reconcile/utils/acs/base.py +2 -3
- reconcile/utils/acs/notifiers.py +3 -3
- reconcile/utils/acs/policies.py +3 -3
- reconcile/utils/aggregated_list.py +1 -1
- reconcile/utils/amtool.py +1 -2
- reconcile/utils/aws_api.py +28 -31
- reconcile/utils/aws_api_typed/account.py +23 -0
- reconcile/utils/aws_api_typed/api.py +20 -9
- reconcile/utils/binary.py +1 -3
- reconcile/utils/clusterhealth/providerbase.py +1 -2
- reconcile/utils/clusterhealth/telemeter.py +2 -2
- reconcile/utils/deadmanssnitch_api.py +1 -2
- reconcile/utils/disabled_integrations.py +4 -6
- reconcile/utils/environ.py +1 -1
- reconcile/utils/expiration.py +3 -7
- reconcile/utils/external_resource_spec.py +3 -4
- reconcile/utils/external_resources.py +4 -7
- reconcile/utils/filtering.py +1 -2
- reconcile/utils/git.py +3 -9
- reconcile/utils/git_secrets.py +5 -5
- reconcile/utils/github_api.py +5 -9
- reconcile/utils/gitlab_api.py +2 -3
- reconcile/utils/glitchtip/client.py +2 -4
- reconcile/utils/glitchtip/models.py +8 -11
- reconcile/utils/gql.py +26 -35
- reconcile/utils/grouping.py +1 -3
- reconcile/utils/imap_client.py +2 -5
- reconcile/utils/internal_groups/client.py +1 -2
- reconcile/utils/internal_groups/models.py +8 -9
- reconcile/utils/jenkins_api.py +4 -4
- reconcile/utils/jinja2/extensions.py +1 -1
- reconcile/utils/jinja2/filters.py +4 -4
- reconcile/utils/jinja2/utils.py +16 -16
- reconcile/utils/jira_client.py +10 -11
- reconcile/utils/jjb_client.py +14 -17
- reconcile/utils/jobcontroller/controller.py +5 -5
- reconcile/utils/jobcontroller/models.py +2 -2
- reconcile/utils/jsonpath.py +4 -5
- reconcile/utils/jump_host.py +7 -8
- reconcile/utils/keycloak.py +3 -7
- reconcile/utils/ldap_client.py +2 -3
- reconcile/utils/lean_terraform_client.py +13 -17
- reconcile/utils/membershipsources/app_interface_resolver.py +1 -1
- reconcile/utils/membershipsources/models.py +19 -22
- reconcile/utils/metrics.py +13 -15
- reconcile/utils/mr/base.py +7 -11
- reconcile/utils/mr/glitchtip_access_reporter.py +2 -2
- reconcile/utils/mr/notificator.py +1 -2
- reconcile/utils/oc.py +38 -38
- reconcile/utils/oc_connection_parameters.py +24 -25
- reconcile/utils/oc_filters.py +2 -3
- reconcile/utils/oc_map.py +9 -15
- reconcile/utils/ocm/addons.py +7 -10
- reconcile/utils/ocm/base.py +38 -39
- reconcile/utils/ocm/clusters.py +6 -9
- reconcile/utils/ocm/label_sources.py +1 -2
- reconcile/utils/ocm/labels.py +3 -6
- reconcile/utils/ocm/ocm.py +11 -14
- reconcile/utils/ocm/products.py +1 -3
- reconcile/utils/ocm/search_filters.py +16 -17
- reconcile/utils/ocm/service_log.py +2 -3
- reconcile/utils/ocm/sre_capability_labels.py +4 -8
- reconcile/utils/ocm/subscriptions.py +1 -3
- reconcile/utils/ocm/syncsets.py +2 -4
- reconcile/utils/ocm/upgrades.py +5 -9
- reconcile/utils/ocm_base_client.py +13 -16
- reconcile/utils/openshift_resource.py +5 -11
- reconcile/utils/output.py +2 -3
- reconcile/utils/pagerduty_api.py +4 -5
- reconcile/utils/prometheus.py +2 -2
- reconcile/utils/promotion_state.py +4 -5
- reconcile/utils/promtool.py +2 -8
- reconcile/utils/quay_api.py +12 -22
- reconcile/utils/raw_github_api.py +3 -5
- reconcile/utils/rosa/rosa_cli.py +6 -6
- reconcile/utils/rosa/session.py +6 -7
- reconcile/utils/runtime/desired_state_diff.py +3 -8
- reconcile/utils/runtime/environment.py +4 -7
- reconcile/utils/runtime/integration.py +4 -4
- reconcile/utils/runtime/meta.py +1 -2
- reconcile/utils/runtime/runner.py +7 -10
- reconcile/utils/runtime/sharding.py +22 -27
- reconcile/utils/saasherder/interfaces.py +63 -69
- reconcile/utils/saasherder/models.py +30 -35
- reconcile/utils/saasherder/saasherder.py +39 -54
- reconcile/utils/secret_reader.py +17 -19
- reconcile/utils/slack_api.py +15 -17
- reconcile/utils/smtp_client.py +1 -2
- reconcile/utils/sqs_gateway.py +1 -3
- reconcile/utils/state.py +1 -2
- reconcile/utils/terraform/config_client.py +4 -5
- reconcile/utils/terraform_client.py +12 -8
- reconcile/utils/terrascript/cloudflare_client.py +4 -10
- reconcile/utils/terrascript/cloudflare_resources.py +10 -13
- reconcile/utils/terrascript/models.py +2 -3
- reconcile/utils/terrascript/resources.py +1 -2
- reconcile/utils/terrascript_aws_client.py +50 -38
- reconcile/utils/unleash/client.py +4 -7
- reconcile/utils/unleash/server.py +2 -2
- reconcile/utils/vault.py +8 -11
- reconcile/utils/vaultsecretref.py +2 -3
- reconcile/utils/vcs.py +7 -8
- reconcile/vault_replication.py +4 -8
- reconcile/vpc_peerings_validator.py +4 -9
- release/version.py +6 -7
- tools/app_interface_reporter.py +2 -2
- tools/cli_commands/gpg_encrypt.py +3 -6
- tools/cli_commands/systems_and_tools.py +4 -7
- tools/qontract_cli.py +105 -17
- tools/saas_promotion_state/__init__.py +0 -0
- tools/saas_promotion_state/saas_promotion_state.py +105 -0
- tools/template_validation.py +1 -1
- tools/test/conftest.py +45 -6
- tools/test/test_saas_promotion_state.py +187 -0
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/top_level.txt +0 -0
reconcile/utils/ocm/clusters.py
CHANGED
@@ -4,10 +4,7 @@ from collections.abc import (
|
|
4
4
|
Iterable,
|
5
5
|
)
|
6
6
|
from functools import lru_cache
|
7
|
-
from typing import
|
8
|
-
Any,
|
9
|
-
Optional,
|
10
|
-
)
|
7
|
+
from typing import Any
|
11
8
|
|
12
9
|
from reconcile.utils.ocm.base import (
|
13
10
|
ACTIVE_SUBSCRIPTION_STATES,
|
@@ -96,7 +93,7 @@ def discover_clusters_by_labels(
|
|
96
93
|
def discover_clusters_for_subscriptions(
|
97
94
|
ocm_api: OCMBaseClient,
|
98
95
|
subscription_ids: list[str],
|
99
|
-
cluster_filter:
|
96
|
+
cluster_filter: Filter | None = None,
|
100
97
|
) -> list[ClusterDetails]:
|
101
98
|
"""
|
102
99
|
Discover clusters by filtering on their subscription IDs.
|
@@ -118,7 +115,7 @@ def discover_clusters_for_subscriptions(
|
|
118
115
|
def discover_clusters_for_organizations(
|
119
116
|
ocm_api: OCMBaseClient,
|
120
117
|
organization_ids: Iterable[str],
|
121
|
-
cluster_filter:
|
118
|
+
cluster_filter: Filter | None = None,
|
122
119
|
) -> list[ClusterDetails]:
|
123
120
|
"""
|
124
121
|
Discover clusters by filtering on their organization IDs.
|
@@ -151,8 +148,8 @@ def get_ocm_clusters(
|
|
151
148
|
|
152
149
|
def get_cluster_details_for_subscriptions(
|
153
150
|
ocm_api: OCMBaseClient,
|
154
|
-
subscription_filter:
|
155
|
-
cluster_filter:
|
151
|
+
subscription_filter: Filter | None = None,
|
152
|
+
cluster_filter: Filter | None = None,
|
156
153
|
init_labels: bool = False,
|
157
154
|
) -> Generator[ClusterDetails, None, None]:
|
158
155
|
"""
|
@@ -227,7 +224,7 @@ def get_node_pools(ocm_api: OCMBaseClient, cluster_id: str) -> list[dict[str, An
|
|
227
224
|
return results
|
228
225
|
|
229
226
|
|
230
|
-
@lru_cache
|
227
|
+
@lru_cache
|
231
228
|
def get_version(ocm_api: OCMBaseClient, version: str) -> dict[str, Any]:
|
232
229
|
api = f"/api/clusters_mgmt/v1/versions/{version}"
|
233
230
|
|
@@ -3,13 +3,12 @@ from abc import (
|
|
3
3
|
abstractmethod,
|
4
4
|
)
|
5
5
|
from dataclasses import dataclass
|
6
|
-
from typing import Optional
|
7
6
|
|
8
7
|
|
9
8
|
@dataclass(frozen=True)
|
10
9
|
class LabelOwnerRef(ABC):
|
11
10
|
ocm_env: str
|
12
|
-
label_container_href:
|
11
|
+
label_container_href: str | None
|
13
12
|
|
14
13
|
@abstractmethod
|
15
14
|
def identity_labels(self) -> list[str]:
|
reconcile/utils/ocm/labels.py
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
from collections import defaultdict
|
2
2
|
from collections.abc import Generator
|
3
|
-
from typing import
|
4
|
-
Any,
|
5
|
-
Optional,
|
6
|
-
)
|
3
|
+
from typing import Any
|
7
4
|
|
8
5
|
from reconcile.utils.ocm.base import (
|
9
6
|
LabelContainer,
|
@@ -171,7 +168,7 @@ def build_container_for_prefix(
|
|
171
168
|
)
|
172
169
|
|
173
170
|
|
174
|
-
def label_filter(key: str, value:
|
171
|
+
def label_filter(key: str, value: str | None = None) -> Filter:
|
175
172
|
"""
|
176
173
|
Creates a filter that matches a label with the given key and
|
177
174
|
optionally a value.
|
@@ -183,7 +180,7 @@ def label_filter(key: str, value: Optional[str] = None) -> Filter:
|
|
183
180
|
|
184
181
|
|
185
182
|
def get_org_labels(
|
186
|
-
ocm_api: OCMBaseClient, org_ids: set[str], label_filter:
|
183
|
+
ocm_api: OCMBaseClient, org_ids: set[str], label_filter: Filter | None
|
187
184
|
) -> dict[str, LabelContainer]:
|
188
185
|
"""
|
189
186
|
Fetch all labels from organizations. Optionally, label filtering can be
|
reconcile/utils/ocm/ocm.py
CHANGED
@@ -3,10 +3,7 @@ from __future__ import annotations
|
|
3
3
|
import functools
|
4
4
|
import re
|
5
5
|
from collections.abc import Mapping
|
6
|
-
from typing import
|
7
|
-
Any,
|
8
|
-
Optional,
|
9
|
-
)
|
6
|
+
from typing import Any
|
10
7
|
|
11
8
|
from sretoolbox.utils import retry
|
12
9
|
|
@@ -96,8 +93,8 @@ class OCM: # pylint: disable=too-many-public-methods
|
|
96
93
|
init_addons=False,
|
97
94
|
init_version_gates=False,
|
98
95
|
blocked_versions=None,
|
99
|
-
inheritVersionData:
|
100
|
-
product_portfolio:
|
96
|
+
inheritVersionData: list[dict[str, Any]] | None = None,
|
97
|
+
product_portfolio: OCMProductPortfolio | None = None,
|
101
98
|
):
|
102
99
|
"""Initiates access token and gets clusters information."""
|
103
100
|
self.name = name
|
@@ -174,7 +171,7 @@ class OCM: # pylint: disable=too-many-public-methods
|
|
174
171
|
return cluster in self.clusters
|
175
172
|
|
176
173
|
def get_product_impl(
|
177
|
-
self, product: str, hypershift:
|
174
|
+
self, product: str, hypershift: bool | None = False
|
178
175
|
) -> OCMProduct:
|
179
176
|
return self.product_portfolio.get_product_impl(product, hypershift)
|
180
177
|
|
@@ -255,7 +252,7 @@ class OCM: # pylint: disable=too-many-public-methods
|
|
255
252
|
)
|
256
253
|
self._delete(api)
|
257
254
|
|
258
|
-
def get_cluster_aws_account_id(self, cluster: str) ->
|
255
|
+
def get_cluster_aws_account_id(self, cluster: str) -> str | None:
|
259
256
|
"""Returns the AWS account id of the cluster.
|
260
257
|
Since there is no direct API to get this information,
|
261
258
|
we hack our way by relying on existing role grants
|
@@ -768,7 +765,7 @@ class OCM: # pylint: disable=too-many-public-methods
|
|
768
765
|
self,
|
769
766
|
cluster: str,
|
770
767
|
with_version: bool = False,
|
771
|
-
required_state:
|
768
|
+
required_state: str | None = None,
|
772
769
|
) -> list[dict[str, str]]:
|
773
770
|
"""Returns a list of Addons installed on a cluster
|
774
771
|
|
@@ -784,7 +781,7 @@ class OCM: # pylint: disable=too-many-public-methods
|
|
784
781
|
return results
|
785
782
|
api = f"{CS_API_BASE}/v1/clusters/{cluster_id}/addons"
|
786
783
|
|
787
|
-
p:
|
784
|
+
p: dict[str, Any] | None = None
|
788
785
|
if required_state:
|
789
786
|
p = {"search": f"state='{required_state}'"}
|
790
787
|
|
@@ -845,7 +842,7 @@ class OCM: # pylint: disable=too-many-public-methods
|
|
845
842
|
return rs["kind"].endswith("List")
|
846
843
|
|
847
844
|
def _get_json(
|
848
|
-
self, api: str, params:
|
845
|
+
self, api: str, params: dict[str, Any] | None = None, page_size: int = 100
|
849
846
|
) -> dict[str, Any]:
|
850
847
|
responses = []
|
851
848
|
if not params:
|
@@ -933,7 +930,7 @@ class OCMMap: # pylint: disable=too-many-public-methods
|
|
933
930
|
init_provision_shards=False,
|
934
931
|
init_addons=False,
|
935
932
|
init_version_gates=False,
|
936
|
-
product_portfolio:
|
933
|
+
product_portfolio: OCMProductPortfolio | None = None,
|
937
934
|
) -> None:
|
938
935
|
"""Initiates OCM instances for each OCM referenced in a cluster."""
|
939
936
|
self.clusters_map: dict[str, str] = {}
|
@@ -984,7 +981,7 @@ class OCMMap: # pylint: disable=too-many-public-methods
|
|
984
981
|
init_provision_shards,
|
985
982
|
init_addons,
|
986
983
|
init_version_gates,
|
987
|
-
product_portfolio:
|
984
|
+
product_portfolio: OCMProductPortfolio | None = None,
|
988
985
|
):
|
989
986
|
if self.cluster_disabled(cluster_info):
|
990
987
|
return
|
@@ -1009,7 +1006,7 @@ class OCMMap: # pylint: disable=too-many-public-methods
|
|
1009
1006
|
init_provision_shards,
|
1010
1007
|
init_addons,
|
1011
1008
|
init_version_gates,
|
1012
|
-
product_portfolio:
|
1009
|
+
product_portfolio: OCMProductPortfolio | None = None,
|
1013
1010
|
):
|
1014
1011
|
"""
|
1015
1012
|
Initiate OCM client.
|
reconcile/utils/ocm/products.py
CHANGED
@@ -5,14 +5,13 @@ from abc import (
|
|
5
5
|
from collections.abc import Iterable
|
6
6
|
from dataclasses import dataclass
|
7
7
|
from datetime import (
|
8
|
+
UTC,
|
8
9
|
datetime,
|
9
|
-
timezone,
|
10
10
|
)
|
11
11
|
from enum import Enum
|
12
12
|
from typing import (
|
13
13
|
Any,
|
14
14
|
Optional,
|
15
|
-
Union,
|
16
15
|
)
|
17
16
|
|
18
17
|
import dateparser
|
@@ -128,8 +127,8 @@ class DateRangeCondition(FilterCondition):
|
|
128
127
|
by the dateparser library is supported, e.g. "now", "today", "5 days ago"
|
129
128
|
"""
|
130
129
|
|
131
|
-
start:
|
132
|
-
end:
|
130
|
+
start: datetime | str | None
|
131
|
+
end: datetime | str | None
|
133
132
|
|
134
133
|
def copy_and_merge(self, other: "FilterCondition") -> "FilterCondition":
|
135
134
|
raise InvalidFilterError("daterange merge not supported")
|
@@ -150,7 +149,7 @@ class DateRangeCondition(FilterCondition):
|
|
150
149
|
conditions.append(f"{self.key} <= '{resolved_end.isoformat()}'")
|
151
150
|
return " and ".join(conditions)
|
152
151
|
|
153
|
-
def resolve_start(self) ->
|
152
|
+
def resolve_start(self) -> datetime | None:
|
154
153
|
"""
|
155
154
|
Resolves the start bound of the date range. If the start bound is a
|
156
155
|
string, it is parsed by the dateparser library. If it is already a
|
@@ -158,7 +157,7 @@ class DateRangeCondition(FilterCondition):
|
|
158
157
|
"""
|
159
158
|
return DateRangeCondition._resolve_date(self.start) if self.start else None
|
160
159
|
|
161
|
-
def resolve_end(self) ->
|
160
|
+
def resolve_end(self) -> datetime | None:
|
162
161
|
"""
|
163
162
|
Resolves the end bound of the date range. If the end bound is a
|
164
163
|
string, it is parsed by the dateparser library. If it is already a
|
@@ -166,7 +165,7 @@ class DateRangeCondition(FilterCondition):
|
|
166
165
|
return DateRangeCondition._resolve_date(self.end) if self.end else None
|
167
166
|
|
168
167
|
@staticmethod
|
169
|
-
def _resolve_date(date:
|
168
|
+
def _resolve_date(date: datetime | str) -> datetime:
|
170
169
|
if isinstance(date, datetime):
|
171
170
|
return date
|
172
171
|
parsed = dateparser.parse(
|
@@ -180,7 +179,7 @@ class DateRangeCondition(FilterCondition):
|
|
180
179
|
|
181
180
|
@staticmethod
|
182
181
|
def now() -> datetime:
|
183
|
-
return datetime.now(tz=
|
182
|
+
return datetime.now(tz=UTC)
|
184
183
|
|
185
184
|
|
186
185
|
class InvalidFilterError(Exception):
|
@@ -210,13 +209,13 @@ class Filter:
|
|
210
209
|
|
211
210
|
def __init__(
|
212
211
|
self,
|
213
|
-
conditions:
|
212
|
+
conditions: list[FilterCondition] | None = None,
|
214
213
|
mode: FilterMode = FilterMode.AND,
|
215
214
|
):
|
216
215
|
self.conditions: list[FilterCondition] = conditions or []
|
217
216
|
self.mode = mode
|
218
217
|
|
219
|
-
def condition_by_key(self, key: str) ->
|
218
|
+
def condition_by_key(self, key: str) -> FilterCondition | None:
|
220
219
|
"""
|
221
220
|
Returns the condition with the given key, or None if it does not exist.
|
222
221
|
"""
|
@@ -258,7 +257,7 @@ class Filter:
|
|
258
257
|
merged_condition = existing_condition.copy_and_merge(condition)
|
259
258
|
return self.copy_and_override(merged_condition)
|
260
259
|
|
261
|
-
def eq(self, key: str, value:
|
260
|
+
def eq(self, key: str, value: str | None) -> "Filter":
|
262
261
|
"""
|
263
262
|
Copies the filter and adds a condition to the copy, that requires
|
264
263
|
the given key to be equal to the given value. If the value is None,
|
@@ -268,7 +267,7 @@ class Filter:
|
|
268
267
|
return self.is_in(key, [value])
|
269
268
|
return self
|
270
269
|
|
271
|
-
def like(self, key: str, value:
|
270
|
+
def like(self, key: str, value: str | None) -> "Filter":
|
272
271
|
"""
|
273
272
|
Copies the filter and adds a condition to the copy, that requires
|
274
273
|
the given key to be similar to the given value based on the % wildcard.
|
@@ -278,7 +277,7 @@ class Filter:
|
|
278
277
|
return self.add_condition(LikeCondition(key, [value]))
|
279
278
|
return self
|
280
279
|
|
281
|
-
def is_in(self, key: str, values:
|
280
|
+
def is_in(self, key: str, values: Iterable[Any] | None) -> "Filter":
|
282
281
|
"""
|
283
282
|
Copies the filter and adds a condition to the copy, that requires
|
284
283
|
the given key to be equal to one of the given values. If the values
|
@@ -293,7 +292,7 @@ class Filter:
|
|
293
292
|
return self.add_condition(EqCondition(key, value_list))
|
294
293
|
return self
|
295
294
|
|
296
|
-
def before(self, key: str, date:
|
295
|
+
def before(self, key: str, date: datetime | str | None) -> "Filter":
|
297
296
|
"""
|
298
297
|
Copies the filter and adds a condition to the copy, that requires
|
299
298
|
the given key to be before the given date. If the date is None,
|
@@ -303,7 +302,7 @@ class Filter:
|
|
303
302
|
return self.add_condition(DateRangeCondition(key, None, date))
|
304
303
|
return self
|
305
304
|
|
306
|
-
def after(self, key: str, date:
|
305
|
+
def after(self, key: str, date: datetime | str | None) -> "Filter":
|
307
306
|
"""
|
308
307
|
Copies the filter and adds a condition to the copy, that requires
|
309
308
|
the given key to be after the given date. If the date is None,
|
@@ -316,8 +315,8 @@ class Filter:
|
|
316
315
|
def between(
|
317
316
|
self,
|
318
317
|
key: str,
|
319
|
-
start:
|
320
|
-
end:
|
318
|
+
start: datetime | str | None,
|
319
|
+
end: datetime | str | None,
|
321
320
|
) -> "Filter":
|
322
321
|
"""
|
323
322
|
Copies the filter and adds a condition to the copy, that requires
|
@@ -3,7 +3,6 @@ from datetime import (
|
|
3
3
|
datetime,
|
4
4
|
timedelta,
|
5
5
|
)
|
6
|
-
from typing import Optional
|
7
6
|
|
8
7
|
from reconcile.utils.ocm.base import (
|
9
8
|
OCMClusterServiceLog,
|
@@ -17,7 +16,7 @@ CLUSTER_SERVICE_LOGS_CREATE_ENDPOINT = "/api/service_logs/v1/cluster_logs"
|
|
17
16
|
|
18
17
|
|
19
18
|
def get_service_logs_for_cluster_uuid(
|
20
|
-
ocm_api: OCMBaseClient, cluster_uuid: str, filter:
|
19
|
+
ocm_api: OCMBaseClient, cluster_uuid: str, filter: Filter | None = None
|
21
20
|
) -> Generator[OCMClusterServiceLog, None, None]:
|
22
21
|
"""
|
23
22
|
Returns a list of service logs for a cluster, matching the optional filter.
|
@@ -36,7 +35,7 @@ def get_service_logs_for_cluster_uuid(
|
|
36
35
|
def create_service_log(
|
37
36
|
ocm_api: OCMBaseClient,
|
38
37
|
service_log: OCMClusterServiceLogCreateModel,
|
39
|
-
dedup_interval:
|
38
|
+
dedup_interval: timedelta | None = None,
|
40
39
|
) -> OCMClusterServiceLog:
|
41
40
|
if dedup_interval:
|
42
41
|
previous_log = next(
|
@@ -1,8 +1,4 @@
|
|
1
|
-
from typing import
|
2
|
-
Any,
|
3
|
-
Optional,
|
4
|
-
Type,
|
5
|
-
)
|
1
|
+
from typing import Any
|
6
2
|
|
7
3
|
from pydantic import Field
|
8
4
|
from pydantic.fields import ModelField
|
@@ -15,7 +11,7 @@ from reconcile.utils.ocm.labels import build_container_for_prefix
|
|
15
11
|
|
16
12
|
|
17
13
|
def sre_capability_label_key(
|
18
|
-
sre_capability: str, config_atom:
|
14
|
+
sre_capability: str, config_atom: str | None = None
|
19
15
|
) -> str:
|
20
16
|
"""
|
21
17
|
Generates label keys compliant with the naming schema defined in
|
@@ -34,7 +30,7 @@ def labelset_groupfield(group_prefix: str) -> Any:
|
|
34
30
|
|
35
31
|
|
36
32
|
def build_labelset(
|
37
|
-
labels: LabelContainer, dataclass:
|
33
|
+
labels: LabelContainer, dataclass: type[LabelSetTypeVar]
|
38
34
|
) -> LabelSetTypeVar:
|
39
35
|
"""
|
40
36
|
Instantiates a dataclass from a set of labels.
|
@@ -46,7 +42,7 @@ def build_labelset(
|
|
46
42
|
return dataclass(**raw_data)
|
47
43
|
|
48
44
|
|
49
|
-
def _labelset_field_value(labels: LabelContainer, field: ModelField) ->
|
45
|
+
def _labelset_field_value(labels: LabelContainer, field: ModelField) -> Any | None:
|
50
46
|
key_prefix = field.field_info.extra.get("group_by_prefix")
|
51
47
|
if key_prefix:
|
52
48
|
return build_container_for_prefix(
|
@@ -1,5 +1,3 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
1
|
from pydantic import ValidationError
|
4
2
|
|
5
3
|
from reconcile.utils.ocm.base import (
|
@@ -38,7 +36,7 @@ def get_subscriptions(
|
|
38
36
|
|
39
37
|
|
40
38
|
def build_subscription_filter(
|
41
|
-
states:
|
39
|
+
states: set[str] | None = None, managed: bool = True
|
42
40
|
) -> Filter:
|
43
41
|
"""
|
44
42
|
Helper function to create a subscription search filer for two very common
|
reconcile/utils/ocm/syncsets.py
CHANGED
reconcile/utils/ocm/upgrades.py
CHANGED
@@ -1,8 +1,4 @@
|
|
1
|
-
from typing import
|
2
|
-
Any,
|
3
|
-
Optional,
|
4
|
-
Union,
|
5
|
-
)
|
1
|
+
from typing import Any
|
6
2
|
|
7
3
|
from reconcile.utils.ocm.base import OCMVersionGate
|
8
4
|
from reconcile.utils.ocm_base_client import OCMBaseClient
|
@@ -20,7 +16,7 @@ def build_cluster_url(cluster_id: str) -> str:
|
|
20
16
|
|
21
17
|
|
22
18
|
def get_upgrade_policies(
|
23
|
-
ocm_api: OCMBaseClient, cluster_id: str, schedule_type:
|
19
|
+
ocm_api: OCMBaseClient, cluster_id: str, schedule_type: str | None = None
|
24
20
|
) -> list[dict[str, Any]]:
|
25
21
|
"""Returns a list of details of Upgrade Policies
|
26
22
|
|
@@ -48,7 +44,7 @@ def get_upgrade_policies(
|
|
48
44
|
|
49
45
|
def get_upgrade_policy_state(
|
50
46
|
ocm_api: OCMBaseClient, cluster_id: str, upgrade_policy_id: str
|
51
|
-
) ->
|
47
|
+
) -> str | None:
|
52
48
|
try:
|
53
49
|
state_data = ocm_api.get(
|
54
50
|
f"{build_cluster_url(cluster_id)}/upgrade_policies/{upgrade_policy_id}/state"
|
@@ -80,7 +76,7 @@ def delete_upgrade_policy(
|
|
80
76
|
|
81
77
|
|
82
78
|
def get_control_plane_upgrade_policies(
|
83
|
-
ocm_api: OCMBaseClient, cluster_id: str, schedule_type:
|
79
|
+
ocm_api: OCMBaseClient, cluster_id: str, schedule_type: str | None = None
|
84
80
|
) -> list[dict[str, Any]]:
|
85
81
|
"""
|
86
82
|
Returns a list of details of Upgrade Policies
|
@@ -160,7 +156,7 @@ def create_node_pool_upgrade_policy(
|
|
160
156
|
|
161
157
|
def create_version_agreement(
|
162
158
|
ocm_api: OCMBaseClient, gate_id: str, cluster_id: str
|
163
|
-
) -> dict[str,
|
159
|
+
) -> dict[str, str | bool]:
|
164
160
|
return ocm_api.post(
|
165
161
|
f"{build_cluster_url(cluster_id)}/gate_agreements",
|
166
162
|
{"version_gate": {"id": gate_id}},
|
@@ -6,9 +6,7 @@ from collections.abc import (
|
|
6
6
|
from types import TracebackType
|
7
7
|
from typing import (
|
8
8
|
Any,
|
9
|
-
Optional,
|
10
9
|
Protocol,
|
11
|
-
Type,
|
12
10
|
)
|
13
11
|
|
14
12
|
from pydantic import BaseModel
|
@@ -40,7 +38,7 @@ class OCMBaseClient:
|
|
40
38
|
access_token_client_secret: str,
|
41
39
|
access_token_url: str,
|
42
40
|
access_token_client_id: str,
|
43
|
-
session:
|
41
|
+
session: Session | None = None,
|
44
42
|
):
|
45
43
|
self._access_token_client_secret = access_token_client_secret
|
46
44
|
self._access_token_client_id = access_token_client_id
|
@@ -69,7 +67,7 @@ class OCMBaseClient:
|
|
69
67
|
"accept": "application/json",
|
70
68
|
})
|
71
69
|
|
72
|
-
def get(self, api_path: str, params:
|
70
|
+
def get(self, api_path: str, params: Mapping[str, str] | None = None) -> Any:
|
73
71
|
ocm_request.labels(verb="GET", client_id=self._access_token_client_id).inc()
|
74
72
|
r = self._session.get(
|
75
73
|
f"{self._url}{api_path}",
|
@@ -82,9 +80,9 @@ class OCMBaseClient:
|
|
82
80
|
def get_paginated(
|
83
81
|
self,
|
84
82
|
api_path: str,
|
85
|
-
params:
|
83
|
+
params: dict[str, Any] | None = None,
|
86
84
|
max_page_size: int = 100,
|
87
|
-
max_pages:
|
85
|
+
max_pages: int | None = None,
|
88
86
|
) -> Generator[dict[str, Any], None, None]:
|
89
87
|
if not params:
|
90
88
|
params_copy = {}
|
@@ -94,8 +92,7 @@ class OCMBaseClient:
|
|
94
92
|
|
95
93
|
while True:
|
96
94
|
rs = self.get(api_path, params=params_copy)
|
97
|
-
|
98
|
-
yield item
|
95
|
+
yield from rs.get("items", [])
|
99
96
|
current_page = rs.get("page", 0)
|
100
97
|
records_on_page = rs.get("size", len(rs.get("items", [])))
|
101
98
|
if records_on_page < max_page_size:
|
@@ -107,8 +104,8 @@ class OCMBaseClient:
|
|
107
104
|
def post(
|
108
105
|
self,
|
109
106
|
api_path: str,
|
110
|
-
data:
|
111
|
-
params:
|
107
|
+
data: Mapping[str, Any] | None = None,
|
108
|
+
params: Mapping[str, str] | None = None,
|
112
109
|
) -> Any:
|
113
110
|
ocm_request.labels(verb="POST", client_id=self._access_token_client_id).inc()
|
114
111
|
r = self._session.post(
|
@@ -130,7 +127,7 @@ class OCMBaseClient:
|
|
130
127
|
self,
|
131
128
|
api_path: str,
|
132
129
|
data: Mapping[str, Any],
|
133
|
-
params:
|
130
|
+
params: Mapping[str, str] | None = None,
|
134
131
|
):
|
135
132
|
ocm_request.labels(verb="PATCH", client_id=self._access_token_client_id).inc()
|
136
133
|
r = self._session.patch(
|
@@ -158,9 +155,9 @@ class OCMBaseClient:
|
|
158
155
|
|
159
156
|
def __exit__(
|
160
157
|
self,
|
161
|
-
exc_type:
|
162
|
-
exc_value:
|
163
|
-
traceback:
|
158
|
+
exc_type: type[BaseException] | None,
|
159
|
+
exc_value: BaseException | None,
|
160
|
+
traceback: TracebackType | None,
|
164
161
|
) -> None:
|
165
162
|
self.close()
|
166
163
|
|
@@ -184,7 +181,7 @@ class OCMAPIClientConfiguration(BaseModel, arbitrary_types_allowed=True):
|
|
184
181
|
def init_ocm_base_client_for_org(
|
185
182
|
org: AUSOCMOrganization,
|
186
183
|
secret_reader: SecretReaderBase,
|
187
|
-
session:
|
184
|
+
session: Session | None = None,
|
188
185
|
) -> OCMBaseClient:
|
189
186
|
if org.access_token_client_id:
|
190
187
|
return init_ocm_base_client(
|
@@ -204,7 +201,7 @@ def init_ocm_base_client_for_org(
|
|
204
201
|
def init_ocm_base_client(
|
205
202
|
cfg: OCMAPIClientConfigurationProtocol,
|
206
203
|
secret_reader: SecretReaderBase,
|
207
|
-
session:
|
204
|
+
session: Session | None = None,
|
208
205
|
) -> OCMBaseClient:
|
209
206
|
"""
|
210
207
|
Initiate an API client towards an OCM instance.
|
@@ -6,10 +6,6 @@ import json
|
|
6
6
|
import re
|
7
7
|
from collections.abc import Mapping
|
8
8
|
from threading import Lock
|
9
|
-
from typing import (
|
10
|
-
Optional,
|
11
|
-
Union,
|
12
|
-
)
|
13
9
|
|
14
10
|
import semver
|
15
11
|
from pydantic import BaseModel
|
@@ -48,7 +44,7 @@ IGNORABLE_DATA_FIELDS = ["service-ca.crt"]
|
|
48
44
|
# these labels existance and/or value is determined by a controller running
|
49
45
|
# on the cluster. we need to ignore their existance in the current state,
|
50
46
|
# otherwise we will deal with constant reconciliation
|
51
|
-
CONTROLLER_MANAGED_LABELS: dict[str, set[
|
47
|
+
CONTROLLER_MANAGED_LABELS: dict[str, set[str | re.Pattern]] = {
|
52
48
|
"ManagedCluster": {
|
53
49
|
"clusterID",
|
54
50
|
"managed-by",
|
@@ -247,9 +243,7 @@ class OpenshiftResource:
|
|
247
243
|
self.name # pylint: disable=pointless-statement
|
248
244
|
self.kind # pylint: disable=pointless-statement
|
249
245
|
except (KeyError, TypeError) as e:
|
250
|
-
msg = "resource invalid data ({}). details: {}"
|
251
|
-
e.__class__.__name__, self.error_details
|
252
|
-
)
|
246
|
+
msg = f"resource invalid data ({e.__class__.__name__}). details: {self.error_details}"
|
253
247
|
raise ConstructResourceError(msg)
|
254
248
|
|
255
249
|
if self.kind not in {
|
@@ -581,7 +575,7 @@ class ResourceInventory:
|
|
581
575
|
cluster,
|
582
576
|
namespace,
|
583
577
|
resource_type,
|
584
|
-
managed_names:
|
578
|
+
managed_names: list[str] | None = None,
|
585
579
|
):
|
586
580
|
self._clusters.setdefault(cluster, {})
|
587
581
|
self._clusters[cluster].setdefault(namespace, {})
|
@@ -690,8 +684,8 @@ def build_secret(
|
|
690
684
|
integration_version: str,
|
691
685
|
unencoded_data: Mapping[str, str],
|
692
686
|
error_details: str = "",
|
693
|
-
caller_name:
|
694
|
-
annotations:
|
687
|
+
caller_name: str | None = None,
|
688
|
+
annotations: Mapping[str, str] | None = None,
|
695
689
|
) -> OpenshiftResource:
|
696
690
|
encoded_data = {
|
697
691
|
k: base64_encode_secret_field_value(v) for k, v in unencoded_data.items()
|
reconcile/utils/output.py
CHANGED
@@ -3,17 +3,16 @@ from collections.abc import (
|
|
3
3
|
Iterable,
|
4
4
|
Mapping,
|
5
5
|
)
|
6
|
-
from typing import Optional, Union
|
7
6
|
|
8
7
|
import yaml
|
9
8
|
from tabulate import tabulate
|
10
9
|
|
11
10
|
|
12
11
|
def print_output(
|
13
|
-
options: Mapping[str,
|
12
|
+
options: Mapping[str, str | bool],
|
14
13
|
content: list[dict],
|
15
14
|
columns: Iterable[str] = (),
|
16
|
-
) ->
|
15
|
+
) -> str | None:
|
17
16
|
if options["sort"]:
|
18
17
|
content.sort(key=lambda c: tuple(c.values()))
|
19
18
|
if options.get("to_string"):
|
reconcile/utils/pagerduty_api.py
CHANGED
@@ -6,7 +6,6 @@ from collections.abc import (
|
|
6
6
|
from datetime import datetime as dt
|
7
7
|
from datetime import timedelta
|
8
8
|
from typing import (
|
9
|
-
Optional,
|
10
9
|
Protocol,
|
11
10
|
)
|
12
11
|
|
@@ -45,7 +44,7 @@ class PagerDutyUser(Protocol):
|
|
45
44
|
which must be implemented by a class to be compatible."""
|
46
45
|
|
47
46
|
org_username: str
|
48
|
-
pagerduty_username:
|
47
|
+
pagerduty_username: str | None
|
49
48
|
|
50
49
|
|
51
50
|
class PagerDutyTarget(Protocol):
|
@@ -54,8 +53,8 @@ class PagerDutyTarget(Protocol):
|
|
54
53
|
|
55
54
|
name: str
|
56
55
|
instance: PagerDutyInstance
|
57
|
-
escalation_policy_id:
|
58
|
-
schedule_id:
|
56
|
+
escalation_policy_id: str | None
|
57
|
+
schedule_id: str | None
|
59
58
|
|
60
59
|
|
61
60
|
class PagerDutyConfig(BaseModel):
|
@@ -166,7 +165,7 @@ class PagerDutyMap:
|
|
166
165
|
|
167
166
|
def get_pagerduty_map(
|
168
167
|
secret_reader: SecretReader,
|
169
|
-
pagerduty_instances:
|
168
|
+
pagerduty_instances: Iterable[PagerDutyInstance] | None,
|
170
169
|
init_users: bool = True,
|
171
170
|
pager_duty_api_class: type[PagerDutyApi] = PagerDutyApi,
|
172
171
|
) -> PagerDutyMap:
|