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
@@ -3,10 +3,7 @@ import logging
|
|
3
3
|
from collections import defaultdict
|
4
4
|
from collections.abc import Callable
|
5
5
|
from dataclasses import field
|
6
|
-
from typing import
|
7
|
-
Any,
|
8
|
-
Optional,
|
9
|
-
)
|
6
|
+
from typing import Any
|
10
7
|
from urllib.parse import urlparse
|
11
8
|
|
12
9
|
from pydantic.dataclasses import dataclass
|
@@ -49,14 +46,14 @@ class EndpointMonitoringProvider:
|
|
49
46
|
name: str
|
50
47
|
provider: str
|
51
48
|
description: str
|
52
|
-
timeout:
|
53
|
-
checkInterval:
|
54
|
-
blackboxExporter:
|
55
|
-
signalFx:
|
56
|
-
metricLabels:
|
49
|
+
timeout: str | None = None
|
50
|
+
checkInterval: str | None = None
|
51
|
+
blackboxExporter: BlackboxMonitoringProvider | None = None
|
52
|
+
signalFx: SignalfxMonitoringProvier | None = None
|
53
|
+
metricLabels: str | None = None
|
57
54
|
|
58
55
|
@property
|
59
|
-
def namespace(self) ->
|
56
|
+
def namespace(self) -> dict[str, Any] | None:
|
60
57
|
if self.blackboxExporter:
|
61
58
|
return self.blackboxExporter.namespace
|
62
59
|
|
@@ -131,7 +128,7 @@ def fill_desired_state(
|
|
131
128
|
def run_for_provider(
|
132
129
|
provider: str,
|
133
130
|
probe_builder: Callable[
|
134
|
-
[EndpointMonitoringProvider, list[Endpoint]],
|
131
|
+
[EndpointMonitoringProvider, list[Endpoint]], OpenshiftResource | None
|
135
132
|
],
|
136
133
|
integration: str,
|
137
134
|
integration_version: str,
|
@@ -1,9 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
import sys
|
3
|
-
from typing import
|
4
|
-
Any,
|
5
|
-
Optional,
|
6
|
-
)
|
3
|
+
from typing import Any
|
7
4
|
|
8
5
|
from reconcile.status import ExitCodes
|
9
6
|
from reconcile.typed_queries.app_interface_vault_settings import (
|
@@ -18,7 +15,7 @@ from reconcile.utils.vault import VaultClient
|
|
18
15
|
QONTRACT_INTEGRATION = "cluster-deployment-mapper"
|
19
16
|
|
20
17
|
|
21
|
-
def run(dry_run: bool, vault_output_path:
|
18
|
+
def run(dry_run: bool, vault_output_path: str | None) -> None:
|
22
19
|
"""Get Hive ClusterDeployments from clusters and save mapping to Vault"""
|
23
20
|
if not vault_output_path:
|
24
21
|
logging.error("must supply vault output path")
|
reconcile/cna/assets/asset.py
CHANGED
@@ -9,10 +9,7 @@ from dataclasses import (
|
|
9
9
|
field,
|
10
10
|
)
|
11
11
|
from enum import Enum
|
12
|
-
from typing import
|
13
|
-
Any,
|
14
|
-
Optional,
|
15
|
-
)
|
12
|
+
from typing import Any
|
16
13
|
|
17
14
|
|
18
15
|
class AssetError(Exception):
|
@@ -31,9 +28,9 @@ class AssetStatus(Enum):
|
|
31
28
|
|
32
29
|
@dataclass(frozen=True)
|
33
30
|
class Asset(ABC):
|
34
|
-
uuid:
|
35
|
-
href:
|
36
|
-
status:
|
31
|
+
uuid: str | None = field(compare=False, hash=True)
|
32
|
+
href: str | None = field(compare=False, hash=True)
|
33
|
+
status: AssetStatus | None = field(compare=False, hash=True)
|
37
34
|
name: str
|
38
35
|
kind: AssetType
|
39
36
|
|
reconcile/cna/assets/null.py
CHANGED
@@ -2,10 +2,7 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
from collections.abc import Mapping
|
4
4
|
from dataclasses import dataclass
|
5
|
-
from typing import
|
6
|
-
Any,
|
7
|
-
Optional,
|
8
|
-
)
|
5
|
+
from typing import Any
|
9
6
|
|
10
7
|
from reconcile.cna.assets.asset import (
|
11
8
|
Asset,
|
@@ -18,7 +15,7 @@ from reconcile.gql_definitions.cna.queries.cna_resources import CNANullAssetV1
|
|
18
15
|
|
19
16
|
@dataclass(frozen=True)
|
20
17
|
class NullAsset(Asset):
|
21
|
-
addr_block:
|
18
|
+
addr_block: str | None
|
22
19
|
|
23
20
|
def api_payload(self) -> dict[str, Any]:
|
24
21
|
return {
|
reconcile/cna/integration.py
CHANGED
@@ -3,7 +3,6 @@ from collections.abc import (
|
|
3
3
|
Iterable,
|
4
4
|
Mapping,
|
5
5
|
)
|
6
|
-
from typing import Optional
|
7
6
|
|
8
7
|
from reconcile.cna.assets.asset_factory import asset_factory_from_schema
|
9
8
|
from reconcile.cna.client import CNAClient
|
@@ -45,8 +44,8 @@ class CNAIntegration:
|
|
45
44
|
self,
|
46
45
|
cna_clients: Mapping[str, CNAClient],
|
47
46
|
namespaces: Iterable[NamespaceV1],
|
48
|
-
desired_states:
|
49
|
-
current_states:
|
47
|
+
desired_states: Mapping[str, State] | None = None,
|
48
|
+
current_states: Mapping[str, State] | None = None,
|
50
49
|
):
|
51
50
|
self._cna_clients = cna_clients
|
52
51
|
self._namespaces = namespaces
|
reconcile/cna/state.py
CHANGED
@@ -4,10 +4,7 @@ from collections.abc import (
|
|
4
4
|
Iterable,
|
5
5
|
Mapping,
|
6
6
|
)
|
7
|
-
from typing import
|
8
|
-
Any,
|
9
|
-
Optional,
|
10
|
-
)
|
7
|
+
from typing import Any
|
11
8
|
|
12
9
|
from reconcile.cna.assets.asset import (
|
13
10
|
Asset,
|
@@ -29,7 +26,7 @@ class State:
|
|
29
26
|
deletions and updates to reach another state.
|
30
27
|
"""
|
31
28
|
|
32
|
-
def __init__(self, assets:
|
29
|
+
def __init__(self, assets: dict[AssetType, dict[str, Asset]] | None = None):
|
33
30
|
self._assets: dict[AssetType, dict[str, Asset]] = {}
|
34
31
|
for kind in AssetType:
|
35
32
|
self._assets[kind] = {}
|
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,16 +1,14 @@
|
|
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
|
13
10
|
|
11
|
+
from reconcile.dynatrace_token_provider.meta import QONTRACT_INTEGRATION
|
14
12
|
from reconcile.dynatrace_token_provider.metrics import (
|
15
13
|
DTPClustersManagedGauge,
|
16
14
|
DTPOrganizationErrorRate,
|
@@ -55,7 +53,6 @@ from reconcile.utils.runtime.integration import (
|
|
55
53
|
)
|
56
54
|
from reconcile.utils.secret_reader import SecretReaderBase
|
57
55
|
|
58
|
-
QONTRACT_INTEGRATION = "dynatrace-token-provider"
|
59
56
|
SYNCSET_ID = "ext-dynatrace-tokens-dtp"
|
60
57
|
SECRET_NAME = "dynatrace-token-dtp"
|
61
58
|
SECRET_NAMESPACE = "dynatrace"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
from reconcile.dynatrace_token_provider.meta import QONTRACT_INTEGRATION
|
2
|
+
from reconcile.utils.runtime.integration import (
|
3
|
+
PydanticRunParams,
|
4
|
+
QontractReconcileIntegration,
|
5
|
+
)
|
6
|
+
|
7
|
+
|
8
|
+
class DynatraceTokenProviderIntegrationParamsV2(PydanticRunParams):
|
9
|
+
ocm_organization_ids: set[str] | None = None
|
10
|
+
|
11
|
+
|
12
|
+
class DynatraceTokenProviderIntegrationV2(
|
13
|
+
QontractReconcileIntegration[DynatraceTokenProviderIntegrationParamsV2]
|
14
|
+
):
|
15
|
+
@property
|
16
|
+
def name(self) -> str:
|
17
|
+
return QONTRACT_INTEGRATION
|
18
|
+
|
19
|
+
def run(self, dry_run: bool) -> None:
|
20
|
+
pass
|
@@ -0,0 +1 @@
|
|
1
|
+
QONTRACT_INTEGRATION = "dynatrace-token-provider"
|
@@ -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)
|