qontract-reconcile 0.10.1rc884__py3-none-any.whl → 0.10.1rc885__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.1rc884.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/RECORD +276 -276
- 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 +2 -2
- 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 +9 -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 +2 -5
- 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 +2 -5
- reconcile/glitchtip_project_alerts/integration.py +3 -6
- reconcile/glitchtip_project_dsn/integration.py +4 -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 +27 -29
- 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 +3 -4
- 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 +5 -5
- reconcile/test/conftest.py +7 -10
- reconcile/test/fixtures.py +1 -1
- reconcile/test/saas_auto_promotions_manager/conftest.py +2 -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/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/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 +32 -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 +37 -53
- 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 +3 -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 +30 -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 +12 -17
- tools/template_validation.py +1 -1
- tools/test/conftest.py +3 -6
- {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,4 @@
|
|
1
1
|
from collections.abc import Callable
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from sretoolbox.utils import threaded
|
5
4
|
|
@@ -95,8 +94,8 @@ class SaasAutoPromotionsManager:
|
|
95
94
|
|
96
95
|
def init_external_dependencies(
|
97
96
|
dry_run: bool,
|
98
|
-
env_name:
|
99
|
-
app_name:
|
97
|
+
env_name: str | None = None,
|
98
|
+
app_name: str | None = None,
|
100
99
|
) -> tuple[
|
101
100
|
PromotionState,
|
102
101
|
VCS,
|
@@ -169,9 +168,9 @@ def init_external_dependencies(
|
|
169
168
|
def run(
|
170
169
|
dry_run: bool,
|
171
170
|
thread_pool_size: int,
|
172
|
-
env_name:
|
173
|
-
app_name:
|
174
|
-
defer:
|
171
|
+
env_name: str | None = None,
|
172
|
+
app_name: str | None = None,
|
173
|
+
defer: Callable | None = None,
|
175
174
|
) -> None:
|
176
175
|
(
|
177
176
|
deployment_state,
|
@@ -1,7 +1,6 @@
|
|
1
1
|
from collections.abc import Iterable
|
2
2
|
from dataclasses import dataclass
|
3
3
|
from enum import Enum
|
4
|
-
from typing import Optional
|
5
4
|
|
6
5
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.open_merge_requests import (
|
7
6
|
OpenBatcherMergeRequest,
|
@@ -145,7 +144,7 @@ class Batcher:
|
|
145
144
|
if not unsubmitted_promotions:
|
146
145
|
return
|
147
146
|
|
148
|
-
batch_with_capacity:
|
147
|
+
batch_with_capacity: OpenBatcherMergeRequest | None = None
|
149
148
|
for mr in self._open_mrs:
|
150
149
|
if mr.is_batchable and len(mr.content_hashes) < batch_limit:
|
151
150
|
batch_with_capacity = mr
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
2
|
from datetime import datetime
|
3
|
-
from typing import Optional
|
4
3
|
|
5
4
|
from reconcile.utils.promotion_state import PromotionState
|
6
5
|
from reconcile.utils.secret_reader import HasSecret
|
@@ -18,7 +17,7 @@ class DeploymentInfo:
|
|
18
17
|
success: bool
|
19
18
|
saas_file: str
|
20
19
|
target_config_hash: str
|
21
|
-
check_in:
|
20
|
+
check_in: datetime | None
|
22
21
|
|
23
22
|
|
24
23
|
class Publisher:
|
@@ -37,10 +36,10 @@ class Publisher:
|
|
37
36
|
app_name: str,
|
38
37
|
namespace_name: str,
|
39
38
|
resource_template_name: str,
|
40
|
-
target_name:
|
39
|
+
target_name: str | None,
|
41
40
|
cluster_name: str,
|
42
|
-
auth_code:
|
43
|
-
publish_job_logs:
|
41
|
+
auth_code: HasSecret | None,
|
42
|
+
publish_job_logs: bool | None,
|
44
43
|
has_subscriber: bool = True,
|
45
44
|
):
|
46
45
|
self._ref = ref
|
@@ -48,7 +47,7 @@ class Publisher:
|
|
48
47
|
self._auth_code = auth_code
|
49
48
|
self.channels: set[str] = set()
|
50
49
|
self.commit_sha: str = ""
|
51
|
-
self.deployment_info_by_channel: dict[str,
|
50
|
+
self.deployment_info_by_channel: dict[str, DeploymentInfo | None] = {}
|
52
51
|
self.uid = uid
|
53
52
|
self.saas_name = saas_name
|
54
53
|
self.saas_file_path = saas_file_path
|
@@ -2,8 +2,7 @@ import hashlib
|
|
2
2
|
import logging
|
3
3
|
from collections.abc import Iterable
|
4
4
|
from dataclasses import dataclass
|
5
|
-
from datetime import datetime, timedelta
|
6
|
-
from typing import Optional
|
5
|
+
from datetime import UTC, datetime, timedelta
|
7
6
|
|
8
7
|
from reconcile.gql_definitions.fragments.saas_target_namespace import (
|
9
8
|
SaasTargetNamespace,
|
@@ -80,7 +79,7 @@ class Subscriber:
|
|
80
79
|
|
81
80
|
def _validate_deployment(
|
82
81
|
self, publisher: Publisher, channel: Channel
|
83
|
-
) ->
|
82
|
+
) -> DeploymentInfo | None:
|
84
83
|
deployment_info = publisher.deployment_info_by_channel.get(channel.name)
|
85
84
|
if not deployment_info:
|
86
85
|
logging.info(
|
@@ -103,7 +102,7 @@ class Subscriber:
|
|
103
102
|
We accumulate the time a ref is running on all publishers for this subscriber.
|
104
103
|
We compare that accumulated time with the soak_days setting of the subscriber.
|
105
104
|
"""
|
106
|
-
now = datetime.now(
|
105
|
+
now = datetime.now(UTC)
|
107
106
|
delta = timedelta(days=0)
|
108
107
|
for channel in self.channels:
|
109
108
|
for publisher in channel.publishers:
|
reconcile/saas_file_validator.py
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
import sys
|
3
|
-
from
|
4
|
-
Callable,
|
5
|
-
Optional,
|
6
|
-
)
|
3
|
+
from collections.abc import Callable
|
7
4
|
|
8
5
|
from reconcile.jenkins_job_builder import init_jjb
|
9
6
|
from reconcile.status import ExitCodes
|
@@ -26,7 +23,7 @@ QONTRACT_INTEGRATION_VERSION = make_semver(0, 1, 0)
|
|
26
23
|
|
27
24
|
|
28
25
|
@defer
|
29
|
-
def run(dry_run: bool, defer:
|
26
|
+
def run(dry_run: bool, defer: Callable | None = None) -> None:
|
30
27
|
vault_settings = get_app_interface_vault_settings()
|
31
28
|
saasherder_settings = get_saasherder_settings()
|
32
29
|
secret_reader = create_secret_reader(use_vault=vault_settings.vault)
|
@@ -1,9 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
import sys
|
3
|
-
from typing import
|
4
|
-
Any,
|
5
|
-
Optional,
|
6
|
-
)
|
3
|
+
from typing import Any
|
7
4
|
|
8
5
|
from reconcile.closedbox_endpoint_monitoring_base import (
|
9
6
|
Endpoint,
|
@@ -43,7 +40,7 @@ def run(
|
|
43
40
|
|
44
41
|
def build_probe(
|
45
42
|
provider: EndpointMonitoringProvider, endpoints: list[Endpoint]
|
46
|
-
) ->
|
43
|
+
) -> OpenshiftResource | None:
|
47
44
|
signalfx = provider.signalFx
|
48
45
|
if not signalfx:
|
49
46
|
return None
|
@@ -4,10 +4,7 @@ from collections.abc import (
|
|
4
4
|
Callable,
|
5
5
|
Iterable,
|
6
6
|
)
|
7
|
-
from typing import
|
8
|
-
Any,
|
9
|
-
Optional,
|
10
|
-
)
|
7
|
+
from typing import Any
|
11
8
|
|
12
9
|
import jinja2
|
13
10
|
import yaml
|
@@ -248,9 +245,9 @@ def get_skupper_networks(query_func: Callable) -> list[SkupperNetworkV1]:
|
|
248
245
|
def run(
|
249
246
|
dry_run: bool,
|
250
247
|
thread_pool_size: int = 10,
|
251
|
-
internal:
|
248
|
+
internal: bool | None = None,
|
252
249
|
use_jump_host: bool = True,
|
253
|
-
defer:
|
250
|
+
defer: Callable | None = None,
|
254
251
|
) -> None:
|
255
252
|
vault_settings = get_app_interface_vault_settings()
|
256
253
|
secret_reader = create_secret_reader(use_vault=vault_settings.vault)
|
@@ -77,10 +77,8 @@ class SkupperSite(BaseModel):
|
|
77
77
|
if (
|
78
78
|
isinstance(
|
79
79
|
c,
|
80
|
-
|
81
|
-
|
82
|
-
ClusterPeeringConnectionClusterAccepterV1,
|
83
|
-
),
|
80
|
+
ClusterPeeringConnectionClusterRequesterV1
|
81
|
+
| ClusterPeeringConnectionClusterAccepterV1,
|
84
82
|
)
|
85
83
|
) and c.cluster.name == other.cluster.name:
|
86
84
|
return True
|
@@ -168,7 +166,7 @@ class SkupperSite(BaseModel):
|
|
168
166
|
|
169
167
|
def unique_token_name(self, other: SkupperSite) -> str:
|
170
168
|
"""Generate a unique token name for a site connection."""
|
171
|
-
return hashlib.sha256(f"{other}-{self}".encode(
|
169
|
+
return hashlib.sha256(f"{other}-{self}".encode()).hexdigest()
|
172
170
|
|
173
171
|
def token_name(self, other: SkupperSite) -> str:
|
174
172
|
"""Get the token name for a site connection."""
|
reconcile/slack_base.py
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
from collections.abc import Mapping
|
2
|
-
from typing import
|
3
|
-
Any,
|
4
|
-
Optional,
|
5
|
-
)
|
2
|
+
from typing import Any
|
6
3
|
|
7
4
|
from reconcile import queries
|
8
5
|
from reconcile.utils.secret_reader import (
|
@@ -31,7 +28,7 @@ def slackapi_from_slack_workspace(
|
|
31
28
|
secret_reader: SecretReaderBase,
|
32
29
|
integration_name: str,
|
33
30
|
init_usergroups: bool = True,
|
34
|
-
channel:
|
31
|
+
channel: str | None = None,
|
35
32
|
) -> SlackApi:
|
36
33
|
if "workspace" not in slack_workspace:
|
37
34
|
raise ValueError('Slack workspace not containing keyword "workspace"')
|
@@ -104,9 +101,9 @@ def slackapi_from_permissions(
|
|
104
101
|
def get_slackapi(
|
105
102
|
workspace_name: str,
|
106
103
|
token: str,
|
107
|
-
client_config:
|
104
|
+
client_config: HasClientConfig | None = None,
|
108
105
|
init_usergroups: bool = True,
|
109
|
-
channel:
|
106
|
+
channel: str | None = None,
|
110
107
|
) -> SlackApi:
|
111
108
|
"""Initiate a SlackApi instance."""
|
112
109
|
if client_config:
|
reconcile/slack_usergroups.py
CHANGED
@@ -3,14 +3,12 @@ import sys
|
|
3
3
|
from collections.abc import (
|
4
4
|
Callable,
|
5
5
|
Iterable,
|
6
|
+
Sequence,
|
6
7
|
)
|
7
8
|
from datetime import datetime
|
8
9
|
from typing import (
|
9
10
|
Any,
|
10
|
-
Optional,
|
11
|
-
Sequence,
|
12
11
|
TypedDict,
|
13
|
-
Union,
|
14
12
|
)
|
15
13
|
from urllib.parse import urlparse
|
16
14
|
|
@@ -77,7 +75,7 @@ INTEGRATION_VERSION = "0.1.0"
|
|
77
75
|
error_occurred = False
|
78
76
|
|
79
77
|
|
80
|
-
def get_git_api(url: str) ->
|
78
|
+
def get_git_api(url: str) -> GithubRepositoryApi | GitLabApi:
|
81
79
|
"""Return GitHub/GitLab API based on url."""
|
82
80
|
parsed_url = urlparse(url)
|
83
81
|
|
@@ -147,7 +145,7 @@ def compute_cluster_user_group(name: str) -> str:
|
|
147
145
|
def get_slack_map(
|
148
146
|
secret_reader: SecretReader,
|
149
147
|
permissions: Iterable[PermissionSlackUsergroupV1],
|
150
|
-
desired_workspace_name:
|
148
|
+
desired_workspace_name: str | None = None,
|
151
149
|
) -> SlackMap:
|
152
150
|
"""Return SlackMap (API) per workspaces."""
|
153
151
|
slack_map = {}
|
@@ -183,8 +181,8 @@ def get_slack_map(
|
|
183
181
|
|
184
182
|
def get_current_state(
|
185
183
|
slack_map: SlackMap,
|
186
|
-
desired_workspace_name:
|
187
|
-
desired_usergroup_name:
|
184
|
+
desired_workspace_name: str | None,
|
185
|
+
desired_usergroup_name: str | None,
|
188
186
|
cluster_usergroups: list[str],
|
189
187
|
) -> SlackState:
|
190
188
|
"""
|
@@ -399,8 +397,8 @@ def get_desired_state(
|
|
399
397
|
pagerduty_map: PagerDutyMap,
|
400
398
|
permissions: Iterable[PermissionSlackUsergroupV1],
|
401
399
|
users: Iterable[User],
|
402
|
-
desired_workspace_name:
|
403
|
-
desired_usergroup_name:
|
400
|
+
desired_workspace_name: str | None,
|
401
|
+
desired_usergroup_name: str | None,
|
404
402
|
) -> SlackState:
|
405
403
|
"""Get the desired state of Slack usergroups."""
|
406
404
|
desired_state: SlackState = {}
|
@@ -461,8 +459,8 @@ def get_desired_state_cluster_usergroups(
|
|
461
459
|
slack_map: SlackMap,
|
462
460
|
clusters: Iterable[ClusterV1],
|
463
461
|
users: Iterable[UserV1],
|
464
|
-
desired_workspace_name:
|
465
|
-
desired_usergroup_name:
|
462
|
+
desired_workspace_name: str | None,
|
463
|
+
desired_usergroup_name: str | None,
|
466
464
|
) -> SlackState:
|
467
465
|
"""Get the desired state of Slack usergroups."""
|
468
466
|
desired_state: SlackState = {}
|
@@ -752,14 +750,14 @@ class RunnerParams(TypedDict):
|
|
752
750
|
slack_map: SlackMap
|
753
751
|
desired_state: SlackState
|
754
752
|
clusters: list[ClusterV1]
|
755
|
-
workspace_name:
|
756
|
-
usergroup_name:
|
753
|
+
workspace_name: str | None
|
754
|
+
usergroup_name: str | None
|
757
755
|
|
758
756
|
|
759
757
|
def run(
|
760
758
|
dry_run: bool,
|
761
|
-
workspace_name:
|
762
|
-
usergroup_name:
|
759
|
+
workspace_name: str | None = None,
|
760
|
+
usergroup_name: str | None = None,
|
763
761
|
enable_extended_early_exit: bool = False,
|
764
762
|
extended_early_exit_cache_ttl_seconds: int = 3600,
|
765
763
|
log_cached_log_output: bool = False,
|
@@ -841,8 +839,8 @@ def runner(
|
|
841
839
|
slack_map: SlackMap,
|
842
840
|
desired_state: SlackState,
|
843
841
|
clusters: list[ClusterV1],
|
844
|
-
workspace_name:
|
845
|
-
usergroup_name:
|
842
|
+
workspace_name: str | None = None,
|
843
|
+
usergroup_name: str | None = None,
|
846
844
|
) -> ExtendedEarlyExitRunnerResult:
|
847
845
|
current_state = get_current_state(
|
848
846
|
slack_map=slack_map,
|
reconcile/sql_query.py
CHANGED
@@ -2,17 +2,13 @@ import logging
|
|
2
2
|
import sys
|
3
3
|
import time
|
4
4
|
from collections.abc import (
|
5
|
+
Callable,
|
5
6
|
Iterable,
|
6
7
|
Mapping,
|
7
8
|
)
|
8
9
|
from enum import Enum
|
9
10
|
from textwrap import indent
|
10
|
-
from typing import
|
11
|
-
Any,
|
12
|
-
Callable,
|
13
|
-
Optional,
|
14
|
-
Union,
|
15
|
-
)
|
11
|
+
from typing import Any
|
16
12
|
|
17
13
|
import jinja2
|
18
14
|
|
@@ -162,7 +158,7 @@ spec:
|
|
162
158
|
|
163
159
|
def get_tf_resource_info(
|
164
160
|
terrascript: Terrascript, namespace: Mapping[str, Any], identifier: str
|
165
|
-
) ->
|
161
|
+
) -> dict[str, str] | None:
|
166
162
|
"""
|
167
163
|
Extracting the external resources information from the namespace
|
168
164
|
for a given identifier
|
@@ -191,7 +187,7 @@ def get_tf_resource_info(
|
|
191
187
|
|
192
188
|
|
193
189
|
def collect_queries(
|
194
|
-
settings: dict[str, Any], smtp_client: SmtpClient, query_name:
|
190
|
+
settings: dict[str, Any], smtp_client: SmtpClient, query_name: str | None = None
|
195
191
|
) -> list[dict[str, Any]]:
|
196
192
|
"""
|
197
193
|
Consults the app-interface and constructs the list of queries
|
@@ -835,7 +831,7 @@ def _process_new_query(
|
|
835
831
|
def run(
|
836
832
|
dry_run: bool,
|
837
833
|
enable_deletion: bool = False,
|
838
|
-
defer:
|
834
|
+
defer: Callable | None = None,
|
839
835
|
) -> None:
|
840
836
|
settings = queries.get_app_interface_settings()
|
841
837
|
state = init_state(integration=QONTRACT_INTEGRATION)
|
reconcile/status_board.py
CHANGED
@@ -3,10 +3,9 @@ from abc import (
|
|
3
3
|
ABC,
|
4
4
|
abstractmethod,
|
5
5
|
)
|
6
|
+
from collections.abc import Iterable, Mapping
|
6
7
|
from typing import (
|
7
8
|
Any,
|
8
|
-
Iterable,
|
9
|
-
Mapping,
|
10
9
|
Optional,
|
11
10
|
)
|
12
11
|
|
@@ -39,10 +38,10 @@ class AbstractStatusBoard(ABC, BaseModel):
|
|
39
38
|
"""Abstract class for upgrade policies
|
40
39
|
Used to create and delete upgrade policies in OCM."""
|
41
40
|
|
42
|
-
id:
|
41
|
+
id: str | None
|
43
42
|
name: str
|
44
43
|
fullname: str
|
45
|
-
metadata:
|
44
|
+
metadata: dict[str, Any] | None
|
46
45
|
|
47
46
|
@abstractmethod
|
48
47
|
def create(self, ocm: OCMBaseClient) -> None:
|
@@ -63,7 +62,7 @@ class AbstractStatusBoard(ABC, BaseModel):
|
|
63
62
|
|
64
63
|
|
65
64
|
class Product(AbstractStatusBoard):
|
66
|
-
applications:
|
65
|
+
applications: list["Application"] | None
|
67
66
|
|
68
67
|
def create(self, ocm: OCMBaseClient) -> None:
|
69
68
|
spec = self.dict(by_alias=True)
|
@@ -2,7 +2,6 @@ import logging
|
|
2
2
|
import time
|
3
3
|
from typing import (
|
4
4
|
Any,
|
5
|
-
Optional,
|
6
5
|
Self,
|
7
6
|
)
|
8
7
|
|
@@ -29,12 +28,12 @@ class AtlassianRawComponent(BaseModel):
|
|
29
28
|
|
30
29
|
id: str
|
31
30
|
name: str
|
32
|
-
description:
|
31
|
+
description: str | None
|
33
32
|
position: int
|
34
33
|
status: str
|
35
|
-
automation_email:
|
36
|
-
group_id:
|
37
|
-
group:
|
34
|
+
automation_email: str | None
|
35
|
+
group_id: str | None
|
36
|
+
group: bool | None
|
38
37
|
|
39
38
|
|
40
39
|
class AtlassianRawMaintenanceUpdate(BaseModel):
|
@@ -56,9 +55,9 @@ class AtlassianRawMaintenance(BaseModel):
|
|
56
55
|
scheduled_until: str
|
57
56
|
incident_updates: list[AtlassianRawMaintenanceUpdate]
|
58
57
|
components: list[AtlassianRawComponent]
|
59
|
-
auto_transition_deliver_notifications_at_end:
|
60
|
-
auto_transition_deliver_notifications_at_start:
|
61
|
-
scheduled_remind_prior:
|
58
|
+
auto_transition_deliver_notifications_at_end: bool | None
|
59
|
+
auto_transition_deliver_notifications_at_start: bool | None
|
60
|
+
scheduled_remind_prior: bool | None
|
62
61
|
|
63
62
|
|
64
63
|
class AtlassianAPI:
|
@@ -177,13 +176,13 @@ class AtlassianStatusPageProvider:
|
|
177
176
|
self._group_name_to_id = {g.name: g.id for g in self._components if g.group}
|
178
177
|
self._group_id_to_name = {g.id: g.name for g in self._components if g.group}
|
179
178
|
|
180
|
-
def get_component_by_id(self, id: str) ->
|
179
|
+
def get_component_by_id(self, id: str) -> StatusComponent | None:
|
181
180
|
raw = self.get_raw_component_by_id(id)
|
182
181
|
if raw:
|
183
182
|
return self._bound_raw_component_to_status_component(raw)
|
184
183
|
return None
|
185
184
|
|
186
|
-
def get_raw_component_by_id(self, id: str) ->
|
185
|
+
def get_raw_component_by_id(self, id: str) -> AtlassianRawComponent | None:
|
187
186
|
return self._components_by_id.get(id)
|
188
187
|
|
189
188
|
def get_current_page(self) -> StatusPage:
|
@@ -201,7 +200,7 @@ class AtlassianStatusPageProvider:
|
|
201
200
|
)
|
202
201
|
|
203
202
|
def _raw_component_to_status_component(
|
204
|
-
self, raw_component: AtlassianRawComponent, name_override:
|
203
|
+
self, raw_component: AtlassianRawComponent, name_override: str | None = None
|
205
204
|
) -> StatusComponent:
|
206
205
|
group_name = (
|
207
206
|
self._group_id_to_name.get(raw_component.group_id)
|
@@ -222,7 +221,7 @@ class AtlassianStatusPageProvider:
|
|
222
221
|
|
223
222
|
def _bound_raw_component_to_status_component(
|
224
223
|
self, raw_component: AtlassianRawComponent
|
225
|
-
) ->
|
224
|
+
) -> StatusComponent | None:
|
226
225
|
bound_component_name = self._binding_state.get_name_for_component_id(
|
227
226
|
raw_component.id
|
228
227
|
)
|
@@ -234,7 +233,7 @@ class AtlassianStatusPageProvider:
|
|
234
233
|
|
235
234
|
def lookup_component(
|
236
235
|
self, desired_component: StatusComponent
|
237
|
-
) -> tuple[
|
236
|
+
) -> tuple[AtlassianRawComponent | None, bool]:
|
238
237
|
"""
|
239
238
|
Finds the component on the page that matches the desired component. This
|
240
239
|
is either done explicitely by using binding information if available or
|
@@ -268,7 +267,7 @@ class AtlassianStatusPageProvider:
|
|
268
267
|
return component, bound
|
269
268
|
|
270
269
|
def should_apply(
|
271
|
-
self, desired: StatusComponent, current:
|
270
|
+
self, desired: StatusComponent, current: AtlassianRawComponent | None
|
272
271
|
) -> bool:
|
273
272
|
"""
|
274
273
|
Verifies if the desired component should be applied to the status page
|
@@ -410,7 +409,7 @@ class AtlassianStatusPageProvider:
|
|
410
409
|
def _raw_maintenance_to_status_maintenance(
|
411
410
|
self,
|
412
411
|
raw_maintenance: AtlassianRawMaintenance,
|
413
|
-
name_override:
|
412
|
+
name_override: str | None = None,
|
414
413
|
) -> StatusMaintenance:
|
415
414
|
return StatusMaintenance(
|
416
415
|
name=name_override or raw_maintenance.name,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
import sys
|
3
|
-
from datetime import datetime, timedelta
|
3
|
+
from datetime import UTC, datetime, timedelta
|
4
4
|
|
5
5
|
from reconcile.slack_base import slackapi_from_queries
|
6
6
|
from reconcile.statuspage.atlassian import AtlassianStatusPageProvider
|
@@ -52,7 +52,7 @@ class StatusPageMaintenancesIntegration(QontractReconcileIntegration[NoParams]):
|
|
52
52
|
desired_state: list[StatusMaintenance],
|
53
53
|
binding_state: S3ComponentBindingState,
|
54
54
|
) -> None:
|
55
|
-
now = datetime.now(
|
55
|
+
now = datetime.now(UTC)
|
56
56
|
slack = slackapi_from_queries(QONTRACT_INTEGRATION, init_usergroups=False)
|
57
57
|
for m in desired_state:
|
58
58
|
scheduled_start = datetime.fromisoformat(m.schedule_start)
|
@@ -68,7 +68,7 @@ class StatusPageMaintenancesIntegration(QontractReconcileIntegration[NoParams]):
|
|
68
68
|
def run(self, dry_run: bool = False) -> None:
|
69
69
|
binding_state = get_binding_state(self.name, self.secret_reader)
|
70
70
|
pages = get_status_pages()
|
71
|
-
now = datetime.now(
|
71
|
+
now = datetime.now(UTC)
|
72
72
|
|
73
73
|
error = False
|
74
74
|
for p in pages:
|
reconcile/statuspage/page.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import
|
1
|
+
from typing import Self, cast
|
2
2
|
|
3
3
|
from pydantic import BaseModel
|
4
4
|
|
@@ -25,8 +25,8 @@ class StatusComponent(BaseModel):
|
|
25
25
|
|
26
26
|
name: str
|
27
27
|
display_name: str
|
28
|
-
description:
|
29
|
-
group_name:
|
28
|
+
description: str | None
|
29
|
+
group_name: str | None
|
30
30
|
status_provider_configs: list[StatusProvider]
|
31
31
|
"""
|
32
32
|
Status provider configs hold different ways for a component to determine its status
|
@@ -39,7 +39,7 @@ class StatusComponent(BaseModel):
|
|
39
39
|
"""
|
40
40
|
return bool(self.status_provider_configs)
|
41
41
|
|
42
|
-
def desired_component_status(self) ->
|
42
|
+
def desired_component_status(self) -> str | None:
|
43
43
|
if self.status_management_enabled():
|
44
44
|
for provider in self.status_provider_configs:
|
45
45
|
status = provider.get_status()
|
@@ -53,7 +53,7 @@ class StatusComponent(BaseModel):
|
|
53
53
|
|
54
54
|
@classmethod
|
55
55
|
def init_from_page_component(
|
56
|
-
cls, component: StatusPageComponentV1, name_override:
|
56
|
+
cls, component: StatusPageComponentV1, name_override: str | None = None
|
57
57
|
) -> Self:
|
58
58
|
status_configs = [
|
59
59
|
build_status_provider_config(cfg) for cfg in component.status_config or []
|
@@ -106,9 +106,9 @@ class StatusMaintenanceAnnouncement(BaseModel):
|
|
106
106
|
Represents the desired state of a status maintenance.
|
107
107
|
"""
|
108
108
|
|
109
|
-
remind_subscribers:
|
110
|
-
notify_subscribers_on_start:
|
111
|
-
notify_subscribers_on_completion:
|
109
|
+
remind_subscribers: bool | None = None
|
110
|
+
notify_subscribers_on_start: bool | None = None
|
111
|
+
notify_subscribers_on_completion: bool | None = None
|
112
112
|
|
113
113
|
@classmethod
|
114
114
|
def init_from_announcement(
|
reconcile/statuspage/state.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
from typing import (
|
2
|
-
Optional,
|
3
2
|
Protocol,
|
4
3
|
)
|
5
4
|
|
@@ -13,9 +12,9 @@ from reconcile.utils.state import State
|
|
13
12
|
|
14
13
|
|
15
14
|
class ComponentBindingState(Protocol):
|
16
|
-
def get_id_for_component_name(self, component_name: str) ->
|
15
|
+
def get_id_for_component_name(self, component_name: str) -> str | None: ...
|
17
16
|
|
18
|
-
def get_name_for_component_id(self, component_id: str) ->
|
17
|
+
def get_name_for_component_id(self, component_id: str) -> str | None: ...
|
19
18
|
|
20
19
|
def bind_component(self, component_name: str, component_id: str) -> None: ...
|
21
20
|
|
@@ -33,10 +32,10 @@ class S3ComponentBindingState(ComponentBindingState):
|
|
33
32
|
v: k for k, v in self.name_to_id_cache.items()
|
34
33
|
}
|
35
34
|
|
36
|
-
def get_id_for_component_name(self, component_name: str) ->
|
35
|
+
def get_id_for_component_name(self, component_name: str) -> str | None:
|
37
36
|
return self.name_to_id_cache.get(component_name)
|
38
37
|
|
39
|
-
def get_name_for_component_id(self, component_id: str) ->
|
38
|
+
def get_name_for_component_id(self, component_id: str) -> str | None:
|
40
39
|
return self.id_to_name_cache.get(component_id)
|
41
40
|
|
42
41
|
def bind_component(self, component_name: str, component_id: str) -> None:
|
reconcile/statuspage/status.py
CHANGED
@@ -3,10 +3,9 @@ from abc import (
|
|
3
3
|
abstractmethod,
|
4
4
|
)
|
5
5
|
from datetime import (
|
6
|
+
UTC,
|
6
7
|
datetime,
|
7
|
-
timezone,
|
8
8
|
)
|
9
|
-
from typing import Optional
|
10
9
|
|
11
10
|
from dateutil.parser import isoparse
|
12
11
|
from pydantic import BaseModel
|
@@ -28,7 +27,7 @@ class StatusProvider(ABC):
|
|
28
27
|
"""
|
29
28
|
|
30
29
|
@abstractmethod
|
31
|
-
def get_status(self) ->
|
30
|
+
def get_status(self) -> str | None: ...
|
32
31
|
|
33
32
|
|
34
33
|
class ManualStatusProvider(StatusProvider, BaseModel):
|
@@ -38,13 +37,13 @@ class ManualStatusProvider(StatusProvider, BaseModel):
|
|
38
37
|
the component.
|
39
38
|
"""
|
40
39
|
|
41
|
-
start:
|
40
|
+
start: datetime | None = None
|
42
41
|
"""
|
43
42
|
The optional start time of the time window in which the manually
|
44
43
|
defined status is active.
|
45
44
|
"""
|
46
45
|
|
47
|
-
end:
|
46
|
+
end: datetime | None = None
|
48
47
|
"""
|
49
48
|
The optional end time of the time window in which the manually
|
50
49
|
defined status is active.
|
@@ -56,7 +55,7 @@ class ManualStatusProvider(StatusProvider, BaseModel):
|
|
56
55
|
time window is active or if no time window is defined.
|
57
56
|
"""
|
58
57
|
|
59
|
-
def get_status(self) ->
|
58
|
+
def get_status(self) -> str | None:
|
60
59
|
if self._is_active():
|
61
60
|
return self.component_status
|
62
61
|
return None
|
@@ -71,7 +70,7 @@ class ManualStatusProvider(StatusProvider, BaseModel):
|
|
71
70
|
raise ValueError(
|
72
71
|
"manual component status time window is invalid: end before start"
|
73
72
|
)
|
74
|
-
now = datetime.now(
|
73
|
+
now = datetime.now(UTC)
|
75
74
|
if self.start and now < self.start:
|
76
75
|
return False
|
77
76
|
if self.end and self.end < now:
|
@@ -81,7 +80,7 @@ class ManualStatusProvider(StatusProvider, BaseModel):
|
|
81
80
|
|
82
81
|
def build_status_provider_config(
|
83
82
|
cfg: StatusProviderV1,
|
84
|
-
) ->
|
83
|
+
) -> StatusProvider | None:
|
85
84
|
"""
|
86
85
|
Translates a status provider config from the desired state into
|
87
86
|
provider specific implementation that provides the status resolution logic.
|