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,6 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
import time
|
3
|
-
from typing import
|
3
|
+
from typing import Protocol, TextIO
|
4
4
|
|
5
5
|
from kubernetes.client import ( # type: ignore[attr-defined]
|
6
6
|
ApiClient,
|
@@ -85,7 +85,7 @@ class K8sJobController:
|
|
85
85
|
self.oc = oc
|
86
86
|
self.dry_run = dry_run
|
87
87
|
self.time_module = time_module
|
88
|
-
self._cache:
|
88
|
+
self._cache: dict[str, OpenshiftResource] | None = None
|
89
89
|
|
90
90
|
@property
|
91
91
|
def cache(self) -> dict[str, OpenshiftResource]:
|
@@ -111,7 +111,7 @@ class K8sJobController:
|
|
111
111
|
self._cache = new_cache
|
112
112
|
return self._cache
|
113
113
|
|
114
|
-
def get_job_generation(self, job_name: str) ->
|
114
|
+
def get_job_generation(self, job_name: str) -> str | None:
|
115
115
|
"""
|
116
116
|
Returns the generation annotation for a job.
|
117
117
|
"""
|
@@ -248,7 +248,7 @@ class K8sJobController:
|
|
248
248
|
return True
|
249
249
|
return False
|
250
250
|
|
251
|
-
def _lookup_job_uid(self, job_name: str) ->
|
251
|
+
def _lookup_job_uid(self, job_name: str) -> str | None:
|
252
252
|
job_resource = self.oc.get(
|
253
253
|
self.namespace, "Job", job_name, allow_not_found=True
|
254
254
|
)
|
@@ -256,7 +256,7 @@ class K8sJobController:
|
|
256
256
|
return None
|
257
257
|
return job_resource.get("metadata", {}).get("uid")
|
258
258
|
|
259
|
-
def build_secret(self, job: K8sJob) ->
|
259
|
+
def build_secret(self, job: K8sJob) -> V1Secret | None:
|
260
260
|
secret_data = job.secret_data()
|
261
261
|
script_data = job.scripts()
|
262
262
|
# fail if both dicts have overlapping keys
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import hashlib
|
2
2
|
import inspect
|
3
3
|
from abc import ABC, abstractmethod
|
4
|
-
from enum import
|
4
|
+
from enum import IntFlag, StrEnum
|
5
5
|
from typing import Any
|
6
6
|
|
7
7
|
from deepdiff import DeepHash
|
@@ -19,7 +19,7 @@ from kubernetes.client import (
|
|
19
19
|
)
|
20
20
|
|
21
21
|
|
22
|
-
class JobStatus(
|
22
|
+
class JobStatus(StrEnum):
|
23
23
|
SUCCESS: str = "SUCCESS"
|
24
24
|
ERROR: str = "ERROR"
|
25
25
|
IN_PROGRESS: str = "IN_PROGRESS"
|
reconcile/utils/jsonpath.py
CHANGED
@@ -4,7 +4,6 @@ from functools import (
|
|
4
4
|
reduce,
|
5
5
|
)
|
6
6
|
from itertools import zip_longest
|
7
|
-
from typing import Optional
|
8
7
|
|
9
8
|
import jsonpath_ng
|
10
9
|
import jsonpath_ng.ext.filter
|
@@ -54,11 +53,11 @@ def narrow_jsonpath_node(
|
|
54
53
|
if path_2.fields == ("*",):
|
55
54
|
return path_1
|
56
55
|
elif isinstance(path_1, jsonpath_ng.Index) and isinstance(
|
57
|
-
path_2,
|
56
|
+
path_2, jsonpath_ng.Slice | jsonpath_ng.ext.filter.Filter
|
58
57
|
):
|
59
58
|
return path_1
|
60
59
|
elif isinstance(
|
61
|
-
path_1,
|
60
|
+
path_1, jsonpath_ng.Slice | jsonpath_ng.ext.filter.Filter
|
62
61
|
) and isinstance(path_2, jsonpath_ng.Index):
|
63
62
|
return path_2
|
64
63
|
elif isinstance(path_1, jsonpath_ng.ext.filter.Filter) and isinstance(
|
@@ -119,7 +118,7 @@ def apply_constraint_to_path(
|
|
119
118
|
path: jsonpath_ng.JSONPath,
|
120
119
|
path_constraint: jsonpath_ng.JSONPath,
|
121
120
|
min_common_prefix_length: int = 1,
|
122
|
-
) ->
|
121
|
+
) -> jsonpath_ng.JSONPath | None:
|
123
122
|
"""
|
124
123
|
Narrow the `path` with a more specific `path_constraint`.
|
125
124
|
e.g. if the path constraints a slice `[*]` and the constraints a
|
@@ -148,7 +147,7 @@ def apply_constraint_to_path(
|
|
148
147
|
|
149
148
|
def remove_prefix_from_path(
|
150
149
|
path: jsonpath_ng.JSONPath, prefix: jsonpath_ng.JSONPath
|
151
|
-
) ->
|
150
|
+
) -> jsonpath_ng.JSONPath | None:
|
152
151
|
path_parts = jsonpath_parts(path, ignore_root=True)
|
153
152
|
prefix_parts = jsonpath_parts(prefix, ignore_root=True)
|
154
153
|
|
reconcile/utils/jump_host.py
CHANGED
@@ -4,7 +4,6 @@ import shutil
|
|
4
4
|
import tempfile
|
5
5
|
import threading
|
6
6
|
from dataclasses import dataclass
|
7
|
-
from typing import Optional
|
8
7
|
|
9
8
|
from sshtunnel import SSHTunnelForwarder
|
10
9
|
|
@@ -27,9 +26,9 @@ class JumphostParameters:
|
|
27
26
|
hostname: str
|
28
27
|
known_hosts: str
|
29
28
|
user: str
|
30
|
-
port:
|
31
|
-
remote_port:
|
32
|
-
local_port:
|
29
|
+
port: int | None
|
30
|
+
remote_port: int | None
|
31
|
+
local_port: int | None
|
33
32
|
key: str
|
34
33
|
|
35
34
|
|
@@ -60,7 +59,7 @@ class JumpHostSSH(JumpHostBase):
|
|
60
59
|
tunnel_lock = threading.Lock()
|
61
60
|
|
62
61
|
def __init__(
|
63
|
-
self, parameters: JumphostParameters, gql_api:
|
62
|
+
self, parameters: JumphostParameters, gql_api: gql.GqlApi | None = None
|
64
63
|
):
|
65
64
|
JumpHostBase.__init__(self, parameters=parameters)
|
66
65
|
|
@@ -75,7 +74,7 @@ class JumpHostSSH(JumpHostBase):
|
|
75
74
|
self._remote_port = parameters.remote_port
|
76
75
|
|
77
76
|
@property
|
78
|
-
def local_port(self) ->
|
77
|
+
def local_port(self) -> int | None:
|
79
78
|
return self._local_port
|
80
79
|
|
81
80
|
@staticmethod
|
@@ -102,7 +101,7 @@ class JumpHostSSH(JumpHostBase):
|
|
102
101
|
self.known_hosts_file = known_hosts_file
|
103
102
|
|
104
103
|
def get_ssh_base_cmd(self) -> list[str]:
|
105
|
-
user_host = "{}@{
|
104
|
+
user_host = f"{self._user}@{self._hostname}"
|
106
105
|
|
107
106
|
return [
|
108
107
|
"ssh",
|
@@ -115,7 +114,7 @@ class JumpHostSSH(JumpHostBase):
|
|
115
114
|
"-o",
|
116
115
|
"StrictHostKeyChecking=yes",
|
117
116
|
"-o",
|
118
|
-
"UserKnownHostsFile={
|
117
|
+
f"UserKnownHostsFile={self.known_hosts_file}",
|
119
118
|
"-i",
|
120
119
|
self._identity_file,
|
121
120
|
"-p",
|
reconcile/utils/keycloak.py
CHANGED
@@ -1,9 +1,5 @@
|
|
1
|
-
from
|
2
|
-
|
3
|
-
Iterable,
|
4
|
-
Optional,
|
5
|
-
Sequence,
|
6
|
-
)
|
1
|
+
from collections.abc import Iterable, Sequence
|
2
|
+
from typing import Any
|
7
3
|
|
8
4
|
import requests
|
9
5
|
from pydantic import BaseModel
|
@@ -31,7 +27,7 @@ class SSOClient(BaseModel):
|
|
31
27
|
|
32
28
|
class KeycloakInstance(BaseModel):
|
33
29
|
url: str
|
34
|
-
initial_access_token:
|
30
|
+
initial_access_token: str | None = None
|
35
31
|
|
36
32
|
|
37
33
|
class KeycloakAPI:
|
reconcile/utils/ldap_client.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
from collections import defaultdict
|
2
2
|
from collections.abc import Iterable
|
3
|
-
from typing import Optional
|
4
3
|
|
5
4
|
from ldap3 import (
|
6
5
|
ALL,
|
@@ -30,7 +29,7 @@ class LdapClient:
|
|
30
29
|
self.connection.unbind()
|
31
30
|
|
32
31
|
def get_users(self, uids: Iterable[str]) -> set[str]:
|
33
|
-
user_filter = "".join(
|
32
|
+
user_filter = "".join(f"(uid={u})" for u in uids)
|
34
33
|
_, _, results, _ = self.connection.search(
|
35
34
|
self.base_dn, f"(&(objectclass=person)(|{user_filter}))", attributes=["uid"]
|
36
35
|
)
|
@@ -66,7 +65,7 @@ class LdapClient:
|
|
66
65
|
|
67
66
|
@classmethod
|
68
67
|
def from_params(
|
69
|
-
cls, server_url: str, user:
|
68
|
+
cls, server_url: str, user: str | None, password: str | None, base_dn: str
|
70
69
|
) -> "LdapClient":
|
71
70
|
connection = Connection(
|
72
71
|
Server(server_url, get_info=ALL),
|
@@ -3,11 +3,7 @@ import logging
|
|
3
3
|
import os
|
4
4
|
import subprocess
|
5
5
|
from collections.abc import Mapping
|
6
|
-
from typing import
|
7
|
-
Any,
|
8
|
-
Optional,
|
9
|
-
Tuple,
|
10
|
-
)
|
6
|
+
from typing import Any
|
11
7
|
|
12
8
|
|
13
9
|
def state_rm_access_key(working_dirs, account, user):
|
@@ -15,13 +11,13 @@ def state_rm_access_key(working_dirs, account, user):
|
|
15
11
|
init_result = subprocess.run(["terraform", "init"], check=False, cwd=wd)
|
16
12
|
if init_result.returncode != 0:
|
17
13
|
return False
|
18
|
-
resource = "aws_iam_access_key.{}"
|
14
|
+
resource = f"aws_iam_access_key.{user}"
|
19
15
|
result = subprocess.run(["terraform", "state", "rm", resource], check=False, cwd=wd)
|
20
16
|
return result.returncode == 0
|
21
17
|
|
22
18
|
|
23
19
|
def _compute_terraform_env(
|
24
|
-
env:
|
20
|
+
env: Mapping[str, str] | None = None,
|
25
21
|
) -> Mapping[str, str]:
|
26
22
|
default_env = os.environ.copy()
|
27
23
|
return default_env if env is None else {**default_env, **env}
|
@@ -30,8 +26,8 @@ def _compute_terraform_env(
|
|
30
26
|
def _terraform_command(
|
31
27
|
args: list[str],
|
32
28
|
working_dir: str,
|
33
|
-
env:
|
34
|
-
) ->
|
29
|
+
env: Mapping[str, str] | None = None,
|
30
|
+
) -> tuple[int, str, str]:
|
35
31
|
result = subprocess.run(
|
36
32
|
args,
|
37
33
|
capture_output=True,
|
@@ -66,8 +62,8 @@ def show_json(working_dir: str, path: str) -> dict[str, Any]:
|
|
66
62
|
|
67
63
|
def init(
|
68
64
|
working_dir: str,
|
69
|
-
env:
|
70
|
-
) ->
|
65
|
+
env: Mapping[str, str] | None = None,
|
66
|
+
) -> tuple[int, str, str]:
|
71
67
|
"""
|
72
68
|
Run terraform init -input=false -no-color.
|
73
69
|
|
@@ -84,8 +80,8 @@ def init(
|
|
84
80
|
|
85
81
|
def output(
|
86
82
|
working_dir: str,
|
87
|
-
env:
|
88
|
-
) ->
|
83
|
+
env: Mapping[str, str] | None = None,
|
84
|
+
) -> tuple[int, str, str]:
|
89
85
|
"""
|
90
86
|
Run terraform output -json.
|
91
87
|
|
@@ -103,8 +99,8 @@ def output(
|
|
103
99
|
def plan(
|
104
100
|
working_dir: str,
|
105
101
|
out: str,
|
106
|
-
env:
|
107
|
-
) ->
|
102
|
+
env: Mapping[str, str] | None = None,
|
103
|
+
) -> tuple[int, str, str]:
|
108
104
|
"""
|
109
105
|
Run terraform plan -out=<out> -input=false -no-color.
|
110
106
|
|
@@ -123,8 +119,8 @@ def plan(
|
|
123
119
|
def apply(
|
124
120
|
working_dir: str,
|
125
121
|
dir_or_plan: str,
|
126
|
-
env:
|
127
|
-
) ->
|
122
|
+
env: Mapping[str, str] | None = None,
|
123
|
+
) -> tuple[int, str, str]:
|
128
124
|
"""
|
129
125
|
Run terraform apply -input=false -no-color <dir_or_plan>.
|
130
126
|
|
@@ -1,11 +1,8 @@
|
|
1
|
-
from collections.abc import Sequence
|
1
|
+
from collections.abc import Callable, Sequence
|
2
2
|
from typing import (
|
3
3
|
Any,
|
4
|
-
Callable,
|
5
|
-
Optional,
|
6
4
|
Protocol,
|
7
5
|
TypeVar,
|
8
|
-
Union,
|
9
6
|
)
|
10
7
|
|
11
8
|
from pydantic import (
|
@@ -34,7 +31,7 @@ class Bot(Protocol):
|
|
34
31
|
def name(self) -> str: ...
|
35
32
|
|
36
33
|
@property
|
37
|
-
def org_username(self) ->
|
34
|
+
def org_username(self) -> str | None: ...
|
38
35
|
|
39
36
|
def dict(self, *, by_alias: bool = False) -> dict[str, Any]: ...
|
40
37
|
|
@@ -50,21 +47,21 @@ class RoleWithMemberships(Protocol):
|
|
50
47
|
def bots(self) -> Sequence[Bot]: ...
|
51
48
|
|
52
49
|
@property
|
53
|
-
def member_sources(self) ->
|
50
|
+
def member_sources(self) -> Sequence[RoleMembershipSource] | None: ...
|
54
51
|
|
55
52
|
|
56
53
|
class RoleUser(BaseModel):
|
57
54
|
name: str
|
58
55
|
org_username: str
|
59
|
-
github_username:
|
60
|
-
quay_username:
|
61
|
-
slack_username:
|
62
|
-
pagerduty_username:
|
63
|
-
aws_username:
|
64
|
-
cloudflare_user:
|
65
|
-
public_gpg_key:
|
66
|
-
tag_on_cluster_updates:
|
67
|
-
tag_on_merge_requests:
|
56
|
+
github_username: str | None
|
57
|
+
quay_username: str | None
|
58
|
+
slack_username: str | None
|
59
|
+
pagerduty_username: str | None
|
60
|
+
aws_username: str | None
|
61
|
+
cloudflare_user: str | None
|
62
|
+
public_gpg_key: str | None
|
63
|
+
tag_on_cluster_updates: bool | None = False
|
64
|
+
tag_on_merge_requests: bool | None = False
|
68
65
|
|
69
66
|
class Config:
|
70
67
|
extra = Extra.ignore
|
@@ -72,18 +69,18 @@ class RoleUser(BaseModel):
|
|
72
69
|
|
73
70
|
class RoleBot(BaseModel):
|
74
71
|
name: str
|
75
|
-
description:
|
76
|
-
org_username:
|
77
|
-
github_username:
|
78
|
-
gitlab_username:
|
79
|
-
openshift_serviceaccount:
|
80
|
-
quay_username:
|
72
|
+
description: str | None
|
73
|
+
org_username: str | None
|
74
|
+
github_username: str | None
|
75
|
+
gitlab_username: str | None
|
76
|
+
openshift_serviceaccount: str | None
|
77
|
+
quay_username: str | None
|
81
78
|
|
82
79
|
class Config:
|
83
80
|
extra = Extra.ignore
|
84
81
|
|
85
82
|
|
86
|
-
RoleMember =
|
83
|
+
RoleMember = RoleUser | RoleBot
|
87
84
|
|
88
85
|
ProviderGroup = tuple[str, str]
|
89
86
|
|
reconcile/utils/metrics.py
CHANGED
@@ -12,8 +12,6 @@ from collections.abc import (
|
|
12
12
|
from types import TracebackType
|
13
13
|
from typing import (
|
14
14
|
Any,
|
15
|
-
Optional,
|
16
|
-
Type,
|
17
15
|
TypeVar,
|
18
16
|
)
|
19
17
|
|
@@ -190,10 +188,10 @@ class MetricsContainer:
|
|
190
188
|
def __init__(
|
191
189
|
self,
|
192
190
|
) -> None:
|
193
|
-
self._gauges: dict[
|
191
|
+
self._gauges: dict[type[GaugeMetric], dict[Sequence[str], float]] = defaultdict(
|
194
192
|
dict
|
195
193
|
)
|
196
|
-
self._counters: dict[
|
194
|
+
self._counters: dict[type[CounterMetric], dict[Sequence[str], float]] = (
|
197
195
|
defaultdict(dict)
|
198
196
|
)
|
199
197
|
|
@@ -236,7 +234,7 @@ class MetricsContainer:
|
|
236
234
|
|
237
235
|
T = TypeVar("T", bound=BaseMetric)
|
238
236
|
|
239
|
-
def get_metric_value(self, metric_class:
|
237
|
+
def get_metric_value(self, metric_class: type[T], **kwargs: Any) -> float | None:
|
240
238
|
"""
|
241
239
|
Finds a unique match for the metrics class and labels, and returns its value.
|
242
240
|
If more than one match is found, a ValueError is raised.
|
@@ -252,7 +250,7 @@ class MetricsContainer:
|
|
252
250
|
return None
|
253
251
|
|
254
252
|
def get_metrics(
|
255
|
-
self, metric_class:
|
253
|
+
self, metric_class: type[T], **kwargs: Any
|
256
254
|
) -> list[tuple[T, float]]:
|
257
255
|
"""
|
258
256
|
Returns all metrics of the given class from this container and all its scopes,
|
@@ -383,7 +381,7 @@ class _MetricsContext:
|
|
383
381
|
|
384
382
|
def __init__(
|
385
383
|
self,
|
386
|
-
scope:
|
384
|
+
scope: Hashable | None,
|
387
385
|
parent: MetricsContainer,
|
388
386
|
aggregate_counters: bool,
|
389
387
|
):
|
@@ -408,9 +406,9 @@ class _MetricsContext:
|
|
408
406
|
|
409
407
|
def __exit__(
|
410
408
|
self,
|
411
|
-
exc_type:
|
412
|
-
exc_value:
|
413
|
-
traceback:
|
409
|
+
exc_type: type[BaseException] | None,
|
410
|
+
exc_value: BaseException | None,
|
411
|
+
traceback: TracebackType | None,
|
414
412
|
) -> None:
|
415
413
|
if self.scope:
|
416
414
|
self.parent._scopes[self.scope] = self.container
|
@@ -420,8 +418,8 @@ class _MetricsContext:
|
|
420
418
|
|
421
419
|
|
422
420
|
def transactional_metrics(
|
423
|
-
scope:
|
424
|
-
parent_container:
|
421
|
+
scope: Hashable | None = None,
|
422
|
+
parent_container: MetricsContainer | None = None,
|
425
423
|
aggregate_counters: bool = True,
|
426
424
|
) -> _MetricsContext:
|
427
425
|
"""
|
@@ -562,9 +560,9 @@ class ErrorRateMetricSet:
|
|
562
560
|
|
563
561
|
def __exit__(
|
564
562
|
self: ERMS,
|
565
|
-
exc_type:
|
566
|
-
exc_value:
|
567
|
-
traceback:
|
563
|
+
exc_type: type[BaseException] | None,
|
564
|
+
exc_value: BaseException | None,
|
565
|
+
traceback: TracebackType | None,
|
568
566
|
) -> None:
|
569
567
|
if exc_value:
|
570
568
|
self.fail(exc_value)
|
reconcile/utils/mr/base.py
CHANGED
@@ -4,11 +4,7 @@ from abc import (
|
|
4
4
|
ABC,
|
5
5
|
abstractmethod,
|
6
6
|
)
|
7
|
-
from typing import
|
8
|
-
Any,
|
9
|
-
Optional,
|
10
|
-
Union,
|
11
|
-
)
|
7
|
+
from typing import Any
|
12
8
|
from uuid import uuid4
|
13
9
|
|
14
10
|
from gitlab.exceptions import GitlabError
|
@@ -36,7 +32,7 @@ class MergeRequestProcessingError(Exception):
|
|
36
32
|
"""
|
37
33
|
|
38
34
|
|
39
|
-
MRClient =
|
35
|
+
MRClient = GitLabApi | SQSGateway
|
40
36
|
|
41
37
|
|
42
38
|
class MergeRequestBase(ABC):
|
@@ -211,7 +207,7 @@ class MergeRequestBase(ABC):
|
|
211
207
|
from_=gitlab_cli.main_branch, to=self.branch
|
212
208
|
)["diffs"]
|
213
209
|
|
214
|
-
def submit(self, cli: MRClient) ->
|
210
|
+
def submit(self, cli: MRClient) -> Any | None:
|
215
211
|
if isinstance(cli, GitLabApi):
|
216
212
|
return self.submit_to_gitlab(gitlab_cli=cli)
|
217
213
|
|
@@ -226,10 +222,10 @@ def app_interface_email(
|
|
226
222
|
name: str,
|
227
223
|
subject: str,
|
228
224
|
body: str,
|
229
|
-
users:
|
230
|
-
aliases:
|
231
|
-
aws_accounts:
|
232
|
-
apps:
|
225
|
+
users: list[str] | None = None,
|
226
|
+
aliases: list[str] | None = None,
|
227
|
+
aws_accounts: list[str] | None = None,
|
228
|
+
apps: list[str] | None = None,
|
233
229
|
) -> str:
|
234
230
|
"""Render app-interface-email template."""
|
235
231
|
with open(EMAIL_TEMPLATE, encoding="locale") as file_obj:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
from collections.abc import Sequence
|
3
|
-
from datetime import
|
3
|
+
from datetime import UTC, date
|
4
4
|
from datetime import datetime as dt
|
5
5
|
from pathlib import Path
|
6
6
|
|
@@ -60,7 +60,7 @@ class UpdateGlitchtipAccessReport(MergeRequestBase):
|
|
60
60
|
self._glitchtip_access_revalidation_workbook = str(
|
61
61
|
glitchtip_access_revalidation_workbook
|
62
62
|
)
|
63
|
-
self._isodate = dt.now(tz=
|
63
|
+
self._isodate = dt.now(tz=UTC).isoformat()
|
64
64
|
self._dry_run = dry_run
|
65
65
|
|
66
66
|
@property
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
from datetime import datetime
|
3
3
|
from pathlib import Path
|
4
|
-
from typing import Optional
|
5
4
|
|
6
5
|
from pydantic import BaseModel
|
7
6
|
|
@@ -32,7 +31,7 @@ class CreateAppInterfaceNotificator(MergeRequestBase):
|
|
32
31
|
def __init__(
|
33
32
|
self,
|
34
33
|
notification: Notification,
|
35
|
-
labels:
|
34
|
+
labels: list[str] | None = None,
|
36
35
|
email_base_path: Path = Path("data") / "app-interface" / "emails",
|
37
36
|
dry_run: bool = False,
|
38
37
|
):
|