qontract-reconcile 0.10.1rc884__py3-none-any.whl → 0.10.1rc886__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/RECORD +279 -276
- reconcile/acs_rbac.py +1 -2
- reconcile/aus/advanced_upgrade_service.py +14 -14
- reconcile/aus/aus_label_source.py +1 -2
- reconcile/aus/base.py +23 -26
- reconcile/aus/cluster_version_data.py +4 -4
- reconcile/aus/models.py +2 -3
- reconcile/aus/version_gate_approver.py +2 -6
- reconcile/aus/version_gates/__init__.py +1 -3
- reconcile/aus/version_gates/sts_version_gate_handler.py +2 -3
- reconcile/aws_account_manager/integration.py +2 -2
- reconcile/aws_ami_cleanup/integration.py +3 -4
- reconcile/aws_iam_password_reset.py +2 -5
- reconcile/aws_version_sync/integration.py +2 -2
- reconcile/blackbox_exporter_endpoint_monitoring.py +2 -5
- reconcile/change_owners/approver.py +4 -5
- reconcile/change_owners/bundle.py +20 -22
- reconcile/change_owners/change_types.py +23 -24
- reconcile/change_owners/changes.py +13 -16
- reconcile/change_owners/decision.py +2 -5
- reconcile/change_owners/diff.py +11 -15
- reconcile/change_owners/self_service_roles.py +1 -2
- reconcile/change_owners/tester.py +7 -10
- reconcile/checkpoint.py +2 -5
- reconcile/cli.py +9 -12
- reconcile/closedbox_endpoint_monitoring_base.py +8 -11
- reconcile/cluster_deployment_mapper.py +2 -5
- reconcile/cna/assets/asset.py +4 -7
- reconcile/cna/assets/null.py +2 -5
- reconcile/cna/integration.py +2 -3
- reconcile/cna/state.py +2 -5
- reconcile/dashdotdb_base.py +8 -11
- reconcile/dashdotdb_cso.py +3 -6
- reconcile/dashdotdb_dora.py +10 -14
- reconcile/dashdotdb_dvo.py +10 -13
- reconcile/dashdotdb_slo.py +5 -8
- reconcile/database_access_manager.py +5 -6
- reconcile/dynatrace_token_provider/integration.py +2 -5
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +4 -4
- reconcile/external_resources/model.py +3 -3
- reconcile/external_resources/secrets_sync.py +5 -5
- reconcile/external_resources/state.py +5 -5
- reconcile/gabi_authorized_users.py +3 -6
- reconcile/gcr_mirror.py +1 -1
- reconcile/github_org.py +1 -3
- reconcile/github_repo_invites.py +2 -5
- reconcile/gitlab_housekeeping.py +7 -11
- reconcile/gitlab_labeler.py +1 -2
- reconcile/gitlab_members.py +2 -5
- reconcile/gitlab_permissions.py +1 -3
- reconcile/glitchtip/integration.py +2 -5
- reconcile/glitchtip_project_alerts/integration.py +3 -6
- reconcile/glitchtip_project_dsn/integration.py +4 -7
- reconcile/integrations_manager.py +5 -8
- reconcile/jenkins/types.py +5 -6
- reconcile/jenkins_job_builder.py +9 -12
- reconcile/jenkins_roles.py +1 -1
- reconcile/jira_watcher.py +2 -2
- reconcile/ldap_groups/integration.py +2 -5
- reconcile/ocm/types.py +21 -26
- reconcile/ocm_addons_upgrade_tests_trigger.py +3 -6
- reconcile/ocm_clusters.py +8 -8
- reconcile/ocm_internal_notifications/integration.py +1 -2
- reconcile/ocm_labels/integration.py +2 -5
- reconcile/ocm_machine_pools.py +11 -15
- reconcile/ocm_upgrade_scheduler_org_updater.py +2 -5
- reconcile/openshift_base.py +27 -29
- reconcile/openshift_groups.py +15 -20
- reconcile/openshift_namespace_labels.py +8 -14
- reconcile/openshift_namespaces.py +5 -8
- reconcile/openshift_network_policies.py +2 -4
- reconcile/openshift_resources_base.py +19 -29
- reconcile/openshift_saas_deploy.py +9 -10
- reconcile/openshift_saas_deploy_change_tester.py +7 -10
- reconcile/openshift_saas_deploy_trigger_base.py +4 -7
- reconcile/openshift_saas_deploy_trigger_cleaner.py +5 -8
- reconcile/openshift_saas_deploy_trigger_configs.py +1 -2
- reconcile/openshift_saas_deploy_trigger_images.py +1 -2
- reconcile/openshift_saas_deploy_trigger_moving_commits.py +1 -2
- reconcile/openshift_saas_deploy_trigger_upstream_jobs.py +1 -2
- reconcile/openshift_tekton_resources.py +7 -11
- reconcile/openshift_upgrade_watcher.py +10 -13
- reconcile/openshift_users.py +8 -11
- reconcile/oum/base.py +3 -4
- reconcile/oum/labelset.py +1 -2
- reconcile/oum/metrics.py +2 -2
- reconcile/oum/models.py +1 -2
- reconcile/oum/standalone.py +2 -3
- reconcile/prometheus_rules_tester/integration.py +6 -9
- reconcile/quay_membership.py +1 -2
- reconcile/quay_mirror.py +12 -13
- reconcile/quay_mirror_org.py +10 -10
- reconcile/queries.py +4 -7
- reconcile/resource_scraper.py +3 -4
- reconcile/rhidp/common.py +2 -2
- reconcile/saas_auto_promotions_manager/integration.py +5 -6
- reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py +1 -2
- reconcile/saas_auto_promotions_manager/publisher.py +5 -6
- reconcile/saas_auto_promotions_manager/subscriber.py +3 -4
- reconcile/saas_file_validator.py +2 -5
- reconcile/signalfx_endpoint_monitoring.py +2 -5
- reconcile/skupper_network/integration.py +3 -6
- reconcile/skupper_network/models.py +3 -5
- reconcile/slack_base.py +4 -7
- reconcile/slack_usergroups.py +15 -17
- reconcile/sql_query.py +5 -9
- reconcile/status_board.py +4 -5
- reconcile/statuspage/atlassian.py +14 -15
- reconcile/statuspage/integrations/maintenances.py +3 -3
- reconcile/statuspage/page.py +8 -8
- reconcile/statuspage/state.py +4 -5
- reconcile/statuspage/status.py +7 -8
- reconcile/templating/lib/rendering.py +8 -8
- reconcile/templating/renderer.py +10 -11
- reconcile/templating/validator.py +4 -4
- reconcile/terraform_aws_route53.py +3 -6
- reconcile/terraform_cloudflare_dns.py +9 -12
- reconcile/terraform_cloudflare_resources.py +9 -11
- reconcile/terraform_cloudflare_users.py +8 -11
- reconcile/terraform_init/integration.py +2 -2
- reconcile/terraform_repo.py +11 -14
- reconcile/terraform_resources.py +20 -21
- reconcile/terraform_tgw_attachments.py +32 -36
- reconcile/terraform_users.py +6 -7
- reconcile/terraform_vpc_resources/integration.py +5 -5
- reconcile/test/conftest.py +7 -10
- reconcile/test/fixtures.py +1 -1
- reconcile/test/saas_auto_promotions_manager/conftest.py +2 -2
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +2 -2
- reconcile/test/test_database_access_manager.py +3 -6
- reconcile/test/test_gitlab_labeler.py +2 -5
- reconcile/test/test_jump_host.py +5 -8
- reconcile/test/test_ocm_machine_pools.py +1 -4
- reconcile/test/test_openshift_base.py +3 -6
- reconcile/test/test_openshift_cluster_bots.py +5 -5
- reconcile/test/test_openshift_namespace_labels.py +2 -3
- reconcile/test/test_openshift_saas_deploy_trigger_cleaner.py +2 -2
- reconcile/test/test_saasherder.py +9 -12
- reconcile/test/test_slack_base.py +4 -6
- reconcile/test/test_status_board.py +4 -7
- reconcile/test/test_terraform_tgw_attachments.py +14 -20
- reconcile/typed_queries/alerting_services_settings.py +1 -2
- reconcile/typed_queries/app_interface_custom_messages.py +2 -3
- reconcile/typed_queries/app_interface_deadmanssnitch_settings.py +1 -3
- reconcile/typed_queries/app_interface_repo_url.py +1 -2
- reconcile/typed_queries/app_interface_state_settings.py +1 -3
- reconcile/typed_queries/app_interface_vault_settings.py +1 -2
- reconcile/typed_queries/aws_vpc_requests.py +1 -3
- reconcile/typed_queries/aws_vpcs.py +1 -3
- reconcile/typed_queries/clusters.py +2 -4
- reconcile/typed_queries/clusters_minimal.py +1 -3
- reconcile/typed_queries/clusters_with_dms.py +1 -3
- reconcile/typed_queries/external_resources.py +3 -4
- reconcile/typed_queries/pagerduty_instances.py +1 -2
- reconcile/typed_queries/repos.py +2 -3
- reconcile/typed_queries/reserved_networks.py +1 -3
- reconcile/typed_queries/saas_files.py +49 -59
- reconcile/typed_queries/slo_documents.py +1 -3
- reconcile/typed_queries/status_board.py +3 -7
- reconcile/typed_queries/tekton_pipeline_providers.py +1 -2
- reconcile/typed_queries/terraform_namespaces.py +1 -2
- reconcile/typed_queries/terraform_tgw_attachments/aws_accounts.py +1 -3
- reconcile/utils/acs/base.py +2 -3
- reconcile/utils/acs/notifiers.py +3 -3
- reconcile/utils/acs/policies.py +3 -3
- reconcile/utils/aggregated_list.py +1 -1
- reconcile/utils/amtool.py +1 -2
- reconcile/utils/aws_api.py +28 -31
- reconcile/utils/binary.py +1 -3
- reconcile/utils/clusterhealth/providerbase.py +1 -2
- reconcile/utils/clusterhealth/telemeter.py +2 -2
- reconcile/utils/deadmanssnitch_api.py +1 -2
- reconcile/utils/disabled_integrations.py +4 -6
- reconcile/utils/environ.py +1 -1
- reconcile/utils/expiration.py +3 -7
- reconcile/utils/external_resource_spec.py +3 -4
- reconcile/utils/external_resources.py +4 -7
- reconcile/utils/filtering.py +1 -2
- reconcile/utils/git.py +3 -9
- reconcile/utils/git_secrets.py +5 -5
- reconcile/utils/github_api.py +5 -9
- reconcile/utils/gitlab_api.py +2 -3
- reconcile/utils/glitchtip/client.py +2 -4
- reconcile/utils/glitchtip/models.py +8 -11
- reconcile/utils/gql.py +26 -35
- reconcile/utils/grouping.py +1 -3
- reconcile/utils/imap_client.py +2 -5
- reconcile/utils/internal_groups/client.py +1 -2
- reconcile/utils/internal_groups/models.py +8 -9
- reconcile/utils/jenkins_api.py +4 -4
- reconcile/utils/jinja2/extensions.py +1 -1
- reconcile/utils/jinja2/filters.py +4 -4
- reconcile/utils/jinja2/utils.py +16 -16
- reconcile/utils/jira_client.py +10 -11
- reconcile/utils/jjb_client.py +14 -17
- reconcile/utils/jobcontroller/controller.py +5 -5
- reconcile/utils/jobcontroller/models.py +2 -2
- reconcile/utils/jsonpath.py +4 -5
- reconcile/utils/jump_host.py +7 -8
- reconcile/utils/keycloak.py +3 -7
- reconcile/utils/ldap_client.py +2 -3
- reconcile/utils/lean_terraform_client.py +13 -17
- reconcile/utils/membershipsources/app_interface_resolver.py +1 -1
- reconcile/utils/membershipsources/models.py +19 -22
- reconcile/utils/metrics.py +13 -15
- reconcile/utils/mr/base.py +7 -11
- reconcile/utils/mr/glitchtip_access_reporter.py +2 -2
- reconcile/utils/mr/notificator.py +1 -2
- reconcile/utils/oc.py +32 -38
- reconcile/utils/oc_connection_parameters.py +24 -25
- reconcile/utils/oc_filters.py +2 -3
- reconcile/utils/oc_map.py +9 -15
- reconcile/utils/ocm/addons.py +7 -10
- reconcile/utils/ocm/base.py +38 -39
- reconcile/utils/ocm/clusters.py +6 -9
- reconcile/utils/ocm/label_sources.py +1 -2
- reconcile/utils/ocm/labels.py +3 -6
- reconcile/utils/ocm/ocm.py +11 -14
- reconcile/utils/ocm/products.py +1 -3
- reconcile/utils/ocm/search_filters.py +16 -17
- reconcile/utils/ocm/service_log.py +2 -3
- reconcile/utils/ocm/sre_capability_labels.py +4 -8
- reconcile/utils/ocm/subscriptions.py +1 -3
- reconcile/utils/ocm/syncsets.py +2 -4
- reconcile/utils/ocm/upgrades.py +5 -9
- reconcile/utils/ocm_base_client.py +13 -16
- reconcile/utils/openshift_resource.py +5 -11
- reconcile/utils/output.py +2 -3
- reconcile/utils/pagerduty_api.py +4 -5
- reconcile/utils/prometheus.py +2 -2
- reconcile/utils/promotion_state.py +4 -5
- reconcile/utils/promtool.py +2 -8
- reconcile/utils/quay_api.py +12 -22
- reconcile/utils/raw_github_api.py +3 -5
- reconcile/utils/rosa/rosa_cli.py +6 -6
- reconcile/utils/rosa/session.py +6 -7
- reconcile/utils/runtime/desired_state_diff.py +3 -8
- reconcile/utils/runtime/environment.py +4 -7
- reconcile/utils/runtime/integration.py +4 -4
- reconcile/utils/runtime/meta.py +1 -2
- reconcile/utils/runtime/runner.py +7 -10
- reconcile/utils/runtime/sharding.py +22 -27
- reconcile/utils/saasherder/interfaces.py +63 -69
- reconcile/utils/saasherder/models.py +30 -35
- reconcile/utils/saasherder/saasherder.py +37 -53
- reconcile/utils/secret_reader.py +17 -19
- reconcile/utils/slack_api.py +15 -17
- reconcile/utils/smtp_client.py +1 -2
- reconcile/utils/sqs_gateway.py +1 -3
- reconcile/utils/state.py +1 -2
- reconcile/utils/terraform/config_client.py +4 -5
- reconcile/utils/terraform_client.py +3 -8
- reconcile/utils/terrascript/cloudflare_client.py +4 -10
- reconcile/utils/terrascript/cloudflare_resources.py +10 -13
- reconcile/utils/terrascript/models.py +2 -3
- reconcile/utils/terrascript/resources.py +1 -2
- reconcile/utils/terrascript_aws_client.py +30 -38
- reconcile/utils/unleash/client.py +4 -7
- reconcile/utils/unleash/server.py +2 -2
- reconcile/utils/vault.py +8 -11
- reconcile/utils/vaultsecretref.py +2 -3
- reconcile/utils/vcs.py +7 -8
- reconcile/vault_replication.py +4 -8
- reconcile/vpc_peerings_validator.py +4 -9
- release/version.py +6 -7
- tools/app_interface_reporter.py +2 -2
- tools/cli_commands/gpg_encrypt.py +3 -6
- tools/cli_commands/systems_and_tools.py +4 -7
- tools/qontract_cli.py +31 -17
- tools/saas_promotion_state/__init__.py +0 -0
- tools/saas_promotion_state/saas_promotion_state.py +72 -0
- tools/template_validation.py +1 -1
- tools/test/conftest.py +45 -6
- tools/test/test_saas_promotion_state.py +86 -0
- {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc884.dist-info → qontract_reconcile-0.10.1rc886.dist-info}/top_level.txt +0 -0
@@ -16,7 +16,6 @@ from enum import Enum
|
|
16
16
|
from typing import (
|
17
17
|
Any,
|
18
18
|
Optional,
|
19
|
-
Tuple,
|
20
19
|
)
|
21
20
|
|
22
21
|
import jinja2
|
@@ -59,7 +58,7 @@ class ChangeTypePriority(Enum):
|
|
59
58
|
LOW = "low"
|
60
59
|
|
61
60
|
|
62
|
-
def parent_of_jsonpath(path: jsonpath_ng.JSONPath) ->
|
61
|
+
def parent_of_jsonpath(path: jsonpath_ng.JSONPath) -> jsonpath_ng.JSONPath | None:
|
63
62
|
# todo - figure out if this is enough of if we have other
|
64
63
|
# structures where a parent can be extracted
|
65
64
|
if isinstance(path, jsonpath_ng.Child):
|
@@ -267,8 +266,8 @@ class PathExpression:
|
|
267
266
|
@dataclass
|
268
267
|
class FileChange:
|
269
268
|
file_ref: FileRef
|
270
|
-
old:
|
271
|
-
new:
|
269
|
+
old: dict[str, Any] | None
|
270
|
+
new: dict[str, Any] | None
|
272
271
|
old_backrefs: set[FileRef] = field(default_factory=set)
|
273
272
|
new_backrefs: set[FileRef] = field(default_factory=set)
|
274
273
|
|
@@ -277,7 +276,7 @@ class OwnershipContext(ABC):
|
|
277
276
|
@abstractmethod
|
278
277
|
def find_ownership_context(
|
279
278
|
self,
|
280
|
-
context_schema:
|
279
|
+
context_schema: str | None,
|
281
280
|
change: FileChange,
|
282
281
|
) -> list[FileRef]: ...
|
283
282
|
|
@@ -285,11 +284,11 @@ class OwnershipContext(ABC):
|
|
285
284
|
@dataclass
|
286
285
|
class ForwardrefOwnershipContext(OwnershipContext):
|
287
286
|
selector: jsonpath_ng.JSONPath
|
288
|
-
when:
|
287
|
+
when: str | None = None
|
289
288
|
|
290
289
|
def find_ownership_context(
|
291
290
|
self,
|
292
|
-
context_schema:
|
291
|
+
context_schema: str | None,
|
293
292
|
change: FileChange,
|
294
293
|
) -> list[FileRef]:
|
295
294
|
old_contexts = {e.value for e in self.selector.find(change.old)}
|
@@ -319,11 +318,11 @@ class ForwardrefOwnershipContext(OwnershipContext):
|
|
319
318
|
class BackrefOwnershipContext(OwnershipContext):
|
320
319
|
selector: jsonpath_ng.JSONPath
|
321
320
|
file_diff_resolver: FileDiffResolver
|
322
|
-
when:
|
321
|
+
when: str | None = None
|
323
322
|
|
324
323
|
def find_ownership_context(
|
325
324
|
self,
|
326
|
-
context_schema:
|
325
|
+
context_schema: str | None,
|
327
326
|
change: FileChange,
|
328
327
|
) -> list[FileRef]:
|
329
328
|
# get backref datafile content
|
@@ -369,7 +368,7 @@ class ContextExpansion:
|
|
369
368
|
def expand_from_file_ref(
|
370
369
|
self,
|
371
370
|
file_ref: FileRef,
|
372
|
-
expansion_trail: Set[
|
371
|
+
expansion_trail: Set[tuple[str, FileRef]],
|
373
372
|
) -> list["ResolvedContext"]:
|
374
373
|
old_data, new_data = self.file_diff_resolver.lookup_file_diff(file_ref)
|
375
374
|
return self.expand(
|
@@ -384,7 +383,7 @@ class ContextExpansion:
|
|
384
383
|
def expand(
|
385
384
|
self,
|
386
385
|
change: FileChange,
|
387
|
-
expansion_trail: Set[
|
386
|
+
expansion_trail: Set[tuple[str, FileRef]],
|
388
387
|
) -> list["ResolvedContext"]:
|
389
388
|
"""
|
390
389
|
Find context based on the `self.context`, lookup the file diff for
|
@@ -395,7 +394,7 @@ class ContextExpansion:
|
|
395
394
|
context_schema=self.change_type.context_schema,
|
396
395
|
change=change,
|
397
396
|
)
|
398
|
-
expaned_context_file_refs: list[
|
397
|
+
expaned_context_file_refs: list[ResolvedContext] = []
|
399
398
|
for ref in context_file_refs:
|
400
399
|
ref_old_data, ref_new_data = self.file_diff_resolver.lookup_file_diff(ref)
|
401
400
|
expaned_context_file_refs.extend(
|
@@ -429,9 +428,9 @@ class ChangeDetector(ABC):
|
|
429
428
|
Represents an item from a change-types `change` list.
|
430
429
|
"""
|
431
430
|
|
432
|
-
context_schema:
|
433
|
-
change_schema:
|
434
|
-
context:
|
431
|
+
context_schema: str | None
|
432
|
+
change_schema: str | None
|
433
|
+
context: OwnershipContext | None
|
435
434
|
|
436
435
|
@abstractmethod
|
437
436
|
def find_context_file_refs(
|
@@ -478,14 +477,14 @@ class ChangeTypeProcessor:
|
|
478
477
|
description: str
|
479
478
|
priority: ChangeTypePriority
|
480
479
|
context_type: BundleFileType
|
481
|
-
context_schema:
|
480
|
+
context_schema: str | None
|
482
481
|
disabled: bool
|
483
482
|
implicit_ownership: list[ChangeTypeImplicitOwnershipV1]
|
484
|
-
restrictive:
|
483
|
+
restrictive: bool | None = False
|
485
484
|
|
486
485
|
def __post_init__(self) -> None:
|
487
486
|
self._expressions_by_file_type_schema: dict[
|
488
|
-
tuple[BundleFileType,
|
487
|
+
tuple[BundleFileType, str | None], list[PathExpression]
|
489
488
|
] = defaultdict(list)
|
490
489
|
self._change_detectors: list[ChangeDetector] = []
|
491
490
|
self._context_expansions: list[ContextExpansion] = []
|
@@ -498,7 +497,7 @@ class ChangeTypeProcessor:
|
|
498
497
|
def find_context_file_refs(
|
499
498
|
self,
|
500
499
|
change: FileChange,
|
501
|
-
expansion_trail: Set[
|
500
|
+
expansion_trail: Set[tuple[str, FileRef]],
|
502
501
|
) -> list[ResolvedContext]:
|
503
502
|
"""
|
504
503
|
ChangeTypeV1 are attached to bundle files, react to changes within
|
@@ -638,7 +637,7 @@ class ChangeTypeProcessor:
|
|
638
637
|
def _allowed_changed_paths_for_file_type_and_schema(
|
639
638
|
self,
|
640
639
|
file_type: BundleFileType,
|
641
|
-
file_schema:
|
640
|
+
file_schema: str | None,
|
642
641
|
file_content: Any,
|
643
642
|
ctx: "ChangeTypeContext",
|
644
643
|
) -> list[jsonpath_ng.JSONPath]:
|
@@ -692,8 +691,8 @@ class ChangeTypeProcessor:
|
|
692
691
|
def build_ownership_context(
|
693
692
|
file_diff_resolver: FileDiffResolver,
|
694
693
|
selector: jsonpath_ng.JSONPath,
|
695
|
-
when:
|
696
|
-
where:
|
694
|
+
when: str | None = None,
|
695
|
+
where: str | None = None,
|
697
696
|
) -> OwnershipContext:
|
698
697
|
"""
|
699
698
|
create an OwnershipContext object based on the provided parameters
|
@@ -840,8 +839,8 @@ class ChangeTypeContext:
|
|
840
839
|
origin: str
|
841
840
|
context_file: FileRef
|
842
841
|
approvers: list[Approver]
|
843
|
-
approver_reachability:
|
844
|
-
change_owner_labels:
|
842
|
+
approver_reachability: list[ApproverReachability] | None = None
|
843
|
+
change_owner_labels: set[str] | None = None
|
845
844
|
|
846
845
|
@property
|
847
846
|
def disabled(self) -> bool:
|
@@ -7,10 +7,7 @@ from dataclasses import (
|
|
7
7
|
dataclass,
|
8
8
|
field,
|
9
9
|
)
|
10
|
-
from typing import
|
11
|
-
Any,
|
12
|
-
Optional,
|
13
|
-
)
|
10
|
+
from typing import Any
|
14
11
|
|
15
12
|
import anymarkup
|
16
13
|
|
@@ -50,8 +47,8 @@ class BundleFileChange:
|
|
50
47
|
"""
|
51
48
|
|
52
49
|
fileref: FileRef
|
53
|
-
old:
|
54
|
-
new:
|
50
|
+
old: dict[str, Any] | None
|
51
|
+
new: dict[str, Any] | None
|
55
52
|
old_content_sha: str
|
56
53
|
new_content_sha: str
|
57
54
|
diffs: list[Diff]
|
@@ -81,16 +78,16 @@ class BundleFileChange:
|
|
81
78
|
return self._diff_coverage[METADATA_CHANGE_PATH]
|
82
79
|
|
83
80
|
@property
|
84
|
-
def old_content_with_metadata(self) ->
|
81
|
+
def old_content_with_metadata(self) -> dict[str, Any] | None:
|
85
82
|
return self._content_with_metadata(self.old)
|
86
83
|
|
87
84
|
@property
|
88
|
-
def new_content_with_metadata(self) ->
|
85
|
+
def new_content_with_metadata(self) -> dict[str, Any] | None:
|
89
86
|
return self._content_with_metadata(self.new)
|
90
87
|
|
91
88
|
def _content_with_metadata(
|
92
|
-
self, content:
|
93
|
-
) ->
|
89
|
+
self, content: dict[str, Any] | None
|
90
|
+
) -> dict[str, Any] | None:
|
94
91
|
if content and self.fileref.file_type == BundleFileType.DATAFILE:
|
95
92
|
content_copy = copy.deepcopy(content)
|
96
93
|
content_copy[DATAFILE_PATH_FIELD_NAME] = self.fileref.path
|
@@ -219,7 +216,7 @@ class BundleFileChange:
|
|
219
216
|
return change_types
|
220
217
|
|
221
218
|
|
222
|
-
def parse_resource_file_content(content:
|
219
|
+
def parse_resource_file_content(content: Any | None) -> tuple[Any, str | None]:
|
223
220
|
if content:
|
224
221
|
try:
|
225
222
|
data = anymarkup.parse(content, force_types=None)
|
@@ -233,7 +230,7 @@ def parse_resource_file_content(content: Optional[Any]) -> tuple[Any, Optional[s
|
|
233
230
|
|
234
231
|
def _create_bundle_file_change(
|
235
232
|
path: str,
|
236
|
-
schema:
|
233
|
+
schema: str | None,
|
237
234
|
file_type: BundleFileType,
|
238
235
|
old_file_content: Any,
|
239
236
|
new_file_content: Any,
|
@@ -241,9 +238,9 @@ def _create_bundle_file_change(
|
|
241
238
|
new_content_sha: str,
|
242
239
|
old_path: str,
|
243
240
|
new_path: str,
|
244
|
-
old_backrefs:
|
245
|
-
new_backrefs:
|
246
|
-
) ->
|
241
|
+
old_backrefs: list[FileRef] | None = None,
|
242
|
+
new_backrefs: list[FileRef] | None = None,
|
243
|
+
) -> BundleFileChange | None:
|
247
244
|
"""
|
248
245
|
this is a factory method that creates a BundleFileChange object based
|
249
246
|
on the old and new content of a file from app-interface. it detects differences
|
@@ -305,7 +302,7 @@ def _create_bundle_file_change(
|
|
305
302
|
|
306
303
|
def get_priority_for_changes(
|
307
304
|
bundle_file_changes: list[BundleFileChange],
|
308
|
-
) ->
|
305
|
+
) -> ChangeTypePriority | None:
|
309
306
|
"""
|
310
307
|
Finds the lowest priority of all change types involved in the provided bundle file changes.
|
311
308
|
"""
|
@@ -5,10 +5,7 @@ from collections.abc import (
|
|
5
5
|
)
|
6
6
|
from dataclasses import dataclass
|
7
7
|
from enum import Enum
|
8
|
-
from typing import
|
9
|
-
Any,
|
10
|
-
Optional,
|
11
|
-
)
|
8
|
+
from typing import Any
|
12
9
|
|
13
10
|
from reconcile.change_owners.approver import (
|
14
11
|
Approver,
|
@@ -70,7 +67,7 @@ def get_approver_decisions_from_mr_comments(
|
|
70
67
|
class ChangeResponsibles:
|
71
68
|
context: str
|
72
69
|
approvers: list[Approver]
|
73
|
-
approver_reachability:
|
70
|
+
approver_reachability: list[ApproverReachability] | None = None
|
74
71
|
|
75
72
|
|
76
73
|
@dataclass
|
reconcile/change_owners/diff.py
CHANGED
@@ -3,11 +3,7 @@ import json
|
|
3
3
|
from dataclasses import dataclass
|
4
4
|
from enum import Enum
|
5
5
|
from functools import reduce
|
6
|
-
from typing import
|
7
|
-
Any,
|
8
|
-
Optional,
|
9
|
-
Union,
|
10
|
-
)
|
6
|
+
from typing import Any
|
11
7
|
|
12
8
|
import jsonpath_ng
|
13
9
|
from deepdiff import DeepDiff
|
@@ -32,8 +28,8 @@ class Diff:
|
|
32
28
|
|
33
29
|
path: jsonpath_ng.JSONPath
|
34
30
|
diff_type: DiffType
|
35
|
-
old:
|
36
|
-
new:
|
31
|
+
old: Any | None
|
32
|
+
new: Any | None
|
37
33
|
|
38
34
|
def create_subdiff(self, sub_path: jsonpath_ng.JSONPath) -> "Diff":
|
39
35
|
if sub_path == self.path:
|
@@ -60,7 +56,7 @@ class Diff:
|
|
60
56
|
new=sub_new[0].value if len(sub_new) > 0 else None,
|
61
57
|
)
|
62
58
|
|
63
|
-
def get_context_data_copy(self) ->
|
59
|
+
def get_context_data_copy(self) -> Any | None:
|
64
60
|
if self.diff_type in {DiffType.ADDED, DiffType.CHANGED}:
|
65
61
|
return copy.deepcopy(self.new)
|
66
62
|
if self.diff_type == DiffType.REMOVED:
|
@@ -70,15 +66,15 @@ class Diff:
|
|
70
66
|
def path_str(self) -> str:
|
71
67
|
return str(self.path)
|
72
68
|
|
73
|
-
def old_value_repr(self) ->
|
69
|
+
def old_value_repr(self) -> str | None:
|
74
70
|
return self._value_repr(self.old)
|
75
71
|
|
76
|
-
def new_value_repr(self) ->
|
72
|
+
def new_value_repr(self) -> str | None:
|
77
73
|
return self._value_repr(self.new)
|
78
74
|
|
79
|
-
def _value_repr(self, value:
|
75
|
+
def _value_repr(self, value: Any | None) -> str | None:
|
80
76
|
if value:
|
81
|
-
if isinstance(value,
|
77
|
+
if isinstance(value, dict | list):
|
82
78
|
return json.dumps(value, indent=2)
|
83
79
|
return str(value)
|
84
80
|
return value
|
@@ -88,7 +84,7 @@ IDENTIFIER_FIELD_NAME = "__identifier"
|
|
88
84
|
REF_FIELD_NAME = "$ref"
|
89
85
|
|
90
86
|
|
91
|
-
def _extract_identifier_from_object(obj: Any) ->
|
87
|
+
def _extract_identifier_from_object(obj: Any) -> str | None:
|
92
88
|
if isinstance(obj, dict):
|
93
89
|
if IDENTIFIER_FIELD_NAME in obj:
|
94
90
|
return obj.get(IDENTIFIER_FIELD_NAME)
|
@@ -98,7 +94,7 @@ def _extract_identifier_from_object(obj: Any) -> Optional[str]:
|
|
98
94
|
|
99
95
|
|
100
96
|
def compare_object_ctx_identifier(
|
101
|
-
x: Any, y: Any, level:
|
97
|
+
x: Any, y: Any, level: DiffLevel | None = None
|
102
98
|
) -> bool:
|
103
99
|
"""
|
104
100
|
this function helps the deepdiff library to decide if two objects are
|
@@ -250,7 +246,7 @@ def deepdiff_path_to_jsonpath(deep_diff_path: str) -> jsonpath_ng.JSONPath:
|
|
250
246
|
if not deep_diff_path.startswith("root"):
|
251
247
|
raise ValueError("a deepdiff path must start with 'root'")
|
252
248
|
|
253
|
-
def build_jsonpath_part(element:
|
249
|
+
def build_jsonpath_part(element: str | int) -> jsonpath_ng.JSONPath:
|
254
250
|
match element:
|
255
251
|
case int():
|
256
252
|
return jsonpath_ng.Index(element)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from collections import defaultdict
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from reconcile.change_owners.approver import (
|
5
4
|
ApproverReachability,
|
@@ -202,7 +201,7 @@ def change_type_contexts_for_self_service_roles(
|
|
202
201
|
return change_type_contexts
|
203
202
|
|
204
203
|
|
205
|
-
def build_approver(role_member: RoleMember) ->
|
204
|
+
def build_approver(role_member: RoleMember) -> Approver | None:
|
206
205
|
"""
|
207
206
|
Builds an approver from a role member. Can return None if the passed
|
208
207
|
approver is not considered valid within this context, e.g. not having
|
@@ -2,10 +2,7 @@ import os
|
|
2
2
|
import sys
|
3
3
|
from collections.abc import Generator
|
4
4
|
from dataclasses import dataclass
|
5
|
-
from typing import
|
6
|
-
Any,
|
7
|
-
Optional,
|
8
|
-
)
|
5
|
+
from typing import Any
|
9
6
|
|
10
7
|
import jsonpath_ng
|
11
8
|
import pygments
|
@@ -151,7 +148,7 @@ class AppInterfaceRepo:
|
|
151
148
|
for file in files:
|
152
149
|
if file.endswith(".yml") or file.endswith(".yaml"):
|
153
150
|
filepath = os.path.join(root, file)
|
154
|
-
with open(filepath,
|
151
|
+
with open(filepath, encoding="locale") as f:
|
155
152
|
parsed_yaml = yaml.safe_load(f)
|
156
153
|
if parsed_yaml.get("$schema") == schema:
|
157
154
|
relative_path = filepath[len(self.data_dir()) :]
|
@@ -166,7 +163,7 @@ class AppInterfaceRepo:
|
|
166
163
|
self, file_type: BundleFileType, path: str
|
167
164
|
) -> BundleFileChange:
|
168
165
|
if file_type == BundleFileType.DATAFILE:
|
169
|
-
with open(f"{self.data_dir()}{path}",
|
166
|
+
with open(f"{self.data_dir()}{path}", encoding="locale") as f:
|
170
167
|
parsed_yaml = yaml.safe_load(f)
|
171
168
|
return BundleFileChange(
|
172
169
|
fileref=FileRef(
|
@@ -181,7 +178,7 @@ class AppInterfaceRepo:
|
|
181
178
|
diffs=[],
|
182
179
|
)
|
183
180
|
elif file_type == BundleFileType.RESOURCEFILE:
|
184
|
-
with open(f"{self.resource_dir()}{path}",
|
181
|
+
with open(f"{self.resource_dir()}{path}", encoding="locale") as f:
|
185
182
|
content = f.read()
|
186
183
|
parsed_content, schema = parse_resource_file_content(content)
|
187
184
|
return BundleFileChange(
|
@@ -223,7 +220,7 @@ class FilesystemFileDiffResolver:
|
|
223
220
|
|
224
221
|
def lookup_file_diff(
|
225
222
|
self, file_ref: FileRef
|
226
|
-
) -> tuple[
|
223
|
+
) -> tuple[dict[str, Any] | None, dict[str, Any] | None]:
|
227
224
|
file = self.app_interface_repo.bundle_file_for_path(
|
228
225
|
file_type=file_ref.file_type, path=file_ref.path
|
229
226
|
)
|
@@ -232,7 +229,7 @@ class FilesystemFileDiffResolver:
|
|
232
229
|
|
233
230
|
def get_changetype_processor_by_name(
|
234
231
|
change_type_name: str, app_interface_repo: AppInterfaceRepo
|
235
|
-
) ->
|
232
|
+
) -> ChangeTypeProcessor | None:
|
236
233
|
processors = fetch_change_type_processors(
|
237
234
|
gql.get_api(), FilesystemFileDiffResolver(app_interface_repo)
|
238
235
|
)
|
@@ -241,7 +238,7 @@ def get_changetype_processor_by_name(
|
|
241
238
|
|
242
239
|
def get_self_service_role_by_name(
|
243
240
|
role_name: str,
|
244
|
-
) ->
|
241
|
+
) -> RoleV1 | None:
|
245
242
|
result = self_service_roles.query(
|
246
243
|
gql.get_api().query, variables={"name": role_name}
|
247
244
|
).roles
|
reconcile/checkpoint.py
CHANGED
@@ -18,10 +18,7 @@ from functools import (
|
|
18
18
|
)
|
19
19
|
from http import HTTPStatus
|
20
20
|
from pathlib import Path
|
21
|
-
from typing import
|
22
|
-
Any,
|
23
|
-
Union,
|
24
|
-
)
|
21
|
+
from typing import Any
|
25
22
|
|
26
23
|
import requests
|
27
24
|
from jinja2 import Template
|
@@ -121,7 +118,7 @@ def file_ticket(
|
|
121
118
|
def report_invalid_metadata(
|
122
119
|
app: Mapping[str, Any],
|
123
120
|
path: str,
|
124
|
-
board: Mapping[str,
|
121
|
+
board: Mapping[str, str | Mapping],
|
125
122
|
settings: Mapping[str, Any],
|
126
123
|
parent: str,
|
127
124
|
dry_run: bool = False,
|
reconcile/cli.py
CHANGED
@@ -6,12 +6,9 @@ import os
|
|
6
6
|
import re
|
7
7
|
import sys
|
8
8
|
import traceback
|
9
|
+
from collections.abc import Iterable
|
9
10
|
from signal import SIGUSR1
|
10
11
|
from types import ModuleType
|
11
|
-
from typing import (
|
12
|
-
Iterable,
|
13
|
-
Optional,
|
14
|
-
)
|
15
12
|
|
16
13
|
import click
|
17
14
|
import sentry_sdk
|
@@ -2530,13 +2527,13 @@ def ocm_groups(ctx, thread_pool_size):
|
|
2530
2527
|
@click.pass_context
|
2531
2528
|
def ocm_clusters(
|
2532
2529
|
ctx,
|
2533
|
-
gitlab_project_id:
|
2530
|
+
gitlab_project_id: str | None,
|
2534
2531
|
thread_pool_size: int,
|
2535
|
-
job_controller_cluster:
|
2536
|
-
job_controller_namespace:
|
2537
|
-
rosa_job_service_account:
|
2538
|
-
rosa_role:
|
2539
|
-
rosa_job_image:
|
2532
|
+
job_controller_cluster: str | None,
|
2533
|
+
job_controller_namespace: str | None,
|
2534
|
+
rosa_job_service_account: str | None,
|
2535
|
+
rosa_role: str | None,
|
2536
|
+
rosa_job_image: str | None,
|
2540
2537
|
):
|
2541
2538
|
from reconcile.ocm_clusters import (
|
2542
2539
|
OcmClusters,
|
@@ -2802,7 +2799,7 @@ def version_gate_approver(
|
|
2802
2799
|
job_controller_namespace: str,
|
2803
2800
|
rosa_job_service_account: str,
|
2804
2801
|
rosa_role: str,
|
2805
|
-
rosa_job_image:
|
2802
|
+
rosa_job_image: str | None,
|
2806
2803
|
) -> None:
|
2807
2804
|
from reconcile.aus.version_gate_approver import (
|
2808
2805
|
VersionGateApprover,
|
@@ -3376,7 +3373,7 @@ def signalfx_prometheus_endpoint_monitoring(
|
|
3376
3373
|
)
|
3377
3374
|
|
3378
3375
|
|
3379
|
-
def parse_image_tag_from_ref(ctx, param, value) ->
|
3376
|
+
def parse_image_tag_from_ref(ctx, param, value) -> dict[str, str] | None:
|
3380
3377
|
if value:
|
3381
3378
|
result = {}
|
3382
3379
|
for v in value:
|
@@ -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] = {}
|