qontract-reconcile 0.10.1rc879__py3-none-any.whl → 0.10.1rc894__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/RECORD +291 -284
- reconcile/acs_rbac.py +1 -2
- reconcile/aus/advanced_upgrade_service.py +14 -14
- reconcile/aus/aus_label_source.py +1 -2
- reconcile/aus/base.py +23 -26
- reconcile/aus/cluster_version_data.py +4 -4
- reconcile/aus/models.py +2 -3
- reconcile/aus/version_gate_approver.py +2 -6
- reconcile/aus/version_gates/__init__.py +1 -3
- reconcile/aus/version_gates/sts_version_gate_handler.py +2 -3
- reconcile/aws_account_manager/integration.py +9 -14
- reconcile/aws_account_manager/reconciler.py +51 -1
- reconcile/aws_account_manager/utils.py +3 -0
- reconcile/aws_ami_cleanup/integration.py +3 -4
- reconcile/aws_iam_password_reset.py +2 -5
- reconcile/aws_version_sync/integration.py +2 -2
- reconcile/blackbox_exporter_endpoint_monitoring.py +2 -5
- reconcile/change_owners/approver.py +4 -5
- reconcile/change_owners/bundle.py +20 -22
- reconcile/change_owners/change_types.py +23 -24
- reconcile/change_owners/changes.py +13 -16
- reconcile/change_owners/decision.py +2 -5
- reconcile/change_owners/diff.py +11 -15
- reconcile/change_owners/self_service_roles.py +1 -2
- reconcile/change_owners/tester.py +7 -10
- reconcile/checkpoint.py +2 -5
- reconcile/cli.py +26 -12
- reconcile/closedbox_endpoint_monitoring_base.py +8 -11
- reconcile/cluster_deployment_mapper.py +2 -5
- reconcile/cna/assets/asset.py +4 -7
- reconcile/cna/assets/null.py +2 -5
- reconcile/cna/integration.py +2 -3
- reconcile/cna/state.py +2 -5
- reconcile/dashdotdb_base.py +8 -11
- reconcile/dashdotdb_cso.py +3 -6
- reconcile/dashdotdb_dora.py +10 -14
- reconcile/dashdotdb_dvo.py +10 -13
- reconcile/dashdotdb_slo.py +5 -8
- reconcile/database_access_manager.py +5 -6
- reconcile/dynatrace_token_provider/integration.py +3 -6
- reconcile/dynatrace_token_provider/integration_v2.py +20 -0
- reconcile/dynatrace_token_provider/meta.py +1 -0
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +4 -4
- reconcile/external_resources/model.py +3 -3
- reconcile/external_resources/secrets_sync.py +5 -5
- reconcile/external_resources/state.py +5 -5
- reconcile/gabi_authorized_users.py +3 -6
- reconcile/gcr_mirror.py +1 -1
- reconcile/github_org.py +1 -3
- reconcile/github_repo_invites.py +2 -5
- reconcile/gitlab_housekeeping.py +7 -11
- reconcile/gitlab_labeler.py +1 -2
- reconcile/gitlab_members.py +2 -5
- reconcile/gitlab_permissions.py +1 -3
- reconcile/glitchtip/integration.py +5 -8
- reconcile/glitchtip_project_alerts/integration.py +57 -33
- reconcile/glitchtip_project_dsn/integration.py +8 -11
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +6 -0
- reconcile/gql_definitions/fragments/aws_account_managed.py +8 -0
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +4 -4
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +27 -7
- reconcile/integrations_manager.py +5 -8
- reconcile/jenkins/types.py +5 -6
- reconcile/jenkins_job_builder.py +9 -12
- reconcile/jenkins_roles.py +1 -1
- reconcile/jira_watcher.py +2 -2
- reconcile/ldap_groups/integration.py +2 -5
- reconcile/ocm/types.py +21 -26
- reconcile/ocm_addons_upgrade_tests_trigger.py +3 -6
- reconcile/ocm_clusters.py +8 -8
- reconcile/ocm_internal_notifications/integration.py +1 -2
- reconcile/ocm_labels/integration.py +2 -5
- reconcile/ocm_machine_pools.py +11 -15
- reconcile/ocm_upgrade_scheduler_org_updater.py +2 -5
- reconcile/openshift_base.py +29 -30
- reconcile/openshift_groups.py +15 -20
- reconcile/openshift_namespace_labels.py +8 -14
- reconcile/openshift_namespaces.py +5 -8
- reconcile/openshift_network_policies.py +2 -4
- reconcile/openshift_resources_base.py +19 -29
- reconcile/openshift_saas_deploy.py +9 -10
- reconcile/openshift_saas_deploy_change_tester.py +7 -10
- reconcile/openshift_saas_deploy_trigger_base.py +4 -7
- reconcile/openshift_saas_deploy_trigger_cleaner.py +5 -8
- reconcile/openshift_saas_deploy_trigger_configs.py +1 -2
- reconcile/openshift_saas_deploy_trigger_images.py +1 -2
- reconcile/openshift_saas_deploy_trigger_moving_commits.py +1 -2
- reconcile/openshift_saas_deploy_trigger_upstream_jobs.py +1 -2
- reconcile/openshift_tekton_resources.py +7 -11
- reconcile/openshift_upgrade_watcher.py +10 -13
- reconcile/openshift_users.py +8 -11
- reconcile/oum/base.py +3 -4
- reconcile/oum/labelset.py +1 -2
- reconcile/oum/metrics.py +2 -2
- reconcile/oum/models.py +1 -2
- reconcile/oum/standalone.py +2 -3
- reconcile/prometheus_rules_tester/integration.py +6 -9
- reconcile/quay_membership.py +1 -2
- reconcile/quay_mirror.py +12 -13
- reconcile/quay_mirror_org.py +10 -10
- reconcile/queries.py +4 -7
- reconcile/resource_scraper.py +3 -4
- reconcile/rhidp/common.py +2 -2
- reconcile/saas_auto_promotions_manager/integration.py +5 -6
- reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py +1 -2
- reconcile/saas_auto_promotions_manager/publisher.py +5 -6
- reconcile/saas_auto_promotions_manager/subscriber.py +36 -15
- reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +8 -0
- reconcile/saas_file_validator.py +2 -5
- reconcile/signalfx_endpoint_monitoring.py +2 -5
- reconcile/skupper_network/integration.py +3 -6
- reconcile/skupper_network/models.py +3 -5
- reconcile/slack_base.py +4 -7
- reconcile/slack_usergroups.py +15 -17
- reconcile/sql_query.py +5 -9
- reconcile/status_board.py +4 -5
- reconcile/statuspage/atlassian.py +14 -15
- reconcile/statuspage/integrations/maintenances.py +3 -3
- reconcile/statuspage/page.py +8 -8
- reconcile/statuspage/state.py +4 -5
- reconcile/statuspage/status.py +7 -8
- reconcile/templating/lib/rendering.py +8 -8
- reconcile/templating/renderer.py +10 -11
- reconcile/templating/validator.py +4 -4
- reconcile/terraform_aws_route53.py +3 -6
- reconcile/terraform_cloudflare_dns.py +9 -12
- reconcile/terraform_cloudflare_resources.py +9 -11
- reconcile/terraform_cloudflare_users.py +8 -11
- reconcile/terraform_init/integration.py +2 -2
- reconcile/terraform_repo.py +11 -14
- reconcile/terraform_resources.py +20 -21
- reconcile/terraform_tgw_attachments.py +32 -36
- reconcile/terraform_users.py +6 -7
- reconcile/terraform_vpc_resources/integration.py +6 -6
- reconcile/test/conftest.py +7 -10
- reconcile/test/fixtures.py +1 -1
- reconcile/test/saas_auto_promotions_manager/conftest.py +3 -2
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +2 -2
- reconcile/test/test_database_access_manager.py +3 -6
- reconcile/test/test_gitlab_labeler.py +2 -5
- reconcile/test/test_jump_host.py +5 -8
- reconcile/test/test_ocm_machine_pools.py +1 -4
- reconcile/test/test_openshift_base.py +3 -6
- reconcile/test/test_openshift_cluster_bots.py +5 -5
- reconcile/test/test_openshift_namespace_labels.py +2 -3
- reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py +2 -2
- reconcile/test/test_saasherder.py +9 -12
- reconcile/test/test_slack_base.py +4 -6
- reconcile/test/test_status_board.py +4 -7
- reconcile/test/test_terraform_tgw_attachments.py +14 -20
- reconcile/typed_queries/alerting_services_settings.py +1 -2
- reconcile/typed_queries/app_interface_custom_messages.py +2 -3
- reconcile/typed_queries/app_interface_deadmanssnitch_settings.py +1 -3
- reconcile/typed_queries/app_interface_repo_url.py +1 -2
- reconcile/typed_queries/app_interface_state_settings.py +1 -3
- reconcile/typed_queries/app_interface_vault_settings.py +1 -2
- reconcile/typed_queries/aws_vpc_requests.py +1 -3
- reconcile/typed_queries/aws_vpcs.py +1 -3
- reconcile/typed_queries/clusters.py +2 -4
- reconcile/typed_queries/clusters_minimal.py +1 -3
- reconcile/typed_queries/clusters_with_dms.py +1 -3
- reconcile/typed_queries/dynatrace_environments.py +14 -0
- reconcile/typed_queries/external_resources.py +3 -4
- reconcile/typed_queries/pagerduty_instances.py +1 -2
- reconcile/typed_queries/repos.py +2 -3
- reconcile/typed_queries/reserved_networks.py +1 -3
- reconcile/typed_queries/saas_files.py +49 -59
- reconcile/typed_queries/slo_documents.py +1 -3
- reconcile/typed_queries/status_board.py +3 -7
- reconcile/typed_queries/tekton_pipeline_providers.py +1 -2
- reconcile/typed_queries/terraform_namespaces.py +1 -2
- reconcile/typed_queries/terraform_tgw_attachments/aws_accounts.py +1 -3
- reconcile/utils/acs/base.py +2 -3
- reconcile/utils/acs/notifiers.py +3 -3
- reconcile/utils/acs/policies.py +3 -3
- reconcile/utils/aggregated_list.py +1 -1
- reconcile/utils/amtool.py +1 -2
- reconcile/utils/aws_api.py +28 -31
- reconcile/utils/aws_api_typed/account.py +23 -0
- reconcile/utils/aws_api_typed/api.py +20 -9
- reconcile/utils/binary.py +1 -3
- reconcile/utils/clusterhealth/providerbase.py +1 -2
- reconcile/utils/clusterhealth/telemeter.py +2 -2
- reconcile/utils/deadmanssnitch_api.py +1 -2
- reconcile/utils/disabled_integrations.py +4 -6
- reconcile/utils/environ.py +1 -1
- reconcile/utils/expiration.py +3 -7
- reconcile/utils/external_resource_spec.py +3 -4
- reconcile/utils/external_resources.py +4 -7
- reconcile/utils/filtering.py +1 -2
- reconcile/utils/git.py +3 -9
- reconcile/utils/git_secrets.py +5 -5
- reconcile/utils/github_api.py +5 -9
- reconcile/utils/gitlab_api.py +2 -3
- reconcile/utils/glitchtip/client.py +2 -4
- reconcile/utils/glitchtip/models.py +8 -11
- reconcile/utils/gql.py +26 -35
- reconcile/utils/grouping.py +1 -3
- reconcile/utils/imap_client.py +2 -5
- reconcile/utils/internal_groups/client.py +1 -2
- reconcile/utils/internal_groups/models.py +8 -9
- reconcile/utils/jenkins_api.py +4 -4
- reconcile/utils/jinja2/extensions.py +1 -1
- reconcile/utils/jinja2/filters.py +4 -4
- reconcile/utils/jinja2/utils.py +16 -16
- reconcile/utils/jira_client.py +10 -11
- reconcile/utils/jjb_client.py +14 -17
- reconcile/utils/jobcontroller/controller.py +5 -5
- reconcile/utils/jobcontroller/models.py +2 -2
- reconcile/utils/jsonpath.py +4 -5
- reconcile/utils/jump_host.py +7 -8
- reconcile/utils/keycloak.py +3 -7
- reconcile/utils/ldap_client.py +2 -3
- reconcile/utils/lean_terraform_client.py +13 -17
- reconcile/utils/membershipsources/app_interface_resolver.py +1 -1
- reconcile/utils/membershipsources/models.py +19 -22
- reconcile/utils/metrics.py +13 -15
- reconcile/utils/mr/base.py +7 -11
- reconcile/utils/mr/glitchtip_access_reporter.py +2 -2
- reconcile/utils/mr/notificator.py +1 -2
- reconcile/utils/oc.py +38 -38
- reconcile/utils/oc_connection_parameters.py +24 -25
- reconcile/utils/oc_filters.py +2 -3
- reconcile/utils/oc_map.py +9 -15
- reconcile/utils/ocm/addons.py +7 -10
- reconcile/utils/ocm/base.py +38 -39
- reconcile/utils/ocm/clusters.py +6 -9
- reconcile/utils/ocm/label_sources.py +1 -2
- reconcile/utils/ocm/labels.py +3 -6
- reconcile/utils/ocm/ocm.py +11 -14
- reconcile/utils/ocm/products.py +1 -3
- reconcile/utils/ocm/search_filters.py +16 -17
- reconcile/utils/ocm/service_log.py +2 -3
- reconcile/utils/ocm/sre_capability_labels.py +4 -8
- reconcile/utils/ocm/subscriptions.py +1 -3
- reconcile/utils/ocm/syncsets.py +2 -4
- reconcile/utils/ocm/upgrades.py +5 -9
- reconcile/utils/ocm_base_client.py +13 -16
- reconcile/utils/openshift_resource.py +5 -11
- reconcile/utils/output.py +2 -3
- reconcile/utils/pagerduty_api.py +4 -5
- reconcile/utils/prometheus.py +2 -2
- reconcile/utils/promotion_state.py +4 -5
- reconcile/utils/promtool.py +2 -8
- reconcile/utils/quay_api.py +12 -22
- reconcile/utils/raw_github_api.py +3 -5
- reconcile/utils/rosa/rosa_cli.py +6 -6
- reconcile/utils/rosa/session.py +6 -7
- reconcile/utils/runtime/desired_state_diff.py +3 -8
- reconcile/utils/runtime/environment.py +4 -7
- reconcile/utils/runtime/integration.py +4 -4
- reconcile/utils/runtime/meta.py +1 -2
- reconcile/utils/runtime/runner.py +7 -10
- reconcile/utils/runtime/sharding.py +22 -27
- reconcile/utils/saasherder/interfaces.py +63 -69
- reconcile/utils/saasherder/models.py +30 -35
- reconcile/utils/saasherder/saasherder.py +39 -54
- reconcile/utils/secret_reader.py +17 -19
- reconcile/utils/slack_api.py +15 -17
- reconcile/utils/smtp_client.py +1 -2
- reconcile/utils/sqs_gateway.py +1 -3
- reconcile/utils/state.py +1 -2
- reconcile/utils/terraform/config_client.py +4 -5
- reconcile/utils/terraform_client.py +12 -8
- reconcile/utils/terrascript/cloudflare_client.py +4 -10
- reconcile/utils/terrascript/cloudflare_resources.py +10 -13
- reconcile/utils/terrascript/models.py +2 -3
- reconcile/utils/terrascript/resources.py +1 -2
- reconcile/utils/terrascript_aws_client.py +50 -38
- reconcile/utils/unleash/client.py +4 -7
- reconcile/utils/unleash/server.py +2 -2
- reconcile/utils/vault.py +8 -11
- reconcile/utils/vaultsecretref.py +2 -3
- reconcile/utils/vcs.py +7 -8
- reconcile/vault_replication.py +4 -8
- reconcile/vpc_peerings_validator.py +4 -9
- release/version.py +6 -7
- tools/app_interface_reporter.py +2 -2
- tools/cli_commands/gpg_encrypt.py +3 -6
- tools/cli_commands/systems_and_tools.py +4 -7
- tools/qontract_cli.py +105 -17
- tools/saas_promotion_state/__init__.py +0 -0
- tools/saas_promotion_state/saas_promotion_state.py +105 -0
- tools/template_validation.py +1 -1
- tools/test/conftest.py +45 -6
- tools/test/test_saas_promotion_state.py +187 -0
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc879.dist-info → qontract_reconcile-0.10.1rc894.dist-info}/top_level.txt +0 -0
reconcile/utils/secret_reader.py
CHANGED
@@ -5,9 +5,7 @@ from abc import (
|
|
5
5
|
from collections.abc import Mapping
|
6
6
|
from typing import (
|
7
7
|
Any,
|
8
|
-
Optional,
|
9
8
|
Protocol,
|
10
|
-
Union,
|
11
9
|
runtime_checkable,
|
12
10
|
)
|
13
11
|
|
@@ -37,20 +35,20 @@ class HasSecret(Protocol):
|
|
37
35
|
|
38
36
|
path: str
|
39
37
|
field: str
|
40
|
-
version:
|
41
|
-
q_format:
|
38
|
+
version: int | None
|
39
|
+
q_format: str | None
|
42
40
|
|
43
41
|
|
44
42
|
class SecretReaderBase(ABC):
|
45
43
|
@abstractmethod
|
46
44
|
def _read(
|
47
|
-
self, path: str, field: str, format:
|
45
|
+
self, path: str, field: str, format: str | None, version: int | None
|
48
46
|
) -> str:
|
49
47
|
raise NotImplementedError()
|
50
48
|
|
51
49
|
@abstractmethod
|
52
50
|
def _read_all(
|
53
|
-
self, path: str, field: str, format:
|
51
|
+
self, path: str, field: str, format: str | None, version: int | None
|
54
52
|
) -> dict[str, str]:
|
55
53
|
raise NotImplementedError()
|
56
54
|
|
@@ -97,7 +95,7 @@ class SecretReaderBase(ABC):
|
|
97
95
|
)
|
98
96
|
|
99
97
|
def read_with_parameters(
|
100
|
-
self, path: str, field: str, format:
|
98
|
+
self, path: str, field: str, format: str | None, version: int | None
|
101
99
|
) -> str:
|
102
100
|
return self._read(
|
103
101
|
path=path,
|
@@ -107,7 +105,7 @@ class SecretReaderBase(ABC):
|
|
107
105
|
)
|
108
106
|
|
109
107
|
def read_all_with_parameters(
|
110
|
-
self, path: str, field: str, format:
|
108
|
+
self, path: str, field: str, format: str | None, version: int | None
|
111
109
|
) -> dict[str, str]:
|
112
110
|
return self._read_all(
|
113
111
|
path=path,
|
@@ -117,7 +115,7 @@ class SecretReaderBase(ABC):
|
|
117
115
|
)
|
118
116
|
|
119
117
|
def _parameters_to_dict(
|
120
|
-
self, path: str, field: str, format:
|
118
|
+
self, path: str, field: str, format: str | None, version: int | None
|
121
119
|
) -> dict[str, Any]:
|
122
120
|
return {
|
123
121
|
"path": path,
|
@@ -127,7 +125,7 @@ class SecretReaderBase(ABC):
|
|
127
125
|
}
|
128
126
|
|
129
127
|
@staticmethod
|
130
|
-
def to_dict(secret: HasSecret) -> dict[str,
|
128
|
+
def to_dict(secret: HasSecret) -> dict[str, str | int | None]:
|
131
129
|
"""Convenient method to convert Secret class to dictionary."""
|
132
130
|
return {
|
133
131
|
"path": secret.path,
|
@@ -142,7 +140,7 @@ class VaultSecretReader(SecretReaderBase):
|
|
142
140
|
Read secrets from vault via a vault_client
|
143
141
|
"""
|
144
142
|
|
145
|
-
def __init__(self, vault_client:
|
143
|
+
def __init__(self, vault_client: VaultClient | None = None):
|
146
144
|
self._vault_client = vault_client
|
147
145
|
|
148
146
|
@property
|
@@ -152,7 +150,7 @@ class VaultSecretReader(SecretReaderBase):
|
|
152
150
|
return self._vault_client
|
153
151
|
|
154
152
|
def _read_all(
|
155
|
-
self, path: str, field: str, format:
|
153
|
+
self, path: str, field: str, format: str | None, version: int | None
|
156
154
|
) -> dict[str, str]:
|
157
155
|
try:
|
158
156
|
data = self.vault_client.read_all( # type: ignore[attr-defined] # mypy doesn't recognize the VaultClient.__new__ method
|
@@ -172,7 +170,7 @@ class VaultSecretReader(SecretReaderBase):
|
|
172
170
|
return data
|
173
171
|
|
174
172
|
def _read(
|
175
|
-
self, path: str, field: str, format:
|
173
|
+
self, path: str, field: str, format: str | None, version: int | None
|
176
174
|
) -> str:
|
177
175
|
try:
|
178
176
|
data = self.vault_client.read( # type: ignore[attr-defined] # mypy doesn't recognize the VaultClient.__new__ method
|
@@ -194,7 +192,7 @@ class ConfigSecretReader(SecretReaderBase):
|
|
194
192
|
"""
|
195
193
|
|
196
194
|
def _read(
|
197
|
-
self, path: str, field: str, format:
|
195
|
+
self, path: str, field: str, format: str | None, version: int | None
|
198
196
|
) -> str:
|
199
197
|
try:
|
200
198
|
data = config.read(
|
@@ -210,7 +208,7 @@ class ConfigSecretReader(SecretReaderBase):
|
|
210
208
|
return data
|
211
209
|
|
212
210
|
def _read_all(
|
213
|
-
self, path: str, field: str, format:
|
211
|
+
self, path: str, field: str, format: str | None, version: int | None
|
214
212
|
) -> dict[str, str]:
|
215
213
|
try:
|
216
214
|
data = config.read_all(
|
@@ -242,13 +240,13 @@ class SecretReader(SecretReaderBase):
|
|
242
240
|
Consider using create_secret_reader() instead.
|
243
241
|
"""
|
244
242
|
|
245
|
-
def __init__(self, settings:
|
243
|
+
def __init__(self, settings: Mapping | None = None) -> None:
|
246
244
|
"""
|
247
245
|
:param settings: app-interface-settings object. It is a dictionary
|
248
246
|
containing `value: true` if Vault is to be used as the secret backend.
|
249
247
|
"""
|
250
248
|
self.settings = settings
|
251
|
-
self._vault_client:
|
249
|
+
self._vault_client: VaultClient | None = None
|
252
250
|
|
253
251
|
@property
|
254
252
|
def vault_client(self) -> VaultClient:
|
@@ -257,7 +255,7 @@ class SecretReader(SecretReaderBase):
|
|
257
255
|
return self._vault_client
|
258
256
|
|
259
257
|
def _read(
|
260
|
-
self, path: str, field: str, format:
|
258
|
+
self, path: str, field: str, format: str | None, version: int | None
|
261
259
|
) -> str:
|
262
260
|
"""Returns a value of a key from Vault secret or configuration file.
|
263
261
|
The input secret is a dictionary which contains the following fields:
|
@@ -292,7 +290,7 @@ class SecretReader(SecretReaderBase):
|
|
292
290
|
return data
|
293
291
|
|
294
292
|
def _read_all(
|
295
|
-
self, path: str, field: str, format:
|
293
|
+
self, path: str, field: str, format: str | None, version: int | None
|
296
294
|
) -> dict[str, str]:
|
297
295
|
"""Returns a dictionary of keys and values
|
298
296
|
from Vault secret or configuration file.
|
reconcile/utils/slack_api.py
CHANGED
@@ -9,9 +9,7 @@ from collections.abc import (
|
|
9
9
|
)
|
10
10
|
from typing import (
|
11
11
|
Any,
|
12
|
-
Optional,
|
13
12
|
Protocol,
|
14
|
-
Union,
|
15
13
|
)
|
16
14
|
|
17
15
|
from slack_sdk import WebClient
|
@@ -46,17 +44,17 @@ class ServerErrorRetryHandler(RetryHandler):
|
|
46
44
|
*,
|
47
45
|
state: RetryState,
|
48
46
|
request: HttpRequest,
|
49
|
-
response:
|
50
|
-
error:
|
47
|
+
response: HttpResponse | None = None,
|
48
|
+
error: Exception | None = None,
|
51
49
|
) -> bool:
|
52
50
|
return response is not None and response.status_code >= 500
|
53
51
|
|
54
52
|
|
55
53
|
class HasClientGlobalConfig(Protocol):
|
56
|
-
max_retries:
|
57
|
-
timeout:
|
54
|
+
max_retries: int | None
|
55
|
+
timeout: int | None
|
58
56
|
|
59
|
-
def dict(self) -> dict[str,
|
57
|
+
def dict(self) -> dict[str, int | None]: ...
|
60
58
|
|
61
59
|
|
62
60
|
class HasClientMethodConfig(Protocol):
|
@@ -68,10 +66,10 @@ class HasClientMethodConfig(Protocol):
|
|
68
66
|
|
69
67
|
class HasClientConfig(Protocol):
|
70
68
|
@property
|
71
|
-
def q_global(self) ->
|
69
|
+
def q_global(self) -> HasClientGlobalConfig | None: ...
|
72
70
|
|
73
71
|
@property
|
74
|
-
def methods(self) ->
|
72
|
+
def methods(self) -> Sequence[HasClientMethodConfig] | None: ...
|
75
73
|
|
76
74
|
|
77
75
|
class SlackApiConfig:
|
@@ -95,7 +93,7 @@ class SlackApiConfig:
|
|
95
93
|
"""
|
96
94
|
self._methods[method_name] = method_config
|
97
95
|
|
98
|
-
def get_method_config(self, method_name: str) ->
|
96
|
+
def get_method_config(self, method_name: str) -> dict[str, Any] | None:
|
99
97
|
"""
|
100
98
|
Get Slack method configuration.
|
101
99
|
:param method_name: the name of a method (ex. users.list)
|
@@ -165,10 +163,10 @@ class SlackApi:
|
|
165
163
|
self,
|
166
164
|
workspace_name: str,
|
167
165
|
token: str,
|
168
|
-
api_config:
|
166
|
+
api_config: SlackApiConfig | None = None,
|
169
167
|
init_usergroups: bool = True,
|
170
|
-
channel:
|
171
|
-
slack_url:
|
168
|
+
channel: str | None = None,
|
169
|
+
slack_url: str | None = None,
|
172
170
|
**chat_kwargs: Any,
|
173
171
|
) -> None:
|
174
172
|
"""
|
@@ -295,7 +293,7 @@ class SlackApi:
|
|
295
293
|
if not info.data["channel"]["is_member"]: # type: ignore[call-overload]
|
296
294
|
self._sc.conversations_join(channel=channel_id)
|
297
295
|
|
298
|
-
def get_usergroup_id(self, handle: str) ->
|
296
|
+
def get_usergroup_id(self, handle: str) -> str | None:
|
299
297
|
try:
|
300
298
|
return self.get_usergroup(handle)["id"]
|
301
299
|
except UsergroupNotFoundException:
|
@@ -449,7 +447,7 @@ class SlackApi:
|
|
449
447
|
result_key = "members" if resource == "users" else resource
|
450
448
|
api_key = "conversations" if resource == "channels" else resource
|
451
449
|
results = {}
|
452
|
-
additional_kwargs: dict[str,
|
450
|
+
additional_kwargs: dict[str, str | int] = {"cursor": ""}
|
453
451
|
|
454
452
|
method_config = self.config.get_method_config(f"{api_key}.list")
|
455
453
|
if method_config:
|
@@ -459,7 +457,7 @@ class SlackApi:
|
|
459
457
|
slack_request.labels(f"{api_key}.list", "GET").inc()
|
460
458
|
|
461
459
|
result = self._sc.api_call(
|
462
|
-
"{}.list"
|
460
|
+
f"{api_key}.list", http_verb="GET", params=additional_kwargs
|
463
461
|
)
|
464
462
|
|
465
463
|
for r in result[result_key]:
|
@@ -487,7 +485,7 @@ class SlackApi:
|
|
487
485
|
return self._enterprise_user_id_to_user_ids.get(user_id, user_id)
|
488
486
|
|
489
487
|
def get_flat_conversation_history(
|
490
|
-
self, from_timestamp: int, to_timestamp:
|
488
|
+
self, from_timestamp: int, to_timestamp: int | None
|
491
489
|
) -> list[dict[str, Any]]:
|
492
490
|
"""Calls conversation_history method to get all messages in a channel between
|
493
491
|
from_timestamp to to_timestamp ignoring threads"""
|
reconcile/utils/smtp_client.py
CHANGED
@@ -4,7 +4,6 @@ from email.header import Header
|
|
4
4
|
from email.mime.multipart import MIMEMultipart
|
5
5
|
from email.mime.text import MIMEText
|
6
6
|
from email.utils import formataddr
|
7
|
-
from typing import Optional
|
8
7
|
|
9
8
|
from pydantic import (
|
10
9
|
BaseModel,
|
@@ -54,7 +53,7 @@ class SmtpClient:
|
|
54
53
|
self.passwd = server.password
|
55
54
|
self.mail_address = mail_address
|
56
55
|
self.timeout = timeout
|
57
|
-
self._client:
|
56
|
+
self._client: smtplib.SMTP | None = None
|
58
57
|
|
59
58
|
@property
|
60
59
|
def client(self) -> smtplib.SMTP:
|
reconcile/utils/sqs_gateway.py
CHANGED
@@ -46,9 +46,7 @@ class SQSGateway:
|
|
46
46
|
a["name"] for a in accounts if a["uid"] == queue_account_uid
|
47
47
|
]
|
48
48
|
if len(queue_account_name) != 1:
|
49
|
-
raise SQSGatewayInitError(
|
50
|
-
"account uid not found: {}".format(queue_account_uid)
|
51
|
-
)
|
49
|
+
raise SQSGatewayInitError(f"account uid not found: {queue_account_uid}")
|
52
50
|
return queue_account_name[0]
|
53
51
|
|
54
52
|
def send_message(self, body):
|
reconcile/utils/state.py
CHANGED
@@ -8,7 +8,6 @@ from dataclasses import dataclass, field
|
|
8
8
|
from typing import (
|
9
9
|
TYPE_CHECKING,
|
10
10
|
Any,
|
11
|
-
Optional,
|
12
11
|
Self,
|
13
12
|
)
|
14
13
|
|
@@ -46,7 +45,7 @@ class StateInaccessibleException(Exception):
|
|
46
45
|
|
47
46
|
def init_state(
|
48
47
|
integration: str,
|
49
|
-
secret_reader:
|
48
|
+
secret_reader: SecretReaderBase | None = None,
|
50
49
|
) -> "State":
|
51
50
|
if not secret_reader:
|
52
51
|
vault_settings = get_app_interface_vault_settings()
|
@@ -4,7 +4,6 @@ from abc import (
|
|
4
4
|
abstractmethod,
|
5
5
|
)
|
6
6
|
from collections.abc import Iterable
|
7
|
-
from typing import Optional
|
8
7
|
|
9
8
|
from reconcile.utils.exceptions import PrintToFileInGitRepositoryError
|
10
9
|
from reconcile.utils.external_resource_spec import (
|
@@ -34,7 +33,7 @@ class TerraformConfigClient(ABC):
|
|
34
33
|
@abstractmethod
|
35
34
|
def dump(
|
36
35
|
self,
|
37
|
-
existing_dir:
|
36
|
+
existing_dir: str | None = None,
|
38
37
|
) -> str:
|
39
38
|
"""Dump the Terraform JSON configuration to the filesystem."""
|
40
39
|
|
@@ -65,7 +64,7 @@ class TerraformConfigClientCollection:
|
|
65
64
|
def add_specs(
|
66
65
|
self,
|
67
66
|
specs: Iterable[ExternalResourceSpec],
|
68
|
-
account_filter:
|
67
|
+
account_filter: str | None = None,
|
69
68
|
) -> None:
|
70
69
|
"""
|
71
70
|
Add external resource specs
|
@@ -94,8 +93,8 @@ class TerraformConfigClientCollection:
|
|
94
93
|
|
95
94
|
def dump(
|
96
95
|
self,
|
97
|
-
print_to_file:
|
98
|
-
existing_dirs:
|
96
|
+
print_to_file: str | None = None,
|
97
|
+
existing_dirs: dict[str, str] | None = None,
|
99
98
|
) -> dict[str, str]:
|
100
99
|
"""
|
101
100
|
Dump the Terraform JSON config to the filesystem.
|
@@ -20,7 +20,6 @@ from threading import Lock
|
|
20
20
|
from typing import (
|
21
21
|
IO,
|
22
22
|
Any,
|
23
|
-
Optional,
|
24
23
|
cast,
|
25
24
|
)
|
26
25
|
|
@@ -81,7 +80,7 @@ class TerraformClient: # pylint: disable=too-many-public-methods
|
|
81
80
|
accounts: Iterable[Mapping[str, Any]],
|
82
81
|
working_dirs: Mapping[str, str],
|
83
82
|
thread_pool_size: int,
|
84
|
-
aws_api:
|
83
|
+
aws_api: AWSApi | None = None,
|
85
84
|
init_users=False,
|
86
85
|
):
|
87
86
|
self.integration = integration
|
@@ -209,6 +208,15 @@ class TerraformClient: # pylint: disable=too-many-public-methods
|
|
209
208
|
self.created_users.extend(created_users)
|
210
209
|
return disabled_deletions_detected, errors
|
211
210
|
|
211
|
+
def safe_plan(self, enable_deletion: bool) -> None:
|
212
|
+
"""Raises exception if errors are detected at plan step"""
|
213
|
+
disable_deletions_detected, errors = self.plan(enable_deletion)
|
214
|
+
|
215
|
+
if errors:
|
216
|
+
raise RuntimeError("Terraform plan has errors")
|
217
|
+
if disable_deletions_detected:
|
218
|
+
raise RuntimeError("Terraform plan has disabled deletions detected")
|
219
|
+
|
212
220
|
@retry()
|
213
221
|
def terraform_plan(
|
214
222
|
self, spec: TerraformSpec, enable_deletion: bool
|
@@ -463,12 +471,8 @@ class TerraformClient: # pylint: disable=too-many-public-methods
|
|
463
471
|
if output is None:
|
464
472
|
return data
|
465
473
|
|
466
|
-
enc_pass_pfx = "{}_{}"
|
467
|
-
|
468
|
-
)
|
469
|
-
console_urls_pfx = "{}_{}".format(
|
470
|
-
self.integration_prefix, self.OUTPUT_TYPE_CONSOLEURLS
|
471
|
-
)
|
474
|
+
enc_pass_pfx = f"{self.integration_prefix}_{self.OUTPUT_TYPE_PASSWORDS}"
|
475
|
+
console_urls_pfx = f"{self.integration_prefix}_{self.OUTPUT_TYPE_CONSOLEURLS}"
|
472
476
|
for k, v in output.items():
|
473
477
|
# the integration creates outputs of the form
|
474
478
|
# 0.11: output_secret_name[secret_key] = secret_value
|
@@ -5,10 +5,6 @@ from abc import (
|
|
5
5
|
)
|
6
6
|
from collections.abc import Iterable
|
7
7
|
from dataclasses import dataclass
|
8
|
-
from typing import (
|
9
|
-
Optional,
|
10
|
-
Union,
|
11
|
-
)
|
12
8
|
|
13
9
|
from terrascript import (
|
14
10
|
Backend,
|
@@ -175,7 +171,7 @@ class TerrascriptCloudflareClient(TerraformConfigClient):
|
|
175
171
|
resources_to_add = create_cloudflare_terrascript_resource(spec)
|
176
172
|
self._add_resources(resources_to_add)
|
177
173
|
|
178
|
-
def dump(self, existing_dir:
|
174
|
+
def dump(self, existing_dir: str | None = None) -> str:
|
179
175
|
"""Write the Terraform JSON representation of the resources to disk"""
|
180
176
|
if existing_dir is None:
|
181
177
|
working_dir = tempfile.mkdtemp(prefix=TMP_DIR_PREFIX)
|
@@ -192,9 +188,7 @@ class TerrascriptCloudflareClient(TerraformConfigClient):
|
|
192
188
|
"""Return the Terraform JSON representation of the resources"""
|
193
189
|
return str(self._terrascript)
|
194
190
|
|
195
|
-
def _add_resources(
|
196
|
-
self, tf_resources: Iterable[Union[Resource, Output, Data]]
|
197
|
-
) -> None:
|
191
|
+
def _add_resources(self, tf_resources: Iterable[Resource | Output | Data]) -> None:
|
198
192
|
for resource in tf_resources:
|
199
193
|
self._terrascript.add(resource)
|
200
194
|
|
@@ -277,7 +271,7 @@ class TerrascriptCloudflareClientFactory:
|
|
277
271
|
cls,
|
278
272
|
tf_state_s3: TerraformStateS3,
|
279
273
|
cf_acct: CloudflareAccount,
|
280
|
-
sharding_strategy:
|
274
|
+
sharding_strategy: TerraformS3StateNamingStrategy | None,
|
281
275
|
secret_reader: SecretReaderBase,
|
282
276
|
is_managed_account: bool,
|
283
277
|
provider_rps: int = DEFAULT_PROVIDER_RPS,
|
@@ -300,7 +294,7 @@ class TerrascriptCloudflareClientFactory:
|
|
300
294
|
|
301
295
|
def _get_terraform_s3_state_key_name(
|
302
296
|
integration: Integration,
|
303
|
-
sharding_strategy:
|
297
|
+
sharding_strategy: TerraformS3StateNamingStrategy | None,
|
304
298
|
) -> str:
|
305
299
|
if sharding_strategy is None:
|
306
300
|
sharding_strategy = Default()
|
@@ -2,10 +2,7 @@ from collections.abc import (
|
|
2
2
|
Iterable,
|
3
3
|
MutableMapping,
|
4
4
|
)
|
5
|
-
from typing import
|
6
|
-
Any,
|
7
|
-
Union,
|
8
|
-
)
|
5
|
+
from typing import Any
|
9
6
|
|
10
7
|
from terrascript import (
|
11
8
|
Data,
|
@@ -90,7 +87,7 @@ class cloudflare_account_roles(Data):
|
|
90
87
|
# TODO: rename to include object?
|
91
88
|
def create_cloudflare_terrascript_resource(
|
92
89
|
spec: ExternalResourceSpec,
|
93
|
-
) -> list[
|
90
|
+
) -> list[Resource | Output | Data]:
|
94
91
|
"""
|
95
92
|
Create the required Cloudflare Terrascript resources as defined by the external
|
96
93
|
resources spec.
|
@@ -117,7 +114,7 @@ def create_cloudflare_terrascript_resource(
|
|
117
114
|
class CloudflareWorkerScriptTerrascriptResource(TerrascriptResource):
|
118
115
|
"""Generate a cloudflare_worker_script resource"""
|
119
116
|
|
120
|
-
def populate(self) -> list[
|
117
|
+
def populate(self) -> list[Resource | Output]:
|
121
118
|
values = ResourceValueResolver(self._spec).resolve()
|
122
119
|
|
123
120
|
gh_repo = values["content_from_github"]["repo"]
|
@@ -164,7 +161,7 @@ class CloudflareZoneTerrascriptResource(TerrascriptResource):
|
|
164
161
|
|
165
162
|
def _create_cloudflare_certificate_pack(
|
166
163
|
self, zone: Resource, zone_certs: Iterable[MutableMapping[str, Any]]
|
167
|
-
) -> list[
|
164
|
+
) -> list[Resource | Output]:
|
168
165
|
resources = []
|
169
166
|
for cert_values in zone_certs:
|
170
167
|
identifier = safe_resource_id(cert_values.pop("identifier"))
|
@@ -192,7 +189,7 @@ class CloudflareZoneTerrascriptResource(TerrascriptResource):
|
|
192
189
|
self,
|
193
190
|
zone: Resource,
|
194
191
|
zone_custom_ssl: Iterable[MutableMapping[str, Any]],
|
195
|
-
) -> list[
|
192
|
+
) -> list[Resource | Output]:
|
196
193
|
vault_settings = get_app_interface_vault_settings()
|
197
194
|
secret_reader = create_secret_reader(use_vault=vault_settings.vault)
|
198
195
|
|
@@ -221,7 +218,7 @@ class CloudflareZoneTerrascriptResource(TerrascriptResource):
|
|
221
218
|
resources.append(custom_ssl)
|
222
219
|
return resources
|
223
220
|
|
224
|
-
def populate(self) -> list[
|
221
|
+
def populate(self) -> list[Resource | Output]:
|
225
222
|
resources = []
|
226
223
|
|
227
224
|
values = ResourceValueResolver(self._spec).resolve()
|
@@ -313,7 +310,7 @@ class CloudflareZoneTerrascriptResource(TerrascriptResource):
|
|
313
310
|
|
314
311
|
|
315
312
|
class CloudflareAccountMemberTerrascriptResource(TerrascriptResource):
|
316
|
-
def populate(self) -> list[
|
313
|
+
def populate(self) -> list[Resource | Output]:
|
317
314
|
resources = []
|
318
315
|
values = ResourceValueResolver(self._spec).resolve()
|
319
316
|
data_source_cloudflare_account_roles = values.pop("cloudflare_account_roles")
|
@@ -340,7 +337,7 @@ class CloudflareLogpushJob(TerrascriptResource):
|
|
340
337
|
we are defining this as inner class.
|
341
338
|
"""
|
342
339
|
|
343
|
-
def populate(self) -> list[
|
340
|
+
def populate(self) -> list[Resource | Output | Data]:
|
344
341
|
resources = []
|
345
342
|
values = ResourceValueResolver(self._spec).resolve()
|
346
343
|
zone = values.pop("zone_name", None)
|
@@ -373,7 +370,7 @@ class CloudflareLogpushOwnershipChallengeResource(TerrascriptResource):
|
|
373
370
|
we are defining this as inner class.
|
374
371
|
"""
|
375
372
|
|
376
|
-
def populate(self) -> list[
|
373
|
+
def populate(self) -> list[Resource | Output | Data]:
|
377
374
|
resources = []
|
378
375
|
values = ResourceValueResolver(self._spec).resolve()
|
379
376
|
destination_conf = values.get("destination_conf")
|
@@ -412,7 +409,7 @@ class CloudflareLogpullRetention(TerrascriptResource):
|
|
412
409
|
we are defining this as inner class.
|
413
410
|
"""
|
414
411
|
|
415
|
-
def populate(self) -> list[
|
412
|
+
def populate(self) -> list[Resource | Output | Data]:
|
416
413
|
resources = []
|
417
414
|
values = ResourceValueResolver(self._spec).resolve()
|
418
415
|
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from reconcile.utils.secret_reader import HasSecret
|
5
4
|
|
@@ -22,6 +21,6 @@ class TerraformStateS3:
|
|
22
21
|
class CloudflareAccount:
|
23
22
|
name: str
|
24
23
|
api_credentials: HasSecret
|
25
|
-
enforce_twofactor:
|
26
|
-
type:
|
24
|
+
enforce_twofactor: bool | None
|
25
|
+
type: str | None
|
27
26
|
provider_version: str
|
@@ -3,7 +3,6 @@ from abc import (
|
|
3
3
|
abstractmethod,
|
4
4
|
)
|
5
5
|
from collections.abc import Iterable
|
6
|
-
from typing import Union
|
7
6
|
|
8
7
|
from terrascript import (
|
9
8
|
Data,
|
@@ -40,5 +39,5 @@ class TerrascriptResource(ABC):
|
|
40
39
|
]
|
41
40
|
|
42
41
|
@abstractmethod
|
43
|
-
def populate(self) -> list[
|
42
|
+
def populate(self) -> list[Resource | Output | Data]:
|
44
43
|
"""Calling this method should return the Terrascript resources to be created."""
|