qontract-reconcile 0.10.2.dev394__py3-none-any.whl → 0.10.2.dev414__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.2.dev394.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/METADATA +4 -3
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/RECORD +308 -308
- reconcile/acs_rbac.py +2 -2
- reconcile/aus/advanced_upgrade_service.py +15 -12
- reconcile/aus/base.py +9 -13
- reconcile/aus/cluster_version_data.py +15 -5
- reconcile/aus/models.py +1 -1
- reconcile/automated_actions/config/integration.py +15 -3
- reconcile/aws_account_manager/integration.py +6 -6
- reconcile/aws_account_manager/reconciler.py +3 -3
- reconcile/aws_ami_cleanup/integration.py +2 -5
- reconcile/aws_ami_share.py +69 -62
- reconcile/aws_saml_idp/integration.py +5 -3
- reconcile/aws_saml_roles/integration.py +23 -22
- reconcile/aws_version_sync/integration.py +6 -12
- reconcile/change_owners/bundle.py +3 -3
- reconcile/change_owners/change_log_tracking.py +3 -2
- reconcile/change_owners/change_owners.py +1 -1
- reconcile/dashdotdb_dora.py +1 -1
- reconcile/dashdotdb_slo.py +1 -1
- reconcile/database_access_manager.py +8 -9
- reconcile/dynatrace_token_provider/integration.py +1 -1
- reconcile/endpoints_discovery/integration.py +4 -1
- reconcile/endpoints_discovery/merge_request.py +1 -1
- reconcile/endpoints_discovery/merge_request_manager.py +1 -1
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +19 -7
- reconcile/external_resources/metrics.py +1 -1
- reconcile/external_resources/model.py +6 -6
- reconcile/external_resources/reconciler.py +7 -4
- reconcile/external_resources/secrets_sync.py +2 -2
- reconcile/external_resources/state.py +56 -14
- reconcile/fleet_labeler/integration.py +1 -1
- reconcile/gcp_image_mirror.py +2 -2
- reconcile/github_org.py +1 -1
- reconcile/github_owners.py +4 -0
- reconcile/gitlab_members.py +6 -12
- reconcile/gitlab_permissions.py +8 -12
- reconcile/glitchtip_project_alerts/integration.py +3 -1
- reconcile/gql_definitions/acs/acs_instances.py +5 -5
- reconcile/gql_definitions/acs/acs_policies.py +5 -5
- reconcile/gql_definitions/acs/acs_rbac.py +5 -5
- reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +5 -5
- reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +5 -5
- reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +5 -5
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
- reconcile/gql_definitions/automated_actions/instance.py +46 -7
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
- reconcile/gql_definitions/aws_version_sync/clusters.py +5 -5
- reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
- reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
- reconcile/gql_definitions/change_owners/queries/self_service_roles.py +5 -5
- reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +5 -5
- reconcile/gql_definitions/common/alerting_services_settings.py +5 -5
- reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
- reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
- reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_roles.py +5 -5
- reconcile/gql_definitions/common/app_interface_state_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
- reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
- reconcile/gql_definitions/common/apps.py +5 -5
- reconcile/gql_definitions/common/aws_vpc_requests.py +5 -5
- reconcile/gql_definitions/common/aws_vpcs.py +5 -5
- reconcile/gql_definitions/common/clusters.py +5 -5
- reconcile/gql_definitions/common/clusters_minimal.py +5 -5
- reconcile/gql_definitions/common/clusters_with_dms.py +5 -5
- reconcile/gql_definitions/common/clusters_with_peering.py +5 -5
- reconcile/gql_definitions/common/github_orgs.py +5 -5
- reconcile/gql_definitions/common/jira_settings.py +5 -5
- reconcile/gql_definitions/common/jiralert_settings.py +5 -5
- reconcile/gql_definitions/common/ldap_settings.py +5 -5
- reconcile/gql_definitions/common/namespaces.py +5 -5
- reconcile/gql_definitions/common/namespaces_minimal.py +7 -5
- reconcile/gql_definitions/common/ocm_env_telemeter.py +5 -5
- reconcile/gql_definitions/common/ocm_environments.py +5 -5
- reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
- reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -5
- reconcile/gql_definitions/common/pipeline_providers.py +5 -5
- reconcile/gql_definitions/common/quay_instances.py +5 -5
- reconcile/gql_definitions/common/quay_orgs.py +5 -5
- reconcile/gql_definitions/common/reserved_networks.py +5 -5
- reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
- reconcile/gql_definitions/common/saas_files.py +5 -5
- reconcile/gql_definitions/common/saas_target_namespaces.py +5 -5
- reconcile/gql_definitions/common/saasherder_settings.py +5 -5
- reconcile/gql_definitions/common/slack_workspaces.py +5 -5
- reconcile/gql_definitions/common/smtp_client_settings.py +5 -5
- reconcile/gql_definitions/common/state_aws_account.py +5 -5
- reconcile/gql_definitions/common/users.py +5 -5
- reconcile/gql_definitions/common/users_with_paths.py +5 -5
- reconcile/gql_definitions/cost_report/app_names.py +5 -5
- reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
- reconcile/gql_definitions/cost_report/settings.py +5 -5
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +5 -5
- reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +5 -5
- reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
- reconcile/gql_definitions/email_sender/apps.py +5 -5
- reconcile/gql_definitions/email_sender/emails.py +5 -5
- reconcile/gql_definitions/email_sender/users.py +5 -5
- reconcile/gql_definitions/endpoints_discovery/apps.py +5 -5
- reconcile/gql_definitions/external_resources/aws_accounts.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_modules.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_settings.py +5 -5
- reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
- reconcile/gql_definitions/fleet_labeler/fleet_labels.py +5 -5
- reconcile/gql_definitions/fragments/aus_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_common.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
- reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
- reconcile/gql_definitions/fragments/aws_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc_request.py +5 -5
- reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
- reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
- reconcile/gql_definitions/fragments/disable.py +5 -5
- reconcile/gql_definitions/fragments/email_service.py +5 -5
- reconcile/gql_definitions/fragments/email_user.py +5 -5
- reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
- reconcile/gql_definitions/fragments/membership_source.py +5 -5
- reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
- reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
- reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
- reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
- reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
- reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_values.py +5 -5
- reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
- reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
- reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
- reconcile/gql_definitions/fragments/terraform_state.py +5 -5
- reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
- reconcile/gql_definitions/fragments/user.py +5 -5
- reconcile/gql_definitions/fragments/vault_secret.py +5 -5
- reconcile/gql_definitions/gcp/gcp_docker_repos.py +5 -5
- reconcile/gql_definitions/gcp/gcp_projects.py +5 -5
- reconcile/gql_definitions/gitlab_members/gitlab_instances.py +5 -5
- reconcile/gql_definitions/gitlab_members/permissions.py +5 -5
- reconcile/gql_definitions/glitchtip/glitchtip_instance.py +5 -5
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +5 -5
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +5 -5
- reconcile/gql_definitions/integrations/integrations.py +5 -5
- reconcile/gql_definitions/introspection.json +231 -0
- reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +5 -5
- reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +5 -5
- reconcile/gql_definitions/jira/jira_servers.py +5 -5
- reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +5 -5
- reconcile/gql_definitions/jumphosts/jumphosts.py +5 -5
- reconcile/gql_definitions/ldap_groups/roles.py +5 -5
- reconcile/gql_definitions/ldap_groups/settings.py +5 -5
- reconcile/gql_definitions/maintenance/maintenances.py +5 -5
- reconcile/gql_definitions/membershipsources/roles.py +5 -5
- reconcile/gql_definitions/ocm_labels/clusters.py +5 -5
- reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
- reconcile/gql_definitions/openshift_cluster_bots/clusters.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_roles.py +5 -5
- reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +5 -5
- reconcile/gql_definitions/quay_membership/quay_membership.py +5 -5
- reconcile/gql_definitions/rhcs/certs.py +5 -5
- reconcile/gql_definitions/rhidp/organizations.py +5 -5
- reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
- reconcile/gql_definitions/service_dependencies/service_dependencies.py +5 -5
- reconcile/gql_definitions/sharding/aws_accounts.py +5 -5
- reconcile/gql_definitions/sharding/ocm_organization.py +5 -5
- reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
- reconcile/gql_definitions/skupper_network/skupper_networks.py +5 -5
- reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
- reconcile/gql_definitions/slack_usergroups/permissions.py +5 -5
- reconcile/gql_definitions/slack_usergroups/users.py +5 -5
- reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
- reconcile/gql_definitions/status_board/status_board.py +5 -5
- reconcile/gql_definitions/statuspage/statuspages.py +5 -5
- reconcile/gql_definitions/templating/template_collection.py +5 -5
- reconcile/gql_definitions/templating/templates.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +5 -5
- reconcile/gql_definitions/terraform_init/aws_accounts.py +5 -5
- reconcile/gql_definitions/terraform_repo/terraform_repo.py +5 -5
- reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +5 -5
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +5 -5
- reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +5 -5
- reconcile/gql_definitions/vault_instances/vault_instances.py +5 -5
- reconcile/gql_definitions/vault_policies/vault_policies.py +5 -5
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +5 -5
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
- reconcile/integrations_manager.py +3 -3
- reconcile/jenkins_worker_fleets.py +9 -8
- reconcile/jira_permissions_validator.py +2 -2
- reconcile/ldap_groups/integration.py +1 -1
- reconcile/ocm/types.py +35 -57
- reconcile/ocm_aws_infrastructure_access.py +1 -1
- reconcile/ocm_clusters.py +4 -4
- reconcile/ocm_labels/integration.py +3 -2
- reconcile/ocm_machine_pools.py +23 -23
- reconcile/openshift_base.py +53 -2
- reconcile/openshift_cluster_bots.py +1 -1
- reconcile/openshift_namespace_labels.py +1 -1
- reconcile/openshift_namespaces.py +97 -101
- reconcile/openshift_resources_base.py +6 -2
- reconcile/openshift_rhcs_certs.py +5 -5
- reconcile/openshift_rolebindings.py +7 -11
- reconcile/openshift_saas_deploy.py +4 -5
- reconcile/openshift_saas_deploy_change_tester.py +9 -7
- reconcile/openshift_serviceaccount_tokens.py +2 -2
- reconcile/openshift_upgrade_watcher.py +1 -1
- reconcile/oum/labelset.py +5 -3
- reconcile/oum/models.py +1 -4
- reconcile/prometheus_rules_tester/integration.py +3 -3
- reconcile/quay_mirror.py +1 -1
- reconcile/queries.py +6 -0
- reconcile/rhidp/common.py +3 -5
- reconcile/rhidp/sso_client/base.py +1 -1
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
- reconcile/skupper_network/integration.py +2 -2
- reconcile/slack_usergroups.py +31 -11
- reconcile/status_board.py +6 -6
- reconcile/statuspage/atlassian.py +7 -7
- reconcile/statuspage/page.py +4 -9
- reconcile/templating/lib/rendering.py +3 -3
- reconcile/templating/renderer.py +2 -2
- reconcile/terraform_cloudflare_dns.py +3 -3
- reconcile/terraform_cloudflare_resources.py +5 -5
- reconcile/terraform_cloudflare_users.py +3 -2
- reconcile/terraform_init/integration.py +2 -2
- reconcile/terraform_repo.py +16 -12
- reconcile/terraform_resources.py +6 -6
- reconcile/terraform_tgw_attachments.py +20 -18
- reconcile/terraform_vpc_resources/integration.py +3 -1
- reconcile/typed_queries/cost_report/app_names.py +1 -1
- reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
- reconcile/typed_queries/saas_files.py +11 -11
- reconcile/typed_queries/status_board.py +2 -2
- reconcile/unleash_feature_toggles/integration.py +4 -2
- reconcile/utils/acs/base.py +6 -3
- reconcile/utils/acs/policies.py +2 -2
- reconcile/utils/aws_api.py +51 -20
- reconcile/utils/aws_api_typed/organization.py +4 -2
- reconcile/utils/deadmanssnitch_api.py +1 -1
- reconcile/utils/early_exit_cache.py +8 -10
- reconcile/utils/gitlab_api.py +7 -5
- reconcile/utils/glitchtip/client.py +6 -2
- reconcile/utils/glitchtip/models.py +25 -28
- reconcile/utils/gql.py +4 -7
- reconcile/utils/instrumented_wrappers.py +1 -1
- reconcile/utils/internal_groups/client.py +2 -2
- reconcile/utils/internal_groups/models.py +8 -17
- reconcile/utils/jinja2/utils.py +2 -5
- reconcile/utils/jobcontroller/controller.py +1 -1
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/json.py +39 -1
- reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
- reconcile/utils/membershipsources/models.py +16 -23
- reconcile/utils/membershipsources/resolver.py +4 -2
- reconcile/utils/merge_request_manager/merge_request_manager.py +1 -1
- reconcile/utils/merge_request_manager/parser.py +4 -4
- reconcile/utils/metrics.py +5 -5
- reconcile/utils/models.py +304 -82
- reconcile/utils/mr/notificator.py +1 -1
- reconcile/utils/mr/user_maintenance.py +3 -2
- reconcile/utils/oc.py +112 -92
- reconcile/utils/ocm/addons.py +0 -1
- reconcile/utils/ocm/base.py +17 -20
- reconcile/utils/ocm/cluster_groups.py +1 -1
- reconcile/utils/ocm/identity_providers.py +2 -2
- reconcile/utils/ocm/labels.py +1 -1
- reconcile/utils/ocm/products.py +8 -8
- reconcile/utils/ocm/service_log.py +1 -1
- reconcile/utils/ocm/sre_capability_labels.py +20 -13
- reconcile/utils/openshift_resource.py +5 -0
- reconcile/utils/pagerduty_api.py +5 -2
- reconcile/utils/promotion_state.py +6 -11
- reconcile/utils/raw_github_api.py +1 -1
- reconcile/utils/rhcsv2_certs.py +1 -4
- reconcile/utils/runtime/integration.py +1 -1
- reconcile/utils/saasherder/interfaces.py +13 -20
- reconcile/utils/saasherder/models.py +23 -20
- reconcile/utils/saasherder/saasherder.py +26 -17
- reconcile/utils/slack_api.py +2 -2
- reconcile/utils/structs.py +1 -1
- reconcile/utils/terraform_client.py +1 -1
- reconcile/utils/terrascript_aws_client.py +47 -43
- reconcile/utils/unleash/server.py +2 -8
- reconcile/utils/vault.py +4 -11
- reconcile/utils/vcs.py +8 -8
- reconcile/vault_replication.py +1 -1
- tools/cli_commands/cost_report/cost_management_api.py +3 -3
- tools/cli_commands/cost_report/view.py +7 -6
- tools/cli_commands/erv2.py +3 -1
- tools/qontract_cli.py +6 -5
- tools/template_validation.py +3 -1
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev414.dist-info}/entry_points.txt +0 -0
|
@@ -164,7 +164,9 @@ class GlitchtipClient(ApiBase):
|
|
|
164
164
|
return ProjectAlert(
|
|
165
165
|
**self._post(
|
|
166
166
|
f"/api/0/projects/{organization_slug}/{project_slug}/alerts/",
|
|
167
|
-
data=alert.
|
|
167
|
+
data=alert.model_dump(
|
|
168
|
+
by_alias=True, exclude_unset=True, exclude_none=True
|
|
169
|
+
),
|
|
168
170
|
)
|
|
169
171
|
)
|
|
170
172
|
|
|
@@ -183,7 +185,9 @@ class GlitchtipClient(ApiBase):
|
|
|
183
185
|
return ProjectAlert(
|
|
184
186
|
**self._put(
|
|
185
187
|
f"/api/0/projects/{organization_slug}/{project_slug}/alerts/{alert.pk}/",
|
|
186
|
-
data=alert.
|
|
188
|
+
data=alert.model_dump(
|
|
189
|
+
by_alias=True, exclude_unset=True, exclude_none=True
|
|
190
|
+
),
|
|
187
191
|
)
|
|
188
192
|
)
|
|
189
193
|
|
|
@@ -3,13 +3,13 @@ from __future__ import annotations
|
|
|
3
3
|
import re
|
|
4
4
|
from datetime import datetime
|
|
5
5
|
from enum import Enum
|
|
6
|
-
from typing import TYPE_CHECKING, Any
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Self
|
|
7
7
|
|
|
8
8
|
from pydantic import (
|
|
9
9
|
BaseModel,
|
|
10
10
|
Field,
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
field_validator,
|
|
12
|
+
model_validator,
|
|
13
13
|
)
|
|
14
14
|
|
|
15
15
|
if TYPE_CHECKING:
|
|
@@ -49,7 +49,8 @@ class Team(BaseModel):
|
|
|
49
49
|
slug: str = ""
|
|
50
50
|
users: list[User] = []
|
|
51
51
|
|
|
52
|
-
@
|
|
52
|
+
@model_validator(mode="before")
|
|
53
|
+
@classmethod
|
|
53
54
|
def name_xor_slug_must_be_set(
|
|
54
55
|
cls, values: MutableMapping[str, Any]
|
|
55
56
|
) -> MutableMapping[str, Any]:
|
|
@@ -58,11 +59,11 @@ class Team(BaseModel):
|
|
|
58
59
|
), "name xor slug must be set!"
|
|
59
60
|
return values
|
|
60
61
|
|
|
61
|
-
@
|
|
62
|
-
def slugify(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return
|
|
62
|
+
@model_validator(mode="after")
|
|
63
|
+
def slugify(self) -> Self:
|
|
64
|
+
self.slug = self.slug or slugify(self.name)
|
|
65
|
+
self.name = slugify(self.name) or self.slug
|
|
66
|
+
return self
|
|
66
67
|
|
|
67
68
|
def __lt__(self, other: Team) -> bool:
|
|
68
69
|
return self.slug < other.slug
|
|
@@ -86,16 +87,15 @@ class RecipientType(Enum):
|
|
|
86
87
|
WEBHOOK = "webhook"
|
|
87
88
|
|
|
88
89
|
|
|
89
|
-
class ProjectAlertRecipient(
|
|
90
|
+
class ProjectAlertRecipient(
|
|
91
|
+
BaseModel, validate_by_name=True, validate_by_alias=True, use_enum_values=True
|
|
92
|
+
):
|
|
90
93
|
pk: int | None = Field(None, alias="id")
|
|
91
94
|
recipient_type: RecipientType = Field(..., alias="recipientType")
|
|
92
95
|
url: str = ""
|
|
93
96
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
use_enum_values = True
|
|
97
|
-
|
|
98
|
-
@validator("recipient_type")
|
|
97
|
+
@field_validator("recipient_type")
|
|
98
|
+
@classmethod
|
|
99
99
|
def recipient_type_enforce_enum_type(cls, v: str | RecipientType) -> RecipientType:
|
|
100
100
|
if isinstance(v, RecipientType):
|
|
101
101
|
return v
|
|
@@ -113,17 +113,15 @@ class ProjectAlertRecipient(BaseModel):
|
|
|
113
113
|
return hash((self.recipient_type, self.url))
|
|
114
114
|
|
|
115
115
|
|
|
116
|
-
class ProjectAlert(BaseModel):
|
|
116
|
+
class ProjectAlert(BaseModel, validate_by_name=True, validate_by_alias=True):
|
|
117
117
|
pk: int | None = Field(None, alias="id")
|
|
118
118
|
name: str
|
|
119
119
|
timespan_minutes: int = Field(..., alias="timespanMinutes")
|
|
120
120
|
quantity: int
|
|
121
121
|
recipients: list[ProjectAlertRecipient] = Field([], alias="alertRecipients")
|
|
122
122
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
@root_validator
|
|
123
|
+
@model_validator(mode="before")
|
|
124
|
+
@classmethod
|
|
127
125
|
def empty_name(cls, values: MutableMapping[str, Any]) -> MutableMapping[str, Any]:
|
|
128
126
|
# name is an empty string if the alert was created manually because it can't be set via UI
|
|
129
127
|
# use the pk instead.
|
|
@@ -141,20 +139,18 @@ class ProjectAlert(BaseModel):
|
|
|
141
139
|
)
|
|
142
140
|
|
|
143
141
|
|
|
144
|
-
class Project(BaseModel):
|
|
142
|
+
class Project(BaseModel, validate_by_name=True, validate_by_alias=True):
|
|
145
143
|
pk: int | None = Field(None, alias="id")
|
|
146
144
|
name: str
|
|
147
145
|
slug: str = ""
|
|
148
|
-
platform: str | None
|
|
146
|
+
platform: str | None = None
|
|
149
147
|
teams: list[Team] = []
|
|
150
148
|
alerts: list[ProjectAlert] = []
|
|
151
149
|
event_throttle_rate: int = Field(0, alias="eventThrottleRate")
|
|
152
150
|
organization: Organization | None = None
|
|
153
151
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
@root_validator
|
|
152
|
+
@model_validator(mode="before")
|
|
153
|
+
@classmethod
|
|
158
154
|
def slugify(cls, values: MutableMapping[str, Any]) -> MutableMapping[str, Any]:
|
|
159
155
|
values["slug"] = values.get("slug") or slugify(values["name"])
|
|
160
156
|
return values
|
|
@@ -195,7 +191,8 @@ class Organization(BaseModel):
|
|
|
195
191
|
teams: list[Team] = []
|
|
196
192
|
users: list[User] = []
|
|
197
193
|
|
|
198
|
-
@
|
|
194
|
+
@model_validator(mode="before")
|
|
195
|
+
@classmethod
|
|
199
196
|
def slugify(cls, values: MutableMapping[str, Any]) -> MutableMapping[str, Any]:
|
|
200
197
|
values["slug"] = values.get("slug") or slugify(values["name"])
|
|
201
198
|
return values
|
|
@@ -212,4 +209,4 @@ class Organization(BaseModel):
|
|
|
212
209
|
return hash(self.name)
|
|
213
210
|
|
|
214
211
|
|
|
215
|
-
Project.
|
|
212
|
+
Project.model_rebuild()
|
reconcile/utils/gql.py
CHANGED
|
@@ -109,7 +109,7 @@ class GqlApi:
|
|
|
109
109
|
if int_name:
|
|
110
110
|
integrations = self.query(INTEGRATIONS_QUERY, skip_validation=True)
|
|
111
111
|
|
|
112
|
-
for integration in integrations["integrations"]:
|
|
112
|
+
for integration in integrations["integrations"] if integrations else []:
|
|
113
113
|
if integration["name"] == int_name:
|
|
114
114
|
self._valid_schemas = integration["schemas"]
|
|
115
115
|
break
|
|
@@ -142,7 +142,7 @@ class GqlApi:
|
|
|
142
142
|
query: str,
|
|
143
143
|
variables: dict[str, Any] | None = None,
|
|
144
144
|
skip_validation: bool = False,
|
|
145
|
-
) -> dict[str, Any]
|
|
145
|
+
) -> dict[str, Any]:
|
|
146
146
|
try:
|
|
147
147
|
result = self.client.execute(
|
|
148
148
|
gql(query), variables, get_execution_result=True
|
|
@@ -172,11 +172,8 @@ class GqlApi:
|
|
|
172
172
|
if forbidden_schemas:
|
|
173
173
|
raise GqlApiErrorForbiddenSchemaError(forbidden_schemas)
|
|
174
174
|
|
|
175
|
-
#
|
|
176
|
-
|
|
177
|
-
if result["data"] is None:
|
|
178
|
-
raise GqlApiError("`data` not received in GraphQL payload")
|
|
179
|
-
|
|
175
|
+
# make mypy happy
|
|
176
|
+
assert "data" in result and result["data"] is not None
|
|
180
177
|
return result["data"]
|
|
181
178
|
|
|
182
179
|
def get_template(self, path: str) -> dict[str, str]:
|
|
@@ -40,7 +40,7 @@ class InstrumentedImage(Image):
|
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
class InstrumentedSkopeo(Skopeo):
|
|
43
|
-
def copy(self, *args: Any, **kwargs: Any) ->
|
|
43
|
+
def copy(self, *args: Any, **kwargs: Any) -> None:
|
|
44
44
|
metrics.copy_count.labels(
|
|
45
45
|
integration=INTEGRATION_NAME, shard=SHARDS, shard_id=SHARD_ID
|
|
46
46
|
).inc()
|
|
@@ -140,7 +140,7 @@ class InternalGroupsClient:
|
|
|
140
140
|
with self._api as api:
|
|
141
141
|
return Group(
|
|
142
142
|
**api.create_group(
|
|
143
|
-
data=group.
|
|
143
|
+
data=group.model_dump(by_alias=True),
|
|
144
144
|
)
|
|
145
145
|
)
|
|
146
146
|
|
|
@@ -155,6 +155,6 @@ class InternalGroupsClient:
|
|
|
155
155
|
return Group(
|
|
156
156
|
**api.update_group(
|
|
157
157
|
name=group.name,
|
|
158
|
-
data=group.
|
|
158
|
+
data=group.model_dump(by_alias=True),
|
|
159
159
|
)
|
|
160
160
|
)
|
|
@@ -27,7 +27,7 @@ class Entity(BaseModel):
|
|
|
27
27
|
return hash(self.id)
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
class Group(BaseModel):
|
|
30
|
+
class Group(BaseModel, validate_by_name=True, validate_by_alias=True):
|
|
31
31
|
name: str
|
|
32
32
|
description: str
|
|
33
33
|
member_approval_type: str = Field("self-service", alias="memberApprovalType")
|
|
@@ -35,16 +35,18 @@ class Group(BaseModel):
|
|
|
35
35
|
owners: list[Entity]
|
|
36
36
|
display_name: str = Field(..., alias="displayName")
|
|
37
37
|
notes: str | None = None
|
|
38
|
-
rover_group_member_query: str | None = Field(
|
|
38
|
+
rover_group_member_query: str | None = Field(
|
|
39
|
+
None, alias="roverGroupMemberQuery", exclude=True
|
|
40
|
+
)
|
|
39
41
|
rover_group_inclusions: list[Entity] | None = Field(
|
|
40
|
-
None, alias="roverGroupInclusions"
|
|
42
|
+
None, alias="roverGroupInclusions", exclude=True
|
|
41
43
|
)
|
|
42
44
|
rover_group_exclusions: list[Entity] | None = Field(
|
|
43
|
-
None, alias="roverGroupExclusions"
|
|
45
|
+
None, alias="roverGroupExclusions", exclude=True
|
|
44
46
|
)
|
|
45
47
|
members: list[Entity] = []
|
|
46
|
-
member_of: list[str] | None = Field(None, alias="memberOf")
|
|
47
|
-
namespace: str | None = None
|
|
48
|
+
member_of: list[str] | None = Field(None, alias="memberOf", exclude=True)
|
|
49
|
+
namespace: str | None = Field(None, exclude=True)
|
|
48
50
|
|
|
49
51
|
def __eq__(self, other: object) -> bool:
|
|
50
52
|
if not isinstance(other, Group):
|
|
@@ -58,14 +60,3 @@ class Group(BaseModel):
|
|
|
58
60
|
and self.notes == other.notes
|
|
59
61
|
and set(self.members) == set(other.members)
|
|
60
62
|
)
|
|
61
|
-
|
|
62
|
-
class Config:
|
|
63
|
-
allow_population_by_field_name = True
|
|
64
|
-
# exclude read-only fields in the json/dict dumps
|
|
65
|
-
fields = {
|
|
66
|
-
"rover_group_member_query": {"exclude": True},
|
|
67
|
-
"rover_group_inclusions": {"exclude": True},
|
|
68
|
-
"rover_group_exclusions": {"exclude": True},
|
|
69
|
-
"member_of": {"exclude": True},
|
|
70
|
-
"namespace": {"exclude": True},
|
|
71
|
-
}
|
reconcile/utils/jinja2/utils.py
CHANGED
|
@@ -45,14 +45,11 @@ class Jinja2TemplateError(Exception):
|
|
|
45
45
|
super().__init__("error processing jinja2 template: " + str(msg))
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
class TemplateRenderOptions(BaseModel):
|
|
48
|
+
class TemplateRenderOptions(BaseModel, frozen=True):
|
|
49
49
|
trim_blocks: bool
|
|
50
50
|
lstrip_blocks: bool
|
|
51
51
|
keep_trailing_newline: bool
|
|
52
52
|
|
|
53
|
-
class Config:
|
|
54
|
-
frozen = True
|
|
55
|
-
|
|
56
53
|
@classmethod
|
|
57
54
|
def create(
|
|
58
55
|
cls,
|
|
@@ -75,7 +72,7 @@ def compile_jinja2_template(
|
|
|
75
72
|
) -> Any:
|
|
76
73
|
if not template_render_options:
|
|
77
74
|
template_render_options = TemplateRenderOptions.create()
|
|
78
|
-
env: dict[str, Any] = template_render_options.
|
|
75
|
+
env: dict[str, Any] = template_render_options.model_dump()
|
|
79
76
|
if extra_curly:
|
|
80
77
|
env.update({
|
|
81
78
|
"block_start_string": "{{%",
|
|
@@ -38,6 +38,8 @@ class JobValidationError(Exception):
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
JOB_GENERATION_ANNOTATION = "qontract-reconcile/job.generation"
|
|
41
|
+
MAX_JOB_NAME_LENGTH = 63
|
|
42
|
+
UNIT_OF_WORK_DIGEST_LENGTH = 10
|
|
41
43
|
|
|
42
44
|
|
|
43
45
|
class K8sJob(ABC):
|
|
@@ -72,7 +74,21 @@ class K8sJob(ABC):
|
|
|
72
74
|
"""
|
|
73
75
|
|
|
74
76
|
def name(self) -> str:
|
|
75
|
-
|
|
77
|
+
"""
|
|
78
|
+
Generate the full job name by combining the name prefix with a digest.
|
|
79
|
+
|
|
80
|
+
The name is constructed from the name_prefix (truncated to ensure total
|
|
81
|
+
length compliance) and the unit_of_work_digest. The total length is
|
|
82
|
+
limited to MAX_JOB_NAME_LENGTH (63 characters) to comply with Kubernetes
|
|
83
|
+
naming constraints.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
A unique job name in the format: {name_prefix}-{digest}
|
|
87
|
+
"""
|
|
88
|
+
prefix = self.name_prefix()[
|
|
89
|
+
: MAX_JOB_NAME_LENGTH - UNIT_OF_WORK_DIGEST_LENGTH - 1
|
|
90
|
+
]
|
|
91
|
+
return f"{prefix}-{self.unit_of_work_digest(UNIT_OF_WORK_DIGEST_LENGTH)}"
|
|
76
92
|
|
|
77
93
|
@abstractmethod
|
|
78
94
|
def name_prefix(self) -> str:
|
reconcile/utils/json.py
CHANGED
|
@@ -1,15 +1,48 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from dataclasses import asdict, is_dataclass
|
|
4
|
+
from datetime import date, datetime
|
|
5
|
+
from decimal import Decimal
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from typing import Any, Literal
|
|
8
|
+
|
|
9
|
+
from pydantic import BaseModel
|
|
3
10
|
|
|
4
11
|
JSON_COMPACT_SEPARATORS = (",", ":")
|
|
5
12
|
|
|
6
13
|
|
|
14
|
+
def pydantic_encoder(obj: Any) -> Any:
|
|
15
|
+
if isinstance(obj, BaseModel):
|
|
16
|
+
return obj.model_dump()
|
|
17
|
+
|
|
18
|
+
if is_dataclass(obj):
|
|
19
|
+
return asdict(obj) # type: ignore
|
|
20
|
+
|
|
21
|
+
if isinstance(obj, (datetime, date)):
|
|
22
|
+
return obj.isoformat()
|
|
23
|
+
|
|
24
|
+
if isinstance(obj, Enum):
|
|
25
|
+
return obj.value
|
|
26
|
+
|
|
27
|
+
if isinstance(obj, Decimal):
|
|
28
|
+
return float(obj)
|
|
29
|
+
|
|
30
|
+
raise TypeError(
|
|
31
|
+
f"Object of type '{obj.__class__.__name__}' is not JSON serializable"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
7
35
|
def json_dumps(
|
|
8
36
|
data: Any,
|
|
9
37
|
*,
|
|
10
38
|
compact: bool = False,
|
|
11
39
|
indent: int | None = None,
|
|
12
40
|
cls: type[json.JSONEncoder] | None = None,
|
|
41
|
+
defaults: Callable | None = None,
|
|
42
|
+
# BaseModel dump parameters
|
|
43
|
+
by_alias: bool = True,
|
|
44
|
+
exclude_none: bool = False,
|
|
45
|
+
mode: Literal["json", "python"] = "json",
|
|
13
46
|
) -> str:
|
|
14
47
|
"""
|
|
15
48
|
Serialize `data` to a consistent JSON formatted `str` with dict keys sorted.
|
|
@@ -22,6 +55,10 @@ def json_dumps(
|
|
|
22
55
|
Returns:
|
|
23
56
|
A JSON formatted string.
|
|
24
57
|
"""
|
|
58
|
+
if isinstance(data, BaseModel):
|
|
59
|
+
data = data.model_dump(mode=mode, by_alias=by_alias, exclude_none=exclude_none)
|
|
60
|
+
if mode == "python":
|
|
61
|
+
defaults = pydantic_encoder
|
|
25
62
|
separators = JSON_COMPACT_SEPARATORS if compact else None
|
|
26
63
|
return json.dumps(
|
|
27
64
|
data,
|
|
@@ -29,4 +66,5 @@ def json_dumps(
|
|
|
29
66
|
separators=separators,
|
|
30
67
|
sort_keys=True,
|
|
31
68
|
cls=cls,
|
|
69
|
+
default=defaults,
|
|
32
70
|
)
|
|
@@ -55,6 +55,8 @@ def resolve_app_interface_membership_source(
|
|
|
55
55
|
|
|
56
56
|
def build_member_list(role: RoleV1) -> list[RoleMember]:
|
|
57
57
|
members: list[RoleMember] = []
|
|
58
|
-
members.extend([RoleUser(**u.
|
|
59
|
-
members.extend([
|
|
58
|
+
members.extend([RoleUser(**u.model_dump()) for u in role.users or []])
|
|
59
|
+
members.extend([
|
|
60
|
+
RoleBot(**b.model_dump()) for b in role.bots or [] if b.org_username
|
|
61
|
+
])
|
|
60
62
|
return members
|
|
@@ -7,7 +7,6 @@ from typing import (
|
|
|
7
7
|
|
|
8
8
|
from pydantic import (
|
|
9
9
|
BaseModel,
|
|
10
|
-
Extra,
|
|
11
10
|
)
|
|
12
11
|
|
|
13
12
|
from reconcile.gql_definitions.fragments.membership_source import (
|
|
@@ -23,7 +22,7 @@ class User(Protocol):
|
|
|
23
22
|
@property
|
|
24
23
|
def org_username(self) -> str: ...
|
|
25
24
|
|
|
26
|
-
def
|
|
25
|
+
def model_dump(self, *, by_alias: bool = False) -> dict[str, Any]: ...
|
|
27
26
|
|
|
28
27
|
|
|
29
28
|
class Bot(Protocol):
|
|
@@ -33,7 +32,7 @@ class Bot(Protocol):
|
|
|
33
32
|
@property
|
|
34
33
|
def org_username(self) -> str | None: ...
|
|
35
34
|
|
|
36
|
-
def
|
|
35
|
+
def model_dump(self, *, by_alias: bool = False) -> dict[str, Any]: ...
|
|
37
36
|
|
|
38
37
|
|
|
39
38
|
class RoleWithMemberships(Protocol):
|
|
@@ -50,33 +49,27 @@ class RoleWithMemberships(Protocol):
|
|
|
50
49
|
def member_sources(self) -> Sequence[RoleMembershipSource] | None: ...
|
|
51
50
|
|
|
52
51
|
|
|
53
|
-
class RoleUser(BaseModel):
|
|
52
|
+
class RoleUser(BaseModel, extra="ignore"):
|
|
54
53
|
name: str
|
|
55
54
|
org_username: str
|
|
56
|
-
github_username: str | None
|
|
57
|
-
quay_username: str | None
|
|
58
|
-
pagerduty_username: str | None
|
|
59
|
-
aws_username: str | None
|
|
60
|
-
cloudflare_user: str | None
|
|
61
|
-
public_gpg_key: str | None
|
|
55
|
+
github_username: str | None = None
|
|
56
|
+
quay_username: str | None = None
|
|
57
|
+
pagerduty_username: str | None = None
|
|
58
|
+
aws_username: str | None = None
|
|
59
|
+
cloudflare_user: str | None = None
|
|
60
|
+
public_gpg_key: str | None = None
|
|
62
61
|
tag_on_cluster_updates: bool | None = False
|
|
63
62
|
tag_on_merge_requests: bool | None = False
|
|
64
63
|
|
|
65
|
-
class Config:
|
|
66
|
-
extra = Extra.ignore
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
class RoleBot(BaseModel):
|
|
65
|
+
class RoleBot(BaseModel, extra="ignore"):
|
|
70
66
|
name: str
|
|
71
|
-
description: str | None
|
|
72
|
-
org_username: str | None
|
|
73
|
-
github_username: str | None
|
|
74
|
-
gitlab_username: str | None
|
|
75
|
-
openshift_serviceaccount: str | None
|
|
76
|
-
quay_username: str | None
|
|
77
|
-
|
|
78
|
-
class Config:
|
|
79
|
-
extra = Extra.ignore
|
|
67
|
+
description: str | None = None
|
|
68
|
+
org_username: str | None = None
|
|
69
|
+
github_username: str | None = None
|
|
70
|
+
gitlab_username: str | None = None
|
|
71
|
+
openshift_serviceaccount: str | None = None
|
|
72
|
+
quay_username: str | None = None
|
|
80
73
|
|
|
81
74
|
|
|
82
75
|
RoleMember = RoleUser | RoleBot
|
|
@@ -98,8 +98,10 @@ def resolve_role_members(
|
|
|
98
98
|
members: list[RoleMember] = []
|
|
99
99
|
|
|
100
100
|
# bring in the local users and bots ...
|
|
101
|
-
members.extend(RoleUser(**u.
|
|
102
|
-
members.extend(
|
|
101
|
+
members.extend(RoleUser(**u.model_dump()) for u in r.users or [])
|
|
102
|
+
members.extend(
|
|
103
|
+
RoleBot(**b.model_dump()) for b in r.bots or [] if b.org_username
|
|
104
|
+
)
|
|
103
105
|
|
|
104
106
|
# ... and enhance with the ones from member sources
|
|
105
107
|
for ms in r.member_sources or []:
|
|
@@ -42,7 +42,7 @@ class MergeRequestManagerBase[T: BaseModel]:
|
|
|
42
42
|
expected_data: dict[str, Any],
|
|
43
43
|
) -> OpenMergeRequest | None:
|
|
44
44
|
for mr in self._open_mrs:
|
|
45
|
-
mr_info_dict = mr.mr_info.
|
|
45
|
+
mr_info_dict = mr.mr_info.model_dump()
|
|
46
46
|
if all(mr_info_dict.get(k) == expected_data.get(k) for k in expected_data):
|
|
47
47
|
return mr
|
|
48
48
|
|
|
@@ -60,8 +60,8 @@ class Parser[T: BaseModel]:
|
|
|
60
60
|
|
|
61
61
|
if self.expected_version != self._find_by_name(self.version_ref, parts[1]):
|
|
62
62
|
raise ParserVersionError("Version is outdated")
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
self.klass, self._data_from_description(parts[1]), use_defaults=False
|
|
66
|
-
)
|
|
63
|
+
data = data_default_none(
|
|
64
|
+
self.klass, self._data_from_description(parts[1]), use_defaults=False
|
|
67
65
|
)
|
|
66
|
+
assert isinstance(data, dict)
|
|
67
|
+
return self.klass(**data)
|
reconcile/utils/metrics.py
CHANGED
|
@@ -144,7 +144,7 @@ class GaugeMetric(BaseMetric):
|
|
|
144
144
|
|
|
145
145
|
@classmethod
|
|
146
146
|
def metric_family(cls) -> GaugeMetricFamily:
|
|
147
|
-
labels = [f.alias for f in cls.
|
|
147
|
+
labels = [f.alias or name for name, f in cls.model_fields.items()]
|
|
148
148
|
return GaugeMetricFamily(cls.name(), cls.__doc__ or "", labels=labels)
|
|
149
149
|
|
|
150
150
|
@classmethod
|
|
@@ -167,7 +167,7 @@ class CounterMetric(BaseMetric):
|
|
|
167
167
|
|
|
168
168
|
@classmethod
|
|
169
169
|
def metric_family(cls) -> CounterMetricFamily:
|
|
170
|
-
labels = [f.alias for f in cls.
|
|
170
|
+
labels = [f.alias or name for name, f in cls.model_fields.items()]
|
|
171
171
|
return CounterMetricFamily(cls.name(), cls.__doc__ or "", labels=labels)
|
|
172
172
|
|
|
173
173
|
@classmethod
|
|
@@ -198,7 +198,7 @@ class MetricsContainer:
|
|
|
198
198
|
"""
|
|
199
199
|
Sets the value of the given gauge metric to the given value.
|
|
200
200
|
"""
|
|
201
|
-
label_values = tuple(metric.
|
|
201
|
+
label_values = tuple(metric.model_dump(by_alias=True).values())
|
|
202
202
|
self._gauges[metric.__class__][label_values] = value
|
|
203
203
|
|
|
204
204
|
def set_info(self, metric: InfoMetric) -> None:
|
|
@@ -213,7 +213,7 @@ class MetricsContainer:
|
|
|
213
213
|
Increases the value of the given counter by the given amount.
|
|
214
214
|
"""
|
|
215
215
|
# all label values need to be strings, so lets convert them
|
|
216
|
-
label_values = tuple(str(v) for v in counter.
|
|
216
|
+
label_values = tuple(str(v) for v in counter.model_dump(by_alias=True).values())
|
|
217
217
|
current_value = self._counters[counter.__class__].get(label_values) or 0
|
|
218
218
|
self._counters[counter.__class__][label_values] = current_value + by
|
|
219
219
|
|
|
@@ -270,7 +270,7 @@ class MetricsContainer:
|
|
|
270
270
|
(
|
|
271
271
|
metric_class(**{
|
|
272
272
|
key: labels[i]
|
|
273
|
-
for i, key in enumerate(metric_class.
|
|
273
|
+
for i, key in enumerate(metric_class.model_fields.keys())
|
|
274
274
|
}),
|
|
275
275
|
value,
|
|
276
276
|
)
|