qontract-reconcile 0.10.1rc884__py3-none-any.whl → 0.10.1rc886__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.1rc886.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/RECORD +279 -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 +31 -17
- tools/saas_promotion_state/__init__.py +0 -0
- tools/saas_promotion_state/saas_promotion_state.py +72 -0
- tools/template_validation.py +1 -1
- tools/test/conftest.py +45 -6
- tools/test/test_saas_promotion_state.py +86 -0
- {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/top_level.txt +0 -0
reconcile/dashdotdb_base.py
CHANGED
@@ -3,10 +3,7 @@ import os
|
|
3
3
|
from base64 import b64encode
|
4
4
|
from collections.abc import Mapping
|
5
5
|
from dataclasses import dataclass
|
6
|
-
from typing import
|
7
|
-
Any,
|
8
|
-
Optional,
|
9
|
-
)
|
6
|
+
from typing import Any
|
10
7
|
from urllib.parse import urljoin
|
11
8
|
|
12
9
|
import requests
|
@@ -23,8 +20,8 @@ LOG = logging.getLogger(__name__)
|
|
23
20
|
class DashdotDBSecret:
|
24
21
|
path: str
|
25
22
|
field: str
|
26
|
-
q_format:
|
27
|
-
version:
|
23
|
+
q_format: str | None
|
24
|
+
version: int | None
|
28
25
|
|
29
26
|
|
30
27
|
DASHDOTDB_SECRET = DashdotDBSecret(
|
@@ -53,7 +50,7 @@ class DashdotdbBase:
|
|
53
50
|
self.dashdotdb_pass = self.secret_content["password"]
|
54
51
|
self.logmarker = marker
|
55
52
|
self.scope = scope
|
56
|
-
self.dashdotdb_token
|
53
|
+
self.dashdotdb_token: str | None
|
57
54
|
|
58
55
|
def _get_token(self) -> None:
|
59
56
|
if self.dry_run:
|
@@ -134,10 +131,10 @@ class DashdotdbBase:
|
|
134
131
|
def _promget(
|
135
132
|
self,
|
136
133
|
url: str,
|
137
|
-
params:
|
138
|
-
token:
|
139
|
-
username:
|
140
|
-
password:
|
134
|
+
params: Mapping[Any, Any] | None,
|
135
|
+
token: str | None = None,
|
136
|
+
username: str | None = None,
|
137
|
+
password: str | None = None,
|
141
138
|
ssl_verify: bool = True,
|
142
139
|
uri: str = "api/v1/query",
|
143
140
|
) -> dict[Any, Any]:
|
reconcile/dashdotdb_cso.py
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
from typing import
|
2
|
-
Any,
|
3
|
-
Optional,
|
4
|
-
)
|
1
|
+
from typing import Any
|
5
2
|
|
6
3
|
import requests
|
7
4
|
from sretoolbox.utils import threaded
|
@@ -44,7 +41,7 @@ class DashdotdbCSO(DashdotdbBase):
|
|
44
41
|
secret_reader=secret_reader,
|
45
42
|
)
|
46
43
|
|
47
|
-
def _post(self, manifest: dict[Any, Any]) ->
|
44
|
+
def _post(self, manifest: dict[Any, Any]) -> requests.Response | None:
|
48
45
|
if manifest is None:
|
49
46
|
return None
|
50
47
|
|
@@ -70,7 +67,7 @@ class DashdotdbCSO(DashdotdbBase):
|
|
70
67
|
return response
|
71
68
|
|
72
69
|
@staticmethod
|
73
|
-
def _get_imagemanifestvuln(cluster: str, oc_map: OCMap) ->
|
70
|
+
def _get_imagemanifestvuln(cluster: str, oc_map: OCMap) -> dict[str, Any] | None:
|
74
71
|
LOG.info("%s processing %s", LOGMARKER, cluster)
|
75
72
|
oc = oc_map.get(cluster)
|
76
73
|
if isinstance(oc, OCLogMsg):
|
reconcile/dashdotdb_dora.py
CHANGED
@@ -1,17 +1,15 @@
|
|
1
1
|
import functools
|
2
2
|
import os
|
3
3
|
from collections import defaultdict
|
4
|
+
from collections.abc import Iterable, Mapping
|
4
5
|
from dataclasses import dataclass
|
5
6
|
from datetime import (
|
7
|
+
UTC,
|
6
8
|
datetime,
|
7
9
|
timedelta,
|
8
|
-
timezone,
|
9
10
|
)
|
10
11
|
from typing import (
|
11
12
|
Any,
|
12
|
-
Iterable,
|
13
|
-
Mapping,
|
14
|
-
Optional,
|
15
13
|
Self,
|
16
14
|
)
|
17
15
|
|
@@ -44,8 +42,8 @@ QONTRACT_INTEGRATION = "dashdotdb-dora"
|
|
44
42
|
class DeploymentDBSecret:
|
45
43
|
path: str
|
46
44
|
field: str
|
47
|
-
q_format:
|
48
|
-
version:
|
45
|
+
q_format: str | None
|
46
|
+
version: int | None
|
49
47
|
|
50
48
|
|
51
49
|
@dataclass(eq=True, frozen=True)
|
@@ -76,9 +74,9 @@ class SaasTarget:
|
|
76
74
|
|
77
75
|
@dataclass(eq=True, frozen=True)
|
78
76
|
class RepoChanges:
|
79
|
-
repo_url:
|
80
|
-
ref_from:
|
81
|
-
ref_to:
|
77
|
+
repo_url: str | None
|
78
|
+
ref_from: str | None
|
79
|
+
ref_to: str | None
|
82
80
|
|
83
81
|
|
84
82
|
@dataclass(eq=True, frozen=True)
|
@@ -162,12 +160,10 @@ class Commit:
|
|
162
160
|
finish_timestamp_tzaware = finish_timestamp
|
163
161
|
|
164
162
|
if commit_date_tzaware.tzinfo is None:
|
165
|
-
commit_date_tzaware = commit_date_tzaware.replace(tzinfo=
|
163
|
+
commit_date_tzaware = commit_date_tzaware.replace(tzinfo=UTC)
|
166
164
|
|
167
165
|
if finish_timestamp_tzaware.tzinfo is None:
|
168
|
-
finish_timestamp_tzaware = finish_timestamp_tzaware.replace(
|
169
|
-
tzinfo=timezone.utc
|
170
|
-
)
|
166
|
+
finish_timestamp_tzaware = finish_timestamp_tzaware.replace(tzinfo=UTC)
|
171
167
|
|
172
168
|
return int((finish_timestamp_tzaware - commit_date_tzaware).total_seconds())
|
173
169
|
|
@@ -397,7 +393,7 @@ class DashdotdbDORA(DashdotdbBase):
|
|
397
393
|
|
398
394
|
def get_repo_ref_for_sha(
|
399
395
|
self, saastarget: SaasTarget, sha: str
|
400
|
-
) -> tuple[
|
396
|
+
) -> tuple[str | None, str | None]:
|
401
397
|
try:
|
402
398
|
saas_file_yaml = self.gl_app_interface_get_file(
|
403
399
|
saastarget.path, ref=sha
|
reconcile/dashdotdb_dvo.py
CHANGED
@@ -4,10 +4,7 @@ from collections.abc import (
|
|
4
4
|
Sequence,
|
5
5
|
)
|
6
6
|
from dataclasses import dataclass
|
7
|
-
from typing import
|
8
|
-
Any,
|
9
|
-
Optional,
|
10
|
-
)
|
7
|
+
from typing import Any
|
11
8
|
|
12
9
|
import requests
|
13
10
|
from requests import Response
|
@@ -67,7 +64,7 @@ class DashdotdbDVO(DashdotdbBase):
|
|
67
64
|
for i in range(0, len(data), int(size)):
|
68
65
|
yield data[i : i + int(size)]
|
69
66
|
|
70
|
-
def _post(self, deploymentvalidation: DVOPayload) ->
|
67
|
+
def _post(self, deploymentvalidation: DVOPayload) -> Response | None:
|
71
68
|
if deploymentvalidation is None:
|
72
69
|
return
|
73
70
|
cluster_name = deploymentvalidation.cluster_name
|
@@ -130,7 +127,7 @@ class DashdotdbDVO(DashdotdbBase):
|
|
130
127
|
|
131
128
|
def _get_deploymentvalidation(
|
132
129
|
self, metrics: list[str], cluster: ClusterV1
|
133
|
-
) ->
|
130
|
+
) -> DVOPayload | None:
|
134
131
|
prom_info = self._get_prometheus_info(cluster)
|
135
132
|
if not prom_info:
|
136
133
|
return None
|
@@ -162,8 +159,8 @@ class DashdotdbDVO(DashdotdbBase):
|
|
162
159
|
# via startswith and return only those that match.
|
163
160
|
# Returns a map of {cluster: cluster_name, data: [metric_names]}
|
164
161
|
def _get_validation_names(
|
165
|
-
self, cluster: ClusterV1, filter:
|
166
|
-
) ->
|
162
|
+
self, cluster: ClusterV1, filter: str | None = None
|
163
|
+
) -> ClusterValidationMetrics | None:
|
167
164
|
prom_info = self._get_prometheus_info(cluster)
|
168
165
|
if not prom_info:
|
169
166
|
return None
|
@@ -202,7 +199,7 @@ class DashdotdbDVO(DashdotdbBase):
|
|
202
199
|
metrics=deploymentvalidation["data"],
|
203
200
|
)
|
204
201
|
|
205
|
-
def _get_prometheus_info(self, cluster: ClusterV1) ->
|
202
|
+
def _get_prometheus_info(self, cluster: ClusterV1) -> PrometheusInfo | None:
|
206
203
|
if not cluster.automation_token:
|
207
204
|
LOG.error(
|
208
205
|
"%s cluster %s does not have an automation token",
|
@@ -217,14 +214,14 @@ class DashdotdbDVO(DashdotdbBase):
|
|
217
214
|
)
|
218
215
|
|
219
216
|
@staticmethod
|
220
|
-
def _get_clusters(name:
|
217
|
+
def _get_clusters(name: str | None = None) -> list[ClusterV1]:
|
221
218
|
return [
|
222
219
|
c for c in get_clusters_minimal(name=name) if c.ocm and c.prometheus_url
|
223
220
|
]
|
224
221
|
|
225
|
-
def run(self, cname:
|
222
|
+
def run(self, cname: str | None = None) -> None:
|
226
223
|
clusters = self._get_clusters(name=cname)
|
227
|
-
validation_list: list[
|
224
|
+
validation_list: list[ClusterValidationMetrics | None] = threaded.run(
|
228
225
|
func=self._get_validation_names,
|
229
226
|
iterable=clusters,
|
230
227
|
thread_pool_size=self.thread_pool_size,
|
@@ -258,7 +255,7 @@ class DashdotdbDVO(DashdotdbBase):
|
|
258
255
|
def run(
|
259
256
|
dry_run: bool = False,
|
260
257
|
thread_pool_size: int = 10,
|
261
|
-
cluster_name:
|
258
|
+
cluster_name: str | None = None,
|
262
259
|
) -> None:
|
263
260
|
vault_settings = get_app_interface_vault_settings()
|
264
261
|
secret_reader = create_secret_reader(use_vault=vault_settings.vault)
|
reconcile/dashdotdb_slo.py
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
from collections.abc import Iterable
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import
|
4
|
-
Any,
|
5
|
-
Optional,
|
6
|
-
)
|
3
|
+
from typing import Any
|
7
4
|
|
8
5
|
import jinja2
|
9
6
|
import requests
|
@@ -72,7 +69,7 @@ class DashdotdbSLO(DashdotdbBase):
|
|
72
69
|
secret_reader=secret_reader,
|
73
70
|
)
|
74
71
|
|
75
|
-
def _post(self, service_slos: Iterable[ServiceSLO]) ->
|
72
|
+
def _post(self, service_slos: Iterable[ServiceSLO]) -> Response | None:
|
76
73
|
for item in service_slos:
|
77
74
|
LOG.debug(f"About to POST SLO JSON item to dashdotDB:\n{item}\n")
|
78
75
|
|
@@ -106,9 +103,9 @@ class DashdotdbSLO(DashdotdbBase):
|
|
106
103
|
continue
|
107
104
|
|
108
105
|
ns = namespace_access.namespace
|
109
|
-
promtoken:
|
110
|
-
username:
|
111
|
-
password:
|
106
|
+
promtoken: str | None = None
|
107
|
+
username: str | None = None
|
108
|
+
password: str | None = None
|
112
109
|
if namespace_access.prometheus_access:
|
113
110
|
promurl = namespace_access.prometheus_access.url
|
114
111
|
username = self.secret_reader.read_secret(
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import base64
|
2
2
|
import logging
|
3
|
+
from collections.abc import Callable
|
3
4
|
from random import choices
|
4
5
|
from string import (
|
5
6
|
ascii_letters,
|
@@ -7,8 +8,6 @@ from string import (
|
|
7
8
|
)
|
8
9
|
from typing import (
|
9
10
|
Any,
|
10
|
-
Callable,
|
11
|
-
Optional,
|
12
11
|
TypedDict,
|
13
12
|
cast,
|
14
13
|
)
|
@@ -57,7 +56,7 @@ JOB_PSQL_ENGINE_VERSION = "15.4-alpine"
|
|
57
56
|
|
58
57
|
|
59
58
|
def get_database_access_namespaces(
|
60
|
-
query_func:
|
59
|
+
query_func: Callable | None = None,
|
61
60
|
) -> list[NamespaceV1]:
|
62
61
|
if not query_func:
|
63
62
|
query_func = gql.get_api().query
|
@@ -74,7 +73,7 @@ class DatabaseConnectionParameters(BaseModel):
|
|
74
73
|
|
75
74
|
class PSQLScriptGenerator(BaseModel):
|
76
75
|
db_access: DatabaseAccessV1
|
77
|
-
current_db_access:
|
76
|
+
current_db_access: DatabaseAccessV1 | None
|
78
77
|
connection_parameter: DatabaseConnectionParameters
|
79
78
|
admin_connection_parameter: DatabaseConnectionParameters
|
80
79
|
engine: str
|
@@ -426,7 +425,7 @@ def _populate_resources(
|
|
426
425
|
settings: dict[Any, Any],
|
427
426
|
user_connection: DatabaseConnectionParameters,
|
428
427
|
admin_connection: DatabaseConnectionParameters,
|
429
|
-
current_db_access:
|
428
|
+
current_db_access: DatabaseAccessV1 | None = None,
|
430
429
|
) -> list[DBAMResource]:
|
431
430
|
if user_connection.database == admin_connection.database:
|
432
431
|
raise ValueError(f"Can not use default database {admin_connection.database}")
|
@@ -594,7 +593,7 @@ def _process_db_access(
|
|
594
593
|
if not _db_access_acccess_is_valid(db_access):
|
595
594
|
raise ValueError("Duplicate schema in access list.")
|
596
595
|
|
597
|
-
current_db_access:
|
596
|
+
current_db_access: DatabaseAccessV1 | None = None
|
598
597
|
if state.exists(db_access.name):
|
599
598
|
current_state = state.get(db_access.name)
|
600
599
|
if current_state == db_access.dict(by_alias=True):
|
@@ -1,12 +1,9 @@
|
|
1
1
|
import base64
|
2
2
|
import logging
|
3
3
|
import sys
|
4
|
-
from collections.abc import Iterable
|
4
|
+
from collections.abc import Iterable, Mapping
|
5
5
|
from datetime import timedelta
|
6
|
-
from typing import
|
7
|
-
Any,
|
8
|
-
Mapping,
|
9
|
-
)
|
6
|
+
from typing import Any
|
10
7
|
|
11
8
|
from dynatrace import Dynatrace
|
12
9
|
from dynatrace.environment_v2.tokens_api import ApiTokenCreated
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import json
|
2
2
|
import logging
|
3
3
|
from collections.abc import Iterable
|
4
|
-
from datetime import
|
5
|
-
from enum import
|
4
|
+
from datetime import UTC, datetime
|
5
|
+
from enum import StrEnum
|
6
6
|
|
7
7
|
from sretoolbox.utils import threaded
|
8
8
|
|
@@ -73,7 +73,7 @@ def setup_factories(
|
|
73
73
|
return of
|
74
74
|
|
75
75
|
|
76
|
-
class ReconcileAction(
|
76
|
+
class ReconcileAction(StrEnum):
|
77
77
|
NOOP = "NOOP"
|
78
78
|
APPLY_NOT_EXISTS = "Resource does not exist"
|
79
79
|
APPLY_ERROR = "Resource status in ERROR state"
|
@@ -260,7 +260,7 @@ class ExternalResourcesManager:
|
|
260
260
|
return need_secret_sync
|
261
261
|
|
262
262
|
def _update_state(self, r: Reconciliation, state: ExternalResourceState) -> None:
|
263
|
-
state.ts = datetime.now(
|
263
|
+
state.ts = datetime.now(UTC)
|
264
264
|
if r.action == Action.APPLY:
|
265
265
|
state.resource_status = ResourceStatus.IN_PROGRESS
|
266
266
|
elif r.action == Action.DESTROY:
|
@@ -9,7 +9,7 @@ from collections.abc import (
|
|
9
9
|
Iterator,
|
10
10
|
MutableMapping,
|
11
11
|
)
|
12
|
-
from enum import
|
12
|
+
from enum import StrEnum
|
13
13
|
from typing import Any
|
14
14
|
|
15
15
|
from pydantic import BaseModel
|
@@ -82,7 +82,7 @@ class ExternalResourcesInventory(MutableMapping):
|
|
82
82
|
for (p, ns) in desired_providers
|
83
83
|
for r in p.resources
|
84
84
|
if isinstance(
|
85
|
-
r,
|
85
|
+
r, NamespaceTerraformResourceRDSV1 | NamespaceTerraformResourceRoleV1
|
86
86
|
)
|
87
87
|
and r.managed_by_erv2
|
88
88
|
]
|
@@ -123,7 +123,7 @@ class ExternalResourcesInventory(MutableMapping):
|
|
123
123
|
raise FetchResourceError(msg)
|
124
124
|
|
125
125
|
|
126
|
-
class Action(
|
126
|
+
class Action(StrEnum):
|
127
127
|
DESTROY: str = "Destroy"
|
128
128
|
APPLY: str = "Apply"
|
129
129
|
|
@@ -3,9 +3,9 @@ import json
|
|
3
3
|
import logging
|
4
4
|
from abc import abstractmethod
|
5
5
|
from collections.abc import Iterable, Mapping
|
6
|
-
from datetime import
|
6
|
+
from datetime import UTC, datetime
|
7
7
|
from hashlib import shake_128
|
8
|
-
from typing import Any
|
8
|
+
from typing import Any
|
9
9
|
|
10
10
|
from pydantic import BaseModel
|
11
11
|
from sretoolbox.utils import threaded
|
@@ -45,8 +45,8 @@ class VaultSecret(BaseModel):
|
|
45
45
|
|
46
46
|
path: str
|
47
47
|
field: str
|
48
|
-
version:
|
49
|
-
q_format:
|
48
|
+
version: int | None
|
49
|
+
q_format: str | None
|
50
50
|
|
51
51
|
|
52
52
|
class SecretHelper:
|
@@ -324,7 +324,7 @@ class InClusterSecretsReconciler(SecretsReconciler):
|
|
324
324
|
else:
|
325
325
|
data[k] = decoded
|
326
326
|
|
327
|
-
spec.metadata[SECRET_UPDATED_AT] = datetime.now(
|
327
|
+
spec.metadata[SECRET_UPDATED_AT] = datetime.now(UTC).strftime(
|
328
328
|
SECRET_UPDATED_AT_TIMEFORMAT
|
329
329
|
)
|
330
330
|
spec.secret = data
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import logging
|
2
2
|
from collections.abc import Mapping
|
3
|
-
from datetime import
|
4
|
-
from enum import
|
3
|
+
from datetime import UTC, datetime
|
4
|
+
from enum import StrEnum
|
5
5
|
from typing import Any
|
6
6
|
|
7
7
|
from pydantic import BaseModel
|
@@ -20,14 +20,14 @@ class StateNotFoundError(Exception):
|
|
20
20
|
pass
|
21
21
|
|
22
22
|
|
23
|
-
class ReconcileStatus(
|
23
|
+
class ReconcileStatus(StrEnum):
|
24
24
|
SUCCESS: str = "SUCCESS"
|
25
25
|
ERROR: str = "ERROR"
|
26
26
|
IN_PROGRESS: str = "IN_PROGRESS"
|
27
27
|
NOT_EXISTS: str = "NOT_EXISTS"
|
28
28
|
|
29
29
|
|
30
|
-
class ResourceStatus(
|
30
|
+
class ResourceStatus(StrEnum):
|
31
31
|
CREATED: str = "CREATED"
|
32
32
|
DELETED: str = "DELETED"
|
33
33
|
ABANDONED: str = "ABANDONED"
|
@@ -198,7 +198,7 @@ class ExternalResourcesStateDynamoDB:
|
|
198
198
|
else:
|
199
199
|
return ExternalResourceState(
|
200
200
|
key=key,
|
201
|
-
ts=datetime.now(
|
201
|
+
ts=datetime.now(UTC),
|
202
202
|
resource_status=ResourceStatus.NOT_EXISTS,
|
203
203
|
reconciliation=Reconciliation(key=key),
|
204
204
|
reconciliation_errors=0,
|
@@ -10,10 +10,7 @@ from datetime import (
|
|
10
10
|
date,
|
11
11
|
datetime,
|
12
12
|
)
|
13
|
-
from typing import
|
14
|
-
Any,
|
15
|
-
Optional,
|
16
|
-
)
|
13
|
+
from typing import Any
|
17
14
|
|
18
15
|
import reconcile.openshift_base as ob
|
19
16
|
from reconcile import queries
|
@@ -114,9 +111,9 @@ def fetch_desired_state(
|
|
114
111
|
def run(
|
115
112
|
dry_run: bool,
|
116
113
|
thread_pool_size: int = 10,
|
117
|
-
internal:
|
114
|
+
internal: bool | None = None,
|
118
115
|
use_jump_host: bool = True,
|
119
|
-
defer:
|
116
|
+
defer: Callable | None = None,
|
120
117
|
) -> None:
|
121
118
|
gabi_instances = queries.get_gabi_instances()
|
122
119
|
if not gabi_instances:
|
reconcile/gcr_mirror.py
CHANGED
@@ -241,7 +241,7 @@ class QuayMirror:
|
|
241
241
|
control_file_name = "qontract-reconcile-gcr-mirror.timestamp"
|
242
242
|
control_file_path = os.path.join(tempfile.gettempdir(), control_file_name)
|
243
243
|
try:
|
244
|
-
with open(control_file_path,
|
244
|
+
with open(control_file_path, encoding="locale") as file_obj:
|
245
245
|
last_deep_sync = float(file_obj.read())
|
246
246
|
except FileNotFoundError:
|
247
247
|
self._record_timestamp(control_file_path)
|
reconcile/github_org.py
CHANGED
@@ -438,9 +438,7 @@ def run(dry_run):
|
|
438
438
|
|
439
439
|
assert (
|
440
440
|
current_orgs == desired_orgs
|
441
|
-
), "Current orgs ({}) don't match desired orgs ({})"
|
442
|
-
current_orgs, desired_orgs
|
443
|
-
)
|
441
|
+
), f"Current orgs ({current_orgs}) don't match desired orgs ({desired_orgs})"
|
444
442
|
|
445
443
|
# Calculate diff
|
446
444
|
diff = current_state.diff(desired_state)
|
reconcile/github_repo_invites.py
CHANGED
@@ -5,10 +5,7 @@ from collections.abc import (
|
|
5
5
|
Mapping,
|
6
6
|
)
|
7
7
|
from dataclasses import dataclass
|
8
|
-
from typing import
|
9
|
-
Any,
|
10
|
-
Optional,
|
11
|
-
)
|
8
|
+
from typing import Any
|
12
9
|
|
13
10
|
from reconcile import queries
|
14
11
|
from reconcile.utils import (
|
@@ -27,7 +24,7 @@ class CodeComponents:
|
|
27
24
|
|
28
25
|
|
29
26
|
def _parse_code_components(
|
30
|
-
raw:
|
27
|
+
raw: Iterable[Mapping[str, Any]] | None,
|
31
28
|
) -> CodeComponents:
|
32
29
|
urls = set()
|
33
30
|
known_orgs = set()
|
reconcile/gitlab_housekeeping.py
CHANGED
@@ -9,11 +9,7 @@ from datetime import (
|
|
9
9
|
timedelta,
|
10
10
|
)
|
11
11
|
from operator import itemgetter
|
12
|
-
from typing import
|
13
|
-
Any,
|
14
|
-
Optional,
|
15
|
-
Union,
|
16
|
-
)
|
12
|
+
from typing import Any
|
17
13
|
|
18
14
|
import gitlab
|
19
15
|
from gitlab.v4.objects import (
|
@@ -178,7 +174,7 @@ def close_item(
|
|
178
174
|
gl: GitLabApi,
|
179
175
|
enable_closing: bool,
|
180
176
|
item_type: str,
|
181
|
-
item:
|
177
|
+
item: ProjectIssue | ProjectMergeRequest,
|
182
178
|
):
|
183
179
|
if enable_closing:
|
184
180
|
logging.info([
|
@@ -239,7 +235,7 @@ def handle_stale_items(
|
|
239
235
|
cancel_notes = [
|
240
236
|
n
|
241
237
|
for n in item.notes.list()
|
242
|
-
if n.attributes.get("body") == "/{} cancel"
|
238
|
+
if n.attributes.get("body") == f"/{LABEL} cancel"
|
243
239
|
]
|
244
240
|
if not cancel_notes:
|
245
241
|
continue
|
@@ -280,7 +276,7 @@ def is_rebased(mr, gl: GitLabApi) -> bool:
|
|
280
276
|
def get_merge_requests(
|
281
277
|
dry_run: bool,
|
282
278
|
gl: GitLabApi,
|
283
|
-
users_allowed_to_label:
|
279
|
+
users_allowed_to_label: Iterable[str] | None = None,
|
284
280
|
) -> list[dict[str, Any]]:
|
285
281
|
mrs = gl.get_merge_requests(state=MRState.OPENED)
|
286
282
|
return preprocess_merge_requests(
|
@@ -295,7 +291,7 @@ def preprocess_merge_requests(
|
|
295
291
|
dry_run: bool,
|
296
292
|
gl: GitLabApi,
|
297
293
|
project_merge_requests: list[ProjectMergeRequest],
|
298
|
-
users_allowed_to_label:
|
294
|
+
users_allowed_to_label: Iterable[str] | None = None,
|
299
295
|
) -> list[dict[str, Any]]:
|
300
296
|
results = []
|
301
297
|
for mr in project_merge_requests:
|
@@ -434,7 +430,7 @@ def rebase_merge_requests(
|
|
434
430
|
rebases += 1
|
435
431
|
rebased_merge_requests.labels(mr.target_project_id).inc()
|
436
432
|
except gitlab.exceptions.GitlabMRRebaseError as e:
|
437
|
-
logging.error("unable to rebase {}: {}"
|
433
|
+
logging.error(f"unable to rebase {mr.iid}: {e}")
|
438
434
|
else:
|
439
435
|
logging.info([
|
440
436
|
"rebase",
|
@@ -538,7 +534,7 @@ def merge_merge_requests(
|
|
538
534
|
return
|
539
535
|
merges += 1
|
540
536
|
except gitlab.exceptions.GitlabMRClosedError as e:
|
541
|
-
logging.error("unable to merge {}: {}"
|
537
|
+
logging.error(f"unable to merge {mr.iid}: {e}")
|
542
538
|
|
543
539
|
|
544
540
|
def get_app_sre_usernames(gl: GitLabApi) -> set[str]:
|
reconcile/gitlab_labeler.py
CHANGED
@@ -4,7 +4,6 @@ from collections.abc import (
|
|
4
4
|
Iterable,
|
5
5
|
Set,
|
6
6
|
)
|
7
|
-
from typing import Optional
|
8
7
|
|
9
8
|
from reconcile import queries
|
10
9
|
from reconcile.gitlab_housekeeping import (
|
@@ -48,7 +47,7 @@ def get_parents_list() -> set[str]:
|
|
48
47
|
|
49
48
|
def guess_onboarding_status(
|
50
49
|
changed_paths: Iterable[str], apps: dict[str, dict], parent_apps: set[str]
|
51
|
-
) ->
|
50
|
+
) -> str | None:
|
52
51
|
"""
|
53
52
|
Guess the service name of a given MR from the changed paths of the
|
54
53
|
MR. This will allow to add the onboarding status to the MR's as label
|
reconcile/gitlab_members.py
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
import enum
|
2
2
|
import logging
|
3
3
|
from collections.abc import Callable
|
4
|
-
from typing import
|
5
|
-
Any,
|
6
|
-
Optional,
|
7
|
-
)
|
4
|
+
from typing import Any
|
8
5
|
|
9
6
|
from pydantic import BaseModel
|
10
7
|
|
@@ -203,7 +200,7 @@ def get_gitlab_instance(query_func: Callable) -> GitlabInstanceV1:
|
|
203
200
|
@defer
|
204
201
|
def run(
|
205
202
|
dry_run: bool,
|
206
|
-
defer:
|
203
|
+
defer: Callable | None = None,
|
207
204
|
) -> None:
|
208
205
|
gqlapi = gql.get_api()
|
209
206
|
# queries
|
reconcile/gitlab_permissions.py
CHANGED
@@ -21,9 +21,7 @@ def get_members_to_add(repo, gl, app_sre):
|
|
21
21
|
if maintainers is None:
|
22
22
|
return []
|
23
23
|
if gl.user.username not in maintainers:
|
24
|
-
logging.error(
|
25
|
-
"'{}' is not shared with {} as 'Maintainer'".format(repo, gl.user.username)
|
26
|
-
)
|
24
|
+
logging.error(f"'{repo}' is not shared with {gl.user.username} as 'Maintainer'")
|
27
25
|
return []
|
28
26
|
members_to_add = [
|
29
27
|
{"user": u, "repo": repo} for u in app_sre if u.username not in maintainers
|
@@ -3,10 +3,7 @@ from collections.abc import (
|
|
3
3
|
Iterable,
|
4
4
|
Sequence,
|
5
5
|
)
|
6
|
-
from typing import
|
7
|
-
Any,
|
8
|
-
Optional,
|
9
|
-
)
|
6
|
+
from typing import Any
|
10
7
|
|
11
8
|
from reconcile.glitchtip.reconciler import GlitchtipReconciler
|
12
9
|
from reconcile.gql_definitions.glitchtip.glitchtip_instance import (
|
@@ -172,7 +169,7 @@ def get_internal_groups_client(
|
|
172
169
|
|
173
170
|
@defer
|
174
171
|
def run(
|
175
|
-
dry_run: bool, instance:
|
172
|
+
dry_run: bool, instance: str | None = None, defer: Callable | None = None
|
176
173
|
) -> None:
|
177
174
|
gqlapi = gql.get_api()
|
178
175
|
vault_settings = get_app_interface_vault_settings()
|