qontract-reconcile 0.10.1rc883__py3-none-any.whl → 0.10.1rc885__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qontract_reconcile-0.10.1rc883.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc883.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/RECORD +276 -276
- reconcile/acs_rbac.py +1 -2
- reconcile/aus/advanced_upgrade_service.py +14 -14
- reconcile/aus/aus_label_source.py +1 -2
- reconcile/aus/base.py +23 -26
- reconcile/aus/cluster_version_data.py +4 -4
- reconcile/aus/models.py +2 -3
- reconcile/aus/version_gate_approver.py +2 -6
- reconcile/aus/version_gates/__init__.py +1 -3
- reconcile/aus/version_gates/sts_version_gate_handler.py +2 -3
- reconcile/aws_account_manager/integration.py +2 -2
- reconcile/aws_ami_cleanup/integration.py +3 -4
- reconcile/aws_iam_password_reset.py +2 -5
- reconcile/aws_version_sync/integration.py +2 -2
- reconcile/blackbox_exporter_endpoint_monitoring.py +2 -5
- reconcile/change_owners/approver.py +4 -5
- reconcile/change_owners/bundle.py +20 -22
- reconcile/change_owners/change_types.py +23 -24
- reconcile/change_owners/changes.py +13 -16
- reconcile/change_owners/decision.py +2 -5
- reconcile/change_owners/diff.py +11 -15
- reconcile/change_owners/self_service_roles.py +1 -2
- reconcile/change_owners/tester.py +7 -10
- reconcile/checkpoint.py +2 -5
- reconcile/cli.py +9 -12
- reconcile/closedbox_endpoint_monitoring_base.py +8 -11
- reconcile/cluster_deployment_mapper.py +2 -5
- reconcile/cna/assets/asset.py +4 -7
- reconcile/cna/assets/null.py +2 -5
- reconcile/cna/integration.py +2 -3
- reconcile/cna/state.py +2 -5
- reconcile/dashdotdb_base.py +8 -11
- reconcile/dashdotdb_cso.py +3 -6
- reconcile/dashdotdb_dora.py +10 -14
- reconcile/dashdotdb_dvo.py +10 -13
- reconcile/dashdotdb_slo.py +5 -8
- reconcile/database_access_manager.py +5 -6
- reconcile/dynatrace_token_provider/integration.py +2 -5
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +4 -4
- reconcile/external_resources/model.py +3 -3
- reconcile/external_resources/secrets_sync.py +5 -5
- reconcile/external_resources/state.py +5 -5
- reconcile/gabi_authorized_users.py +3 -6
- reconcile/gcr_mirror.py +1 -1
- reconcile/github_org.py +1 -3
- reconcile/github_repo_invites.py +2 -5
- reconcile/gitlab_housekeeping.py +7 -11
- reconcile/gitlab_labeler.py +1 -2
- reconcile/gitlab_members.py +2 -5
- reconcile/gitlab_permissions.py +1 -3
- reconcile/glitchtip/integration.py +2 -5
- reconcile/glitchtip_project_alerts/integration.py +3 -6
- reconcile/glitchtip_project_dsn/integration.py +4 -7
- reconcile/integrations_manager.py +5 -8
- reconcile/jenkins/types.py +5 -6
- reconcile/jenkins_job_builder.py +9 -12
- reconcile/jenkins_roles.py +1 -1
- reconcile/jira_watcher.py +2 -2
- reconcile/ldap_groups/integration.py +2 -5
- reconcile/ocm/types.py +21 -26
- reconcile/ocm_addons_upgrade_tests_trigger.py +3 -6
- reconcile/ocm_clusters.py +8 -8
- reconcile/ocm_internal_notifications/integration.py +1 -2
- reconcile/ocm_labels/integration.py +2 -5
- reconcile/ocm_machine_pools.py +11 -15
- reconcile/ocm_upgrade_scheduler_org_updater.py +2 -5
- reconcile/openshift_base.py +27 -29
- reconcile/openshift_groups.py +15 -20
- reconcile/openshift_namespace_labels.py +8 -14
- reconcile/openshift_namespaces.py +5 -8
- reconcile/openshift_network_policies.py +2 -4
- reconcile/openshift_resources_base.py +19 -29
- reconcile/openshift_saas_deploy.py +9 -10
- reconcile/openshift_saas_deploy_change_tester.py +7 -10
- reconcile/openshift_saas_deploy_trigger_base.py +4 -7
- reconcile/openshift_saas_deploy_trigger_cleaner.py +5 -8
- reconcile/openshift_saas_deploy_trigger_configs.py +1 -2
- reconcile/openshift_saas_deploy_trigger_images.py +1 -2
- reconcile/openshift_saas_deploy_trigger_moving_commits.py +1 -2
- reconcile/openshift_saas_deploy_trigger_upstream_jobs.py +1 -2
- reconcile/openshift_tekton_resources.py +7 -11
- reconcile/openshift_upgrade_watcher.py +10 -13
- reconcile/openshift_users.py +8 -11
- reconcile/oum/base.py +3 -4
- reconcile/oum/labelset.py +1 -2
- reconcile/oum/metrics.py +2 -2
- reconcile/oum/models.py +1 -2
- reconcile/oum/standalone.py +2 -3
- reconcile/prometheus_rules_tester/integration.py +6 -9
- reconcile/quay_membership.py +1 -2
- reconcile/quay_mirror.py +12 -13
- reconcile/quay_mirror_org.py +10 -10
- reconcile/queries.py +4 -7
- reconcile/resource_scraper.py +3 -4
- reconcile/rhidp/common.py +2 -2
- reconcile/saas_auto_promotions_manager/integration.py +5 -6
- reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py +1 -2
- reconcile/saas_auto_promotions_manager/publisher.py +5 -6
- reconcile/saas_auto_promotions_manager/subscriber.py +3 -4
- reconcile/saas_file_validator.py +2 -5
- reconcile/signalfx_endpoint_monitoring.py +2 -5
- reconcile/skupper_network/integration.py +3 -6
- reconcile/skupper_network/models.py +3 -5
- reconcile/slack_base.py +4 -7
- reconcile/slack_usergroups.py +15 -17
- reconcile/sql_query.py +5 -9
- reconcile/status_board.py +4 -5
- reconcile/statuspage/atlassian.py +14 -15
- reconcile/statuspage/integrations/maintenances.py +3 -3
- reconcile/statuspage/page.py +8 -8
- reconcile/statuspage/state.py +4 -5
- reconcile/statuspage/status.py +7 -8
- reconcile/templating/lib/rendering.py +8 -8
- reconcile/templating/renderer.py +10 -11
- reconcile/templating/validator.py +4 -4
- reconcile/terraform_aws_route53.py +3 -6
- reconcile/terraform_cloudflare_dns.py +9 -12
- reconcile/terraform_cloudflare_resources.py +9 -11
- reconcile/terraform_cloudflare_users.py +8 -11
- reconcile/terraform_init/integration.py +2 -2
- reconcile/terraform_repo.py +11 -14
- reconcile/terraform_resources.py +20 -21
- reconcile/terraform_tgw_attachments.py +32 -36
- reconcile/terraform_users.py +6 -7
- reconcile/terraform_vpc_resources/integration.py +6 -6
- 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 +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 +30 -38
- reconcile/utils/unleash/client.py +4 -7
- reconcile/utils/unleash/server.py +2 -2
- reconcile/utils/vault.py +8 -11
- reconcile/utils/vaultsecretref.py +2 -3
- reconcile/utils/vcs.py +7 -8
- reconcile/vault_replication.py +4 -8
- reconcile/vpc_peerings_validator.py +4 -9
- release/version.py +6 -7
- tools/app_interface_reporter.py +2 -2
- tools/cli_commands/gpg_encrypt.py +3 -6
- tools/cli_commands/systems_and_tools.py +4 -7
- tools/qontract_cli.py +12 -17
- tools/template_validation.py +1 -1
- tools/test/conftest.py +3 -6
- {qontract_reconcile-0.10.1rc883.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc883.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc883.dist-info → qontract_reconcile-0.10.1rc885.dist-info}/top_level.txt +0 -0
reconcile/acs_rbac.py
CHANGED
@@ -2,7 +2,6 @@ import logging
|
|
2
2
|
from collections import defaultdict
|
3
3
|
from collections.abc import Callable
|
4
4
|
from typing import (
|
5
|
-
Optional,
|
6
5
|
Self,
|
7
6
|
)
|
8
7
|
|
@@ -64,7 +63,7 @@ class AcsRole(BaseModel):
|
|
64
63
|
assignments: list[AssignmentPair]
|
65
64
|
permission_set_name: str
|
66
65
|
access_scope: AcsAccessScope
|
67
|
-
system_default:
|
66
|
+
system_default: bool | None
|
68
67
|
|
69
68
|
@classmethod
|
70
69
|
def build(cls, permission: Permission, usernames: list[str]) -> Self:
|
@@ -197,7 +197,7 @@ class AdvancedUpgradeServiceIntegration(OCMClusterUpgradeSchedulerOrgIntegration
|
|
197
197
|
|
198
198
|
def discover_clusters(
|
199
199
|
ocm_api: OCMBaseClient,
|
200
|
-
org_ids:
|
200
|
+
org_ids: set[str] | None = None,
|
201
201
|
ignore_sts_clusters: bool = False,
|
202
202
|
) -> dict[str, list[ClusterDetails]]:
|
203
203
|
"""
|
@@ -222,7 +222,7 @@ def discover_clusters(
|
|
222
222
|
|
223
223
|
|
224
224
|
def _get_org_labels(
|
225
|
-
ocm_api: OCMBaseClient, org_ids:
|
225
|
+
ocm_api: OCMBaseClient, org_ids: set[str] | None
|
226
226
|
) -> dict[str, LabelContainer]:
|
227
227
|
"""
|
228
228
|
Fetch all AUS OCM org labels from organizations. They hold config
|
@@ -263,7 +263,7 @@ def _build_org_upgrade_specs_for_ocm_env(
|
|
263
263
|
}
|
264
264
|
|
265
265
|
|
266
|
-
def aus_label_key(config_atom:
|
266
|
+
def aus_label_key(config_atom: str | None = None) -> str:
|
267
267
|
"""
|
268
268
|
Generates label keys for aus, compliant with the naming schema defined in
|
269
269
|
https://service.pages.redhat.com/dev-guidelines/docs/sre-capabilities/framework/ocm-labels/
|
@@ -276,7 +276,7 @@ class OrganizationLabelSet(BaseModel):
|
|
276
276
|
Parses, represents and validates a set of organization labels for AUS.
|
277
277
|
"""
|
278
278
|
|
279
|
-
blocked_versions:
|
279
|
+
blocked_versions: CSV | None = Field(alias=aus_label_key("blocked-versions"))
|
280
280
|
|
281
281
|
sector_deps: dict[str, CSV] = labelset_groupfield(
|
282
282
|
group_prefix=aus_label_key("sector-deps.")
|
@@ -395,10 +395,10 @@ class ClusterUpgradePolicyLabelSet(BaseModel):
|
|
395
395
|
soak_days: int = Field(alias=aus_label_key("soak-days"), ge=0)
|
396
396
|
workloads: CSV = Field(alias=aus_label_key("workloads"), csv_min_items=1)
|
397
397
|
schedule: str = Field(alias=aus_label_key("schedule"))
|
398
|
-
mutexes:
|
399
|
-
sector:
|
400
|
-
blocked_versions:
|
401
|
-
version_gate_approvals:
|
398
|
+
mutexes: CSV | None = Field(alias=aus_label_key("mutexes"))
|
399
|
+
sector: str | None = Field(alias=aus_label_key("sector"))
|
400
|
+
blocked_versions: CSV | None = Field(alias=aus_label_key("blocked-versions"))
|
401
|
+
version_gate_approvals: CSV | None = Field(
|
402
402
|
alias=aus_label_key("version-gate-approvals")
|
403
403
|
)
|
404
404
|
_schedule_validator = validator("schedule", allow_reuse=True)(cron_validator)
|
@@ -422,10 +422,10 @@ def build_cluster_upgrade_policy_label_set(
|
|
422
422
|
workloads: list[str],
|
423
423
|
schedule: str,
|
424
424
|
soak_days: int,
|
425
|
-
mutexes:
|
426
|
-
sector:
|
427
|
-
blocked_versions:
|
428
|
-
version_gate_approvals:
|
425
|
+
mutexes: list[str] | None = None,
|
426
|
+
sector: str | None = None,
|
427
|
+
blocked_versions: list[str] | None = None,
|
428
|
+
version_gate_approvals: list[str] | None = None,
|
429
429
|
) -> ClusterUpgradePolicyLabelSet:
|
430
430
|
return ClusterUpgradePolicyLabelSet(**{
|
431
431
|
aus_label_key("workloads"): ",".join(workloads),
|
@@ -463,7 +463,7 @@ def _build_policy_from_labels(labels: LabelContainer) -> ClusterUpgradePolicyV1:
|
|
463
463
|
|
464
464
|
|
465
465
|
class VersionDataInheritanceLabelSet(BaseModel):
|
466
|
-
inherit_version_data:
|
466
|
+
inherit_version_data: CSV | None = Field(
|
467
467
|
alias=aus_label_key("version-data.inherit")
|
468
468
|
)
|
469
469
|
"""
|
@@ -472,7 +472,7 @@ class VersionDataInheritanceLabelSet(BaseModel):
|
|
472
472
|
Version data publishing/inheritance can also be defined between OCM environments.
|
473
473
|
"""
|
474
474
|
|
475
|
-
publish_version_data:
|
475
|
+
publish_version_data: CSV | None = Field(
|
476
476
|
alias=aus_label_key("version-data.publish")
|
477
477
|
)
|
478
478
|
"""
|
reconcile/aus/base.py
CHANGED
@@ -5,16 +5,13 @@ from abc import (
|
|
5
5
|
ABC,
|
6
6
|
abstractmethod,
|
7
7
|
)
|
8
|
+
from collections.abc import Callable, Sequence
|
8
9
|
from datetime import (
|
9
10
|
datetime,
|
10
11
|
timedelta,
|
11
|
-
timezone,
|
12
12
|
)
|
13
13
|
from typing import (
|
14
|
-
Callable,
|
15
|
-
Optional,
|
16
14
|
Protocol,
|
17
|
-
Sequence,
|
18
15
|
cast,
|
19
16
|
)
|
20
17
|
|
@@ -112,9 +109,9 @@ MIN_DELTA_MINUTES = 6
|
|
112
109
|
|
113
110
|
|
114
111
|
class AdvancedUpgradeSchedulerBaseIntegrationParams(PydanticRunParams):
|
115
|
-
ocm_environment:
|
116
|
-
ocm_organization_ids:
|
117
|
-
excluded_ocm_organization_ids:
|
112
|
+
ocm_environment: str | None = None
|
113
|
+
ocm_organization_ids: set[str] | None = None
|
114
|
+
excluded_ocm_organization_ids: set[str] | None = None
|
118
115
|
ignore_sts_clusters: bool = False
|
119
116
|
|
120
117
|
|
@@ -342,7 +339,7 @@ class AdvancedUpgradeSchedulerBaseIntegration(
|
|
342
339
|
def _build_telemeter_health_check_provider_for_env(
|
343
340
|
self,
|
344
341
|
ocm_env_name: str,
|
345
|
-
) ->
|
342
|
+
) -> TelemeterClusterHealthProvider | None:
|
346
343
|
ocm_env = next(
|
347
344
|
iter(
|
348
345
|
ocm_env_telemeter_query(
|
@@ -403,12 +400,12 @@ class AbstractUpgradePolicy(ABC, BaseModel):
|
|
403
400
|
|
404
401
|
cluster: OCMCluster
|
405
402
|
|
406
|
-
id:
|
407
|
-
next_run:
|
408
|
-
schedule:
|
403
|
+
id: str | None
|
404
|
+
next_run: str | None
|
405
|
+
schedule: str | None
|
409
406
|
schedule_type: str
|
410
407
|
version: str
|
411
|
-
state:
|
408
|
+
state: str | None
|
412
409
|
|
413
410
|
@abstractmethod
|
414
411
|
def create(self, ocm_api: OCMBaseClient) -> None:
|
@@ -424,7 +421,7 @@ class AbstractUpgradePolicy(ABC, BaseModel):
|
|
424
421
|
|
425
422
|
|
426
423
|
def addon_upgrade_policy_soonest_next_run() -> str:
|
427
|
-
now = datetime.now(tz=
|
424
|
+
now = datetime.now(tz=dt.UTC)
|
428
425
|
next_run = now + timedelta(minutes=MIN_DELTA_MINUTES)
|
429
426
|
return next_run.strftime("%Y-%m-%dT%H:%M:%SZ")
|
430
427
|
|
@@ -683,7 +680,7 @@ def update_history(
|
|
683
680
|
version_data.check_in = now
|
684
681
|
|
685
682
|
|
686
|
-
def version_data_state_key(ocm_env: str, org_id: str, addon_id:
|
683
|
+
def version_data_state_key(ocm_env: str, org_id: str, addon_id: str | None) -> str:
|
687
684
|
return f"{ocm_env}/{org_id}/{addon_id}" if addon_id else f"{ocm_env}/{org_id}"
|
688
685
|
|
689
686
|
|
@@ -694,7 +691,7 @@ def get_version_data_map(
|
|
694
691
|
integration: str,
|
695
692
|
addon_id: str = "",
|
696
693
|
inherit_version_data: bool = True,
|
697
|
-
defer:
|
694
|
+
defer: Callable | None = None,
|
698
695
|
) -> VersionDataMap:
|
699
696
|
"""Get a summary of versions history per OCM instance
|
700
697
|
|
@@ -788,7 +785,7 @@ def version_conditions_met(
|
|
788
785
|
version: str,
|
789
786
|
version_data: VersionData,
|
790
787
|
upgrade_policy: ClusterUpgradePolicyV1,
|
791
|
-
sector:
|
788
|
+
sector: Sector | None,
|
792
789
|
) -> bool:
|
793
790
|
"""Check that upgrade conditions are met for a version
|
794
791
|
|
@@ -887,8 +884,8 @@ def gates_to_agree(
|
|
887
884
|
def upgradeable_version(
|
888
885
|
spec: ClusterUpgradeSpec,
|
889
886
|
version_data: VersionData,
|
890
|
-
sector:
|
891
|
-
) ->
|
887
|
+
sector: Sector | None,
|
888
|
+
) -> str | None:
|
892
889
|
"""Get the highest next version we can upgrade to, fulfilling all conditions"""
|
893
890
|
for version in reversed(sort_versions(spec.get_available_upgrades())):
|
894
891
|
if spec.version_blocked(version):
|
@@ -908,7 +905,7 @@ def verify_current_should_skip(
|
|
908
905
|
desired: ClusterUpgradeSpec,
|
909
906
|
now: datetime,
|
910
907
|
addon_id: str = "",
|
911
|
-
) -> tuple[bool,
|
908
|
+
) -> tuple[bool, UpgradePolicyHandler | None]:
|
912
909
|
current_policies = [c for c in current_state if c.cluster.id == desired.cluster.id]
|
913
910
|
if not current_policies:
|
914
911
|
return False, None
|
@@ -944,7 +941,7 @@ def verify_schedule_should_skip(
|
|
944
941
|
desired: ClusterUpgradeSpec,
|
945
942
|
now: datetime,
|
946
943
|
addon_id: str = "",
|
947
|
-
) ->
|
944
|
+
) -> str | None:
|
948
945
|
schedule = desired.upgrade_policy.schedule
|
949
946
|
iter = croniter(schedule)
|
950
947
|
# ClusterService refuses scheduling upgrades less than 5m in advance
|
@@ -1006,7 +1003,7 @@ def _create_upgrade_policy(
|
|
1006
1003
|
|
1007
1004
|
def _calculate_node_pool_diffs(
|
1008
1005
|
ocm_api: OCMBaseClient, spec: ClusterUpgradeSpec, now: datetime
|
1009
|
-
) ->
|
1006
|
+
) -> UpgradePolicyHandler | None:
|
1010
1007
|
node_pools = get_node_pools(ocm_api, spec.cluster.id)
|
1011
1008
|
if node_pools:
|
1012
1009
|
for pool in node_pools:
|
@@ -1051,7 +1048,7 @@ def calculate_diff(
|
|
1051
1048
|
"""
|
1052
1049
|
|
1053
1050
|
def set_mutex(
|
1054
|
-
locked: dict[str, str], cluster_id: str, mutexes:
|
1051
|
+
locked: dict[str, str], cluster_id: str, mutexes: set[str] | None = None
|
1055
1052
|
) -> None:
|
1056
1053
|
for mutex in mutexes or set():
|
1057
1054
|
locked[mutex] = cluster_id
|
@@ -1174,7 +1171,7 @@ def act(
|
|
1174
1171
|
dry_run: bool,
|
1175
1172
|
diffs: list[UpgradePolicyHandler],
|
1176
1173
|
ocm_api: OCMBaseClient,
|
1177
|
-
addon_id:
|
1174
|
+
addon_id: str | None = None,
|
1178
1175
|
) -> None:
|
1179
1176
|
diffs.sort(key=sort_diffs)
|
1180
1177
|
for diff in diffs:
|
@@ -1207,8 +1204,8 @@ def get_orgs_for_environment(
|
|
1207
1204
|
integration: str,
|
1208
1205
|
ocm_env_name: str,
|
1209
1206
|
query_func: Callable,
|
1210
|
-
ocm_organization_ids:
|
1211
|
-
excluded_ocm_organization_ids:
|
1207
|
+
ocm_organization_ids: set[str] | None = None,
|
1208
|
+
excluded_ocm_organization_ids: set[str] | None = None,
|
1212
1209
|
only_addon_managed_upgrades: bool = False,
|
1213
1210
|
) -> list[AUSOCMOrganization]:
|
1214
1211
|
"""
|
@@ -1243,7 +1240,7 @@ def get_orgs_for_environment(
|
|
1243
1240
|
def remaining_soak_day_metric_values_for_cluster(
|
1244
1241
|
spec: ClusterUpgradeSpec,
|
1245
1242
|
soaked_versions: dict[str, float],
|
1246
|
-
current_upgrade:
|
1243
|
+
current_upgrade: AbstractUpgradePolicy | None,
|
1247
1244
|
) -> dict[str, float]:
|
1248
1245
|
"""
|
1249
1246
|
Calculate what versions and metric values to report for `AUS*VersionRemainingSoakDaysGauge` metrics.
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import json
|
2
|
+
from collections.abc import Iterable
|
2
3
|
from datetime import datetime
|
3
4
|
from typing import (
|
4
5
|
Any,
|
5
|
-
Iterable,
|
6
6
|
Optional,
|
7
7
|
)
|
8
8
|
|
@@ -93,9 +93,9 @@ class VersionData(BaseModel):
|
|
93
93
|
upgrade policies.
|
94
94
|
"""
|
95
95
|
|
96
|
-
check_in:
|
96
|
+
check_in: datetime | None
|
97
97
|
versions: dict[str, VersionHistory] = Field(default_factory=dict)
|
98
|
-
stats:
|
98
|
+
stats: Stats | None
|
99
99
|
|
100
100
|
def jsondict(self) -> dict[str, Any]:
|
101
101
|
return json.loads(self.json(exclude_none=True))
|
@@ -104,7 +104,7 @@ class VersionData(BaseModel):
|
|
104
104
|
state.add(ocm_name, self.jsondict(), force=True)
|
105
105
|
|
106
106
|
def workload_history(
|
107
|
-
self, version: str, workload: str, default:
|
107
|
+
self, version: str, workload: str, default: WorkloadHistory | None = None
|
108
108
|
) -> WorkloadHistory:
|
109
109
|
if not default:
|
110
110
|
vh = self.versions.get(version, VersionHistory())
|
reconcile/aus/models.py
CHANGED
@@ -7,7 +7,6 @@ from collections.abc import (
|
|
7
7
|
Mapping,
|
8
8
|
Sequence,
|
9
9
|
)
|
10
|
-
from typing import Optional
|
11
10
|
|
12
11
|
from pydantic import (
|
13
12
|
BaseModel,
|
@@ -108,7 +107,7 @@ class OrganizationUpgradeSpec(BaseModel):
|
|
108
107
|
def __init__(
|
109
108
|
self,
|
110
109
|
org: AUSOCMOrganization,
|
111
|
-
specs:
|
110
|
+
specs: Iterable[ClusterUpgradeSpec] | None = None,
|
112
111
|
) -> None:
|
113
112
|
super().__init__(org=org)
|
114
113
|
|
@@ -200,7 +199,7 @@ class SectorConfigError(Exception):
|
|
200
199
|
|
201
200
|
class Sector(BaseModel):
|
202
201
|
name: str
|
203
|
-
dependencies: list[
|
202
|
+
dependencies: list[Sector] = Field(default_factory=list)
|
204
203
|
_specs: dict[str, ClusterUpgradeSpec] = PrivateAttr(default_factory=dict)
|
205
204
|
|
206
205
|
def __key(self) -> str:
|
@@ -1,9 +1,5 @@
|
|
1
1
|
import logging
|
2
|
-
from
|
3
|
-
Callable,
|
4
|
-
Iterable,
|
5
|
-
Optional,
|
6
|
-
)
|
2
|
+
from collections.abc import Callable, Iterable
|
7
3
|
|
8
4
|
from reconcile.aus.advanced_upgrade_service import aus_label_key
|
9
5
|
from reconcile.aus.base import gates_to_agree, get_orgs_for_environment
|
@@ -54,7 +50,7 @@ class VersionGateApproverParams(PydanticRunParams):
|
|
54
50
|
job_controller_namespace: str
|
55
51
|
rosa_job_service_account: str
|
56
52
|
rosa_role: str
|
57
|
-
rosa_job_image:
|
53
|
+
rosa_job_image: str | None = None
|
58
54
|
|
59
55
|
|
60
56
|
class VersionGateApprover(QontractReconcileIntegration[VersionGateApproverParams]):
|
@@ -1,5 +1,3 @@
|
|
1
|
-
from typing import Type
|
2
|
-
|
3
1
|
from reconcile.aus.version_gates import (
|
4
2
|
ingress_gate_handler,
|
5
3
|
ocp_gate_handler,
|
@@ -7,7 +5,7 @@ from reconcile.aus.version_gates import (
|
|
7
5
|
)
|
8
6
|
from reconcile.aus.version_gates.handler import GateHandler
|
9
7
|
|
10
|
-
HANDLERS: dict[str,
|
8
|
+
HANDLERS: dict[str, type[GateHandler]] = {
|
11
9
|
ocp_gate_handler.GATE_LABEL: ocp_gate_handler.OCPGateHandler,
|
12
10
|
sts_version_gate_handler.GATE_LABEL: sts_version_gate_handler.STSGateHandler,
|
13
11
|
ingress_gate_handler.GATE_LABEL: ingress_gate_handler.IngressGateHandler,
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import logging
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from reconcile.aus.version_gates.handler import GateHandler
|
5
4
|
from reconcile.utils.jobcontroller.controller import K8sJobController
|
@@ -16,8 +15,8 @@ class STSGateHandler(GateHandler):
|
|
16
15
|
self,
|
17
16
|
job_controller: K8sJobController,
|
18
17
|
aws_iam_role: str,
|
19
|
-
rosa_job_service_account:
|
20
|
-
rosa_job_image:
|
18
|
+
rosa_job_service_account: str | None = None,
|
19
|
+
rosa_job_image: str | None = None,
|
21
20
|
) -> None:
|
22
21
|
self.job_controller = job_controller
|
23
22
|
self.aws_iam_role = aws_iam_role
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from collections.abc import Callable, Iterable
|
2
|
-
from datetime import
|
2
|
+
from datetime import UTC, datetime
|
3
3
|
from typing import Any
|
4
4
|
|
5
5
|
import jinja2
|
@@ -99,7 +99,7 @@ class AwsAccountMgmtIntegration(
|
|
99
99
|
"accountRequest": account_request.dict(by_alias=True),
|
100
100
|
"uid": uid,
|
101
101
|
"settings": settings,
|
102
|
-
"timestamp": int(datetime.now(tz=
|
102
|
+
"timestamp": int(datetime.now(tz=UTC).timestamp()),
|
103
103
|
})
|
104
104
|
return tmpl
|
105
105
|
|
@@ -12,7 +12,6 @@ from datetime import (
|
|
12
12
|
from typing import (
|
13
13
|
TYPE_CHECKING,
|
14
14
|
Any,
|
15
|
-
Optional,
|
16
15
|
)
|
17
16
|
|
18
17
|
from botocore.exceptions import ClientError
|
@@ -153,7 +152,7 @@ def get_region(
|
|
153
152
|
|
154
153
|
|
155
154
|
def get_app_interface_amis(
|
156
|
-
namespaces:
|
155
|
+
namespaces: list[NamespaceV1] | None, ts: Terrascript
|
157
156
|
) -> list[AIAmi]:
|
158
157
|
"""Returns all the ami referenced in ASGs in app-interface."""
|
159
158
|
app_interface_amis = []
|
@@ -185,7 +184,7 @@ def get_app_interface_amis(
|
|
185
184
|
|
186
185
|
def check_aws_ami_in_use(
|
187
186
|
aws_ami: AWSAmi, app_interface_amis: list[AIAmi]
|
188
|
-
) ->
|
187
|
+
) -> str | None:
|
189
188
|
"""Verifies if the given AWS ami is in use in a defined app-interface ASG."""
|
190
189
|
for ai_ami in app_interface_amis:
|
191
190
|
# This can happen if the ASG init template has changed over the time. We don't have a way
|
@@ -203,7 +202,7 @@ def check_aws_ami_in_use(
|
|
203
202
|
|
204
203
|
|
205
204
|
@defer
|
206
|
-
def run(dry_run: bool, thread_pool_size: int, defer:
|
205
|
+
def run(dry_run: bool, thread_pool_size: int, defer: Callable | None = None) -> None:
|
207
206
|
exit_code = ExitCodes.SUCCESS
|
208
207
|
|
209
208
|
# We still use here a non-typed query; accounts is passed to AWSApi and Terrascript classes
|
@@ -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 pydantic import BaseModel
|
13
10
|
|
@@ -21,7 +18,7 @@ QONTRACT_INTEGRATION = "aws-iam-password-reset"
|
|
21
18
|
|
22
19
|
def get_roles(
|
23
20
|
roles: Iterable[Mapping[str, Any]], org_username: str
|
24
|
-
) ->
|
21
|
+
) -> Mapping[str, Any] | None:
|
25
22
|
for d in roles:
|
26
23
|
if d["org_username"] == org_username:
|
27
24
|
return d
|
@@ -3,7 +3,7 @@ from collections.abc import (
|
|
3
3
|
Callable,
|
4
4
|
Iterable,
|
5
5
|
)
|
6
|
-
from enum import
|
6
|
+
from enum import StrEnum
|
7
7
|
from typing import Any
|
8
8
|
|
9
9
|
import semver
|
@@ -69,7 +69,7 @@ class ExternalResourceProvisioner(BaseModel):
|
|
69
69
|
path: str | None = None
|
70
70
|
|
71
71
|
|
72
|
-
class VersionFormat(
|
72
|
+
class VersionFormat(StrEnum):
|
73
73
|
MAJOR = "major"
|
74
74
|
MAJOR_MINOR = "major_minor"
|
75
75
|
MAJOR_MINOR_PATCH = "major_minor_patch"
|
@@ -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 import queries
|
9
6
|
from reconcile.closedbox_endpoint_monitoring_base import (
|
@@ -69,7 +66,7 @@ def get_blackbox_providers() -> list[EndpointMonitoringProvider]:
|
|
69
66
|
|
70
67
|
def build_probe(
|
71
68
|
provider: EndpointMonitoringProvider, endpoints: list[Endpoint]
|
72
|
-
) ->
|
69
|
+
) -> OpenshiftResource | None:
|
73
70
|
blackbox_exporter = provider.blackboxExporter
|
74
71
|
if blackbox_exporter:
|
75
72
|
prober_url = parse_prober_url(blackbox_exporter.exporterUrl)
|
@@ -1,6 +1,5 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
2
|
from typing import (
|
3
|
-
Optional,
|
4
3
|
Protocol,
|
5
4
|
)
|
6
5
|
|
@@ -17,25 +16,25 @@ class Approver:
|
|
17
16
|
"""
|
18
17
|
|
19
18
|
org_username: str
|
20
|
-
tag_on_merge_requests:
|
19
|
+
tag_on_merge_requests: bool | None = False
|
21
20
|
|
22
21
|
|
23
22
|
class ApproverResolver(Protocol):
|
24
|
-
def lookup_approver_by_path(self, path: str) ->
|
23
|
+
def lookup_approver_by_path(self, path: str) -> Approver | None: ...
|
25
24
|
|
26
25
|
|
27
26
|
class GqlApproverResolver:
|
28
27
|
def __init__(self, gqlapis: list[GqlApi]):
|
29
28
|
self.gqlapis = gqlapis
|
30
29
|
|
31
|
-
def lookup_approver_by_path(self, path: str) ->
|
30
|
+
def lookup_approver_by_path(self, path: str) -> Approver | None:
|
32
31
|
for gqlapi in self.gqlapis:
|
33
32
|
approver = self._lookup_approver_by_path(gqlapi, path)
|
34
33
|
if approver:
|
35
34
|
return approver
|
36
35
|
return None
|
37
36
|
|
38
|
-
def _lookup_approver_by_path(self, gqlapi: GqlApi, path: str) ->
|
37
|
+
def _lookup_approver_by_path(self, gqlapi: GqlApi, path: str) -> Approver | None:
|
39
38
|
approvers = gqlapi.query(
|
40
39
|
"""
|
41
40
|
query Approvers($path: String) {
|
@@ -1,11 +1,9 @@
|
|
1
1
|
from abc import abstractmethod
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from enum import
|
3
|
+
from enum import StrEnum
|
4
4
|
from typing import (
|
5
5
|
Any,
|
6
|
-
Optional,
|
7
6
|
Protocol,
|
8
|
-
Tuple,
|
9
7
|
)
|
10
8
|
|
11
9
|
from pydantic import (
|
@@ -20,7 +18,7 @@ DATAFILE_SHA256SUM_FIELD_NAME = "$file_sha256sum"
|
|
20
18
|
DATAFILE_SCHEMA_FIELD_NAME = "$schema"
|
21
19
|
|
22
20
|
|
23
|
-
class BundleFileType(
|
21
|
+
class BundleFileType(StrEnum):
|
24
22
|
DATAFILE = "datafile"
|
25
23
|
RESOURCEFILE = "resourcefile"
|
26
24
|
|
@@ -33,7 +31,7 @@ class FileRef:
|
|
33
31
|
|
34
32
|
file_type: BundleFileType
|
35
33
|
path: str
|
36
|
-
schema:
|
34
|
+
schema: str | None
|
37
35
|
|
38
36
|
def __str__(self) -> str:
|
39
37
|
return f"{self.file_type.value}:{self.path}"
|
@@ -63,35 +61,35 @@ class QontractServerDatafileDiff(BaseModel):
|
|
63
61
|
|
64
62
|
datafilepath: str
|
65
63
|
datafileschema: str
|
66
|
-
old:
|
67
|
-
new:
|
64
|
+
old: dict[str, Any] | None
|
65
|
+
new: dict[str, Any] | None
|
68
66
|
|
69
67
|
@property
|
70
|
-
def old_datafilepath(self) ->
|
68
|
+
def old_datafilepath(self) -> str | None:
|
71
69
|
return self.old.get(DATAFILE_PATH_FIELD_NAME) if self.old else None
|
72
70
|
|
73
71
|
@property
|
74
|
-
def new_datafilepath(self) ->
|
72
|
+
def new_datafilepath(self) -> str | None:
|
75
73
|
return self.new.get(DATAFILE_PATH_FIELD_NAME) if self.new else None
|
76
74
|
|
77
75
|
@property
|
78
|
-
def old_data_sha(self) ->
|
76
|
+
def old_data_sha(self) -> str | None:
|
79
77
|
return self.old.get(DATAFILE_SHA256SUM_FIELD_NAME) if self.old else None
|
80
78
|
|
81
79
|
@property
|
82
|
-
def new_data_sha(self) ->
|
80
|
+
def new_data_sha(self) -> str | None:
|
83
81
|
return self.new.get(DATAFILE_SHA256SUM_FIELD_NAME) if self.new else None
|
84
82
|
|
85
83
|
@property
|
86
|
-
def cleaned_old_data(self) ->
|
84
|
+
def cleaned_old_data(self) -> dict[str, Any] | None:
|
87
85
|
return _clean_datafile_content(self.old)
|
88
86
|
|
89
87
|
@property
|
90
|
-
def cleaned_new_data(self) ->
|
88
|
+
def cleaned_new_data(self) -> dict[str, Any] | None:
|
91
89
|
return _clean_datafile_content(self.new)
|
92
90
|
|
93
91
|
|
94
|
-
def _clean_datafile_content(data:
|
92
|
+
def _clean_datafile_content(data: dict[str, Any] | None) -> dict[str, Any] | None:
|
95
93
|
"""
|
96
94
|
Sadly, datafiles mix and match data and metadata in the same file. This
|
97
95
|
function removes some metadata that is otherwise annoying to deal with.
|
@@ -117,9 +115,9 @@ class QontractServerResourcefileDiffState(BaseModel):
|
|
117
115
|
|
118
116
|
path: str
|
119
117
|
content: str
|
120
|
-
resourcefileschema:
|
118
|
+
resourcefileschema: str | None = Field(..., alias="$schema")
|
121
119
|
sha256sum: str
|
122
|
-
backrefs:
|
120
|
+
backrefs: list[QontractServerResourcefileBackref] | None
|
123
121
|
|
124
122
|
|
125
123
|
class QontractServerResourcefileDiff(BaseModel):
|
@@ -128,11 +126,11 @@ class QontractServerResourcefileDiff(BaseModel):
|
|
128
126
|
"""
|
129
127
|
|
130
128
|
resourcepath: str
|
131
|
-
old:
|
132
|
-
new:
|
129
|
+
old: QontractServerResourcefileDiffState | None = None
|
130
|
+
new: QontractServerResourcefileDiffState | None = None
|
133
131
|
|
134
132
|
@property
|
135
|
-
def resourcefileschema(self) ->
|
133
|
+
def resourcefileschema(self) -> str | None:
|
136
134
|
old_schema = self.old.resourcefileschema if self.old else None
|
137
135
|
new_schema = self.new.resourcefileschema if self.new else None
|
138
136
|
return new_schema or old_schema
|
@@ -160,7 +158,7 @@ class FileDiffResolver(Protocol):
|
|
160
158
|
@abstractmethod
|
161
159
|
def lookup_file_diff(
|
162
160
|
self, file_ref: FileRef
|
163
|
-
) ->
|
161
|
+
) -> tuple[dict[str, Any] | None, dict[str, Any] | None]: ...
|
164
162
|
|
165
163
|
|
166
164
|
@dataclass
|
@@ -174,7 +172,7 @@ class QontractServerFileDiffResolver:
|
|
174
172
|
|
175
173
|
def lookup_file_diff(
|
176
174
|
self, file_ref: FileRef
|
177
|
-
) ->
|
175
|
+
) -> tuple[dict[str, Any] | None, dict[str, Any] | None]:
|
178
176
|
data = get_diff(
|
179
177
|
old_sha=self.comparison_sha,
|
180
178
|
file_type=file_ref.file_type.value,
|
@@ -191,7 +189,7 @@ class NoOpFileDiffResolver:
|
|
191
189
|
|
192
190
|
def lookup_file_diff(
|
193
191
|
self, file_ref: FileRef
|
194
|
-
) ->
|
192
|
+
) -> tuple[dict[str, Any] | None, dict[str, Any] | None]:
|
195
193
|
raise Exception(
|
196
194
|
"NoOpFileDiffResolver is not supposed to be used in "
|
197
195
|
"runtime contexts where lookups are needed"
|