qontract-reconcile 0.10.2.dev334__py3-none-any.whl → 0.10.2.dev439__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.
Potentially problematic release.
This version of qontract-reconcile might be problematic. Click here for more details.
- {qontract_reconcile-0.10.2.dev334.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/METADATA +13 -12
- {qontract_reconcile-0.10.2.dev334.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/RECORD +366 -361
- reconcile/acs_rbac.py +2 -2
- reconcile/aus/advanced_upgrade_service.py +18 -12
- reconcile/aus/base.py +134 -32
- reconcile/aus/cluster_version_data.py +15 -5
- reconcile/aus/models.py +3 -1
- reconcile/aus/ocm_addons_upgrade_scheduler_org.py +1 -0
- reconcile/aus/ocm_upgrade_scheduler.py +8 -1
- reconcile/aus/ocm_upgrade_scheduler_org.py +20 -5
- reconcile/aus/version_gates/sts_version_gate_handler.py +54 -1
- reconcile/automated_actions/config/integration.py +16 -4
- reconcile/aws_account_manager/integration.py +8 -8
- reconcile/aws_account_manager/reconciler.py +3 -3
- reconcile/aws_ami_cleanup/integration.py +8 -12
- reconcile/aws_ami_share.py +69 -62
- reconcile/aws_cloudwatch_log_retention/integration.py +155 -126
- reconcile/aws_ecr_image_pull_secrets.py +3 -3
- reconcile/aws_iam_keys.py +1 -0
- reconcile/aws_saml_idp/integration.py +12 -4
- reconcile/aws_saml_roles/integration.py +32 -25
- 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/change_owners/diff.py +2 -4
- reconcile/checkpoint.py +11 -3
- reconcile/cli.py +111 -18
- reconcile/dashdotdb_dora.py +5 -12
- reconcile/dashdotdb_slo.py +1 -1
- reconcile/database_access_manager.py +123 -117
- 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 +9 -11
- reconcile/external_resources/factories.py +5 -12
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +8 -5
- reconcile/external_resources/meta.py +0 -1
- reconcile/external_resources/metrics.py +1 -1
- reconcile/external_resources/model.py +20 -20
- reconcile/external_resources/reconciler.py +7 -4
- reconcile/external_resources/secrets_sync.py +8 -11
- reconcile/external_resources/state.py +26 -16
- reconcile/fleet_labeler/integration.py +1 -1
- reconcile/gabi_authorized_users.py +8 -5
- reconcile/gcp_image_mirror.py +2 -2
- reconcile/github_org.py +1 -1
- reconcile/github_owners.py +4 -0
- reconcile/gitlab_housekeeping.py +13 -15
- reconcile/gitlab_members.py +6 -12
- reconcile/gitlab_mr_sqs_consumer.py +2 -2
- reconcile/gitlab_owners.py +15 -11
- reconcile/gitlab_permissions.py +8 -12
- reconcile/glitchtip_project_alerts/integration.py +3 -1
- reconcile/gql_definitions/acs/acs_instances.py +10 -10
- reconcile/gql_definitions/acs/acs_policies.py +5 -5
- reconcile/gql_definitions/acs/acs_rbac.py +6 -6
- reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +32 -32
- reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +26 -26
- reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +6 -7
- 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 +51 -12
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +11 -11
- reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +20 -10
- reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +28 -68
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +20 -10
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +20 -10
- reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
- reconcile/gql_definitions/aws_version_sync/clusters.py +10 -10
- 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 +9 -9
- reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +18 -18
- reconcile/gql_definitions/common/alerting_services_settings.py +9 -9
- 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 +120 -0
- reconcile/gql_definitions/common/app_interface_state_settings.py +10 -10
- 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 +22 -9
- reconcile/gql_definitions/common/aws_vpcs.py +11 -11
- reconcile/gql_definitions/common/clusters.py +37 -35
- reconcile/gql_definitions/common/clusters_minimal.py +14 -14
- reconcile/gql_definitions/common/clusters_with_dms.py +6 -6
- reconcile/gql_definitions/common/clusters_with_peering.py +29 -30
- reconcile/gql_definitions/common/github_orgs.py +10 -10
- reconcile/gql_definitions/common/jira_settings.py +10 -10
- reconcile/gql_definitions/common/jiralert_settings.py +5 -5
- reconcile/gql_definitions/common/ldap_settings.py +5 -5
- reconcile/gql_definitions/common/namespaces.py +42 -44
- reconcile/gql_definitions/common/namespaces_minimal.py +15 -13
- reconcile/gql_definitions/common/ocm_env_telemeter.py +12 -12
- reconcile/gql_definitions/common/ocm_environments.py +19 -19
- reconcile/gql_definitions/common/pagerduty_instances.py +9 -9
- reconcile/gql_definitions/common/pgp_reencryption_settings.py +6 -6
- reconcile/gql_definitions/common/pipeline_providers.py +29 -29
- 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 +44 -44
- reconcile/gql_definitions/common/saas_target_namespaces.py +10 -10
- 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 +19 -19
- reconcile/gql_definitions/common/state_aws_account.py +7 -8
- 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 +9 -9
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +43 -43
- reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +10 -10
- 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 +8 -8
- reconcile/gql_definitions/email_sender/users.py +6 -6
- reconcile/gql_definitions/endpoints_discovery/apps.py +10 -10
- reconcile/gql_definitions/external_resources/aws_accounts.py +9 -9
- reconcile/gql_definitions/external_resources/external_resources_modules.py +23 -23
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py +494 -410
- reconcile/gql_definitions/external_resources/external_resources_settings.py +28 -26
- reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
- reconcile/gql_definitions/fleet_labeler/fleet_labels.py +40 -40
- reconcile/gql_definitions/fragments/aus_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_common.py +7 -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_vpc_request_subnet.py → aws_organization.py} +12 -8
- reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc_request.py +12 -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 +9 -9
- reconcile/gql_definitions/gcp/gcp_projects.py +9 -9
- reconcile/gql_definitions/gitlab_members/gitlab_instances.py +9 -9
- reconcile/gql_definitions/gitlab_members/permissions.py +9 -9
- reconcile/gql_definitions/glitchtip/glitchtip_instance.py +9 -9
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +11 -11
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +9 -9
- reconcile/gql_definitions/integrations/integrations.py +48 -51
- reconcile/gql_definitions/introspection.json +3207 -1683
- reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +11 -11
- reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +10 -10
- reconcile/gql_definitions/jira/jira_servers.py +5 -5
- reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +14 -10
- reconcile/gql_definitions/jumphosts/jumphosts.py +13 -13
- reconcile/gql_definitions/ldap_groups/roles.py +5 -5
- reconcile/gql_definitions/ldap_groups/settings.py +9 -9
- reconcile/gql_definitions/maintenance/maintenances.py +5 -5
- reconcile/gql_definitions/membershipsources/roles.py +5 -5
- reconcile/gql_definitions/ocm_labels/clusters.py +18 -19
- reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
- reconcile/gql_definitions/openshift_cluster_bots/clusters.py +22 -22
- reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_roles.py +6 -6
- reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +10 -10
- reconcile/gql_definitions/quay_membership/quay_membership.py +6 -6
- reconcile/gql_definitions/rhcs/certs.py +33 -87
- reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +43 -0
- reconcile/gql_definitions/rhidp/organizations.py +18 -18
- reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
- reconcile/gql_definitions/service_dependencies/service_dependencies.py +8 -8
- reconcile/gql_definitions/sharding/aws_accounts.py +10 -10
- reconcile/gql_definitions/sharding/ocm_organization.py +8 -8
- reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
- reconcile/gql_definitions/skupper_network/skupper_networks.py +10 -10
- reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
- reconcile/gql_definitions/slack_usergroups/permissions.py +9 -9
- 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 +6 -7
- reconcile/gql_definitions/statuspage/statuspages.py +9 -9
- 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 +6 -6
- reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +11 -11
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +11 -11
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +20 -25
- reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +6 -6
- reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +12 -12
- reconcile/gql_definitions/terraform_init/aws_accounts.py +23 -9
- reconcile/gql_definitions/terraform_repo/terraform_repo.py +9 -9
- reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +440 -407
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +23 -17
- reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +9 -9
- reconcile/gql_definitions/vault_instances/vault_instances.py +61 -61
- reconcile/gql_definitions/vault_policies/vault_policies.py +11 -11
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +8 -8
- 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 +10 -8
- reconcile/jira_permissions_validator.py +237 -122
- reconcile/ldap_groups/integration.py +1 -1
- reconcile/ocm/types.py +35 -56
- 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 +33 -27
- reconcile/openshift_base.py +113 -5
- reconcile/openshift_cluster_bots.py +3 -2
- 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 +74 -37
- reconcile/openshift_rolebindings.py +230 -130
- reconcile/openshift_saas_deploy.py +6 -7
- reconcile/openshift_saas_deploy_change_tester.py +9 -7
- reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
- reconcile/openshift_serviceaccount_tokens.py +2 -2
- reconcile/openshift_upgrade_watcher.py +4 -4
- reconcile/openshift_users.py +5 -3
- 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 +131 -0
- reconcile/rhidp/common.py +3 -5
- reconcile/rhidp/sso_client/base.py +16 -5
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
- reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
- reconcile/skupper_network/integration.py +2 -2
- reconcile/slack_usergroups.py +35 -14
- reconcile/sql_query.py +1 -0
- reconcile/status_board.py +6 -6
- reconcile/statuspage/atlassian.py +7 -7
- reconcile/statuspage/integrations/maintenances.py +4 -3
- reconcile/statuspage/page.py +4 -9
- reconcile/statuspage/status.py +5 -8
- reconcile/templates/rosa-classic-cluster-creation.sh.j2 +5 -1
- reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +4 -1
- reconcile/templating/lib/merge_request_manager.py +2 -2
- reconcile/templating/lib/rendering.py +3 -3
- reconcile/templating/renderer.py +12 -13
- reconcile/terraform_aws_route53.py +7 -1
- 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 +187 -23
- reconcile/terraform_repo.py +16 -12
- reconcile/terraform_resources.py +17 -7
- reconcile/terraform_tgw_attachments.py +27 -19
- reconcile/terraform_users.py +7 -0
- reconcile/terraform_vpc_peerings.py +14 -3
- reconcile/terraform_vpc_resources/integration.py +20 -8
- reconcile/typed_queries/app_interface_roles.py +10 -0
- reconcile/typed_queries/aws_account_tags.py +41 -0
- 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 +13 -13
- 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/aggregated_list.py +4 -3
- reconcile/utils/aws_api.py +51 -20
- reconcile/utils/aws_api_typed/api.py +38 -9
- reconcile/utils/aws_api_typed/cloudformation.py +149 -0
- reconcile/utils/aws_api_typed/logs.py +73 -0
- reconcile/utils/aws_api_typed/organization.py +4 -2
- reconcile/utils/binary.py +7 -12
- reconcile/utils/datetime_util.py +67 -0
- reconcile/utils/deadmanssnitch_api.py +1 -1
- reconcile/utils/differ.py +2 -3
- reconcile/utils/early_exit_cache.py +11 -12
- reconcile/utils/expiration.py +7 -3
- reconcile/utils/external_resource_spec.py +24 -1
- reconcile/utils/filtering.py +1 -1
- 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/helm.py +2 -1
- reconcile/utils/helpers.py +1 -1
- 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 +6 -8
- reconcile/utils/jira_client.py +82 -63
- reconcile/utils/jjb_client.py +28 -15
- reconcile/utils/jobcontroller/controller.py +2 -2
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/json.py +74 -0
- 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 +4 -4
- reconcile/utils/merge_request_manager/parser.py +6 -6
- reconcile/utils/metrics.py +5 -5
- reconcile/utils/models.py +304 -82
- reconcile/utils/mr/app_interface_reporter.py +2 -2
- reconcile/utils/mr/base.py +2 -2
- reconcile/utils/mr/notificator.py +3 -3
- reconcile/utils/mr/update_access_report_base.py +3 -4
- reconcile/utils/mr/user_maintenance.py +3 -2
- reconcile/utils/oc.py +249 -203
- reconcile/utils/oc_filters.py +3 -3
- reconcile/utils/ocm/addons.py +0 -1
- reconcile/utils/ocm/base.py +18 -21
- 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 +9 -3
- reconcile/utils/ocm/search_filters.py +3 -6
- reconcile/utils/ocm/service_log.py +4 -6
- reconcile/utils/ocm/sre_capability_labels.py +20 -13
- reconcile/utils/openshift_resource.py +10 -5
- reconcile/utils/output.py +3 -2
- reconcile/utils/pagerduty_api.py +10 -7
- reconcile/utils/promotion_state.py +6 -11
- reconcile/utils/raw_github_api.py +1 -1
- reconcile/utils/rhcsv2_certs.py +138 -35
- reconcile/utils/rosa/session.py +16 -0
- reconcile/utils/runtime/integration.py +2 -3
- reconcile/utils/runtime/runner.py +2 -2
- reconcile/utils/saasherder/interfaces.py +13 -20
- reconcile/utils/saasherder/models.py +25 -21
- reconcile/utils/saasherder/saasherder.py +55 -31
- reconcile/utils/slack_api.py +26 -4
- reconcile/utils/sloth.py +224 -0
- reconcile/utils/sqs_gateway.py +2 -1
- reconcile/utils/state.py +2 -1
- reconcile/utils/structs.py +1 -1
- reconcile/utils/terraform_client.py +5 -4
- reconcile/utils/terrascript_aws_client.py +192 -114
- reconcile/utils/unleash/server.py +2 -8
- reconcile/utils/vault.py +5 -12
- reconcile/utils/vcs.py +8 -8
- reconcile/vault_replication.py +107 -42
- tools/app_interface_reporter.py +4 -4
- 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 +1 -1
- tools/cli_commands/systems_and_tools.py +5 -1
- tools/qontract_cli.py +31 -18
- tools/template_validation.py +3 -1
- reconcile/gql_definitions/cna/__init__.py +0 -0
- reconcile/gql_definitions/cna/queries/__init__.py +0 -0
- reconcile/gql_definitions/ocm_oidc_idp/__init__.py +0 -0
- reconcile/gql_definitions/ocm_subscription_labels/__init__.py +0 -0
- {qontract_reconcile-0.10.2.dev334.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev334.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/entry_points.txt +0 -0
reconcile/utils/oc_filters.py
CHANGED
|
@@ -19,19 +19,19 @@ class Namespace(Protocol):
|
|
|
19
19
|
NS = TypeVar("NS", bound=Namespace)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
def filter_namespaces_by_cluster(
|
|
22
|
+
def filter_namespaces_by_cluster[NS: Namespace](
|
|
23
23
|
namespaces: Iterable[NS], cluster_names: Iterable[str]
|
|
24
24
|
) -> list[NS]:
|
|
25
25
|
return [n for n in namespaces if n.cluster.name in cluster_names]
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
def filter_namespaces_by_name(
|
|
28
|
+
def filter_namespaces_by_name[NS: Namespace](
|
|
29
29
|
namespaces: Iterable[NS], namespace_names: Iterable[str]
|
|
30
30
|
) -> list[NS]:
|
|
31
31
|
return [n for n in namespaces if n.name in namespace_names]
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
def filter_namespaces_by_cluster_and_namespace(
|
|
34
|
+
def filter_namespaces_by_cluster_and_namespace[NS: Namespace](
|
|
35
35
|
namespaces: Iterable[NS],
|
|
36
36
|
cluster_names: Iterable[str] | None,
|
|
37
37
|
namespace_names: Iterable[str] | None,
|
reconcile/utils/ocm/addons.py
CHANGED
reconcile/utils/ocm/base.py
CHANGED
|
@@ -141,16 +141,16 @@ class OCMClusterAWSOperatorRole(BaseModel):
|
|
|
141
141
|
|
|
142
142
|
|
|
143
143
|
class OCMAWSSTS(OCMClusterFlag):
|
|
144
|
-
role_arn: str | None
|
|
145
|
-
support_role_arn: str | None
|
|
146
|
-
oidc_endpoint_url: str | None
|
|
147
|
-
operator_iam_roles: list[OCMClusterAWSOperatorRole] | None
|
|
148
|
-
instance_iam_roles: dict[str, str] | None
|
|
149
|
-
operator_role_prefix: str | None
|
|
144
|
+
role_arn: str | None = None
|
|
145
|
+
support_role_arn: str | None = None
|
|
146
|
+
oidc_endpoint_url: str | None = None
|
|
147
|
+
operator_iam_roles: list[OCMClusterAWSOperatorRole] | None = None
|
|
148
|
+
instance_iam_roles: dict[str, str] | None = None
|
|
149
|
+
operator_role_prefix: str | None = None
|
|
150
150
|
|
|
151
151
|
|
|
152
152
|
class OCMClusterAWSSettings(BaseModel):
|
|
153
|
-
sts: OCMAWSSTS | None
|
|
153
|
+
sts: OCMAWSSTS | None = None
|
|
154
154
|
|
|
155
155
|
@property
|
|
156
156
|
def sts_enabled(self) -> bool:
|
|
@@ -264,21 +264,21 @@ class OCMCluster(BaseModel):
|
|
|
264
264
|
product: OCMModelLink
|
|
265
265
|
identity_providers: OCMCollectionLink
|
|
266
266
|
|
|
267
|
-
aws: OCMClusterAWSSettings | None
|
|
267
|
+
aws: OCMClusterAWSSettings | None = None
|
|
268
268
|
|
|
269
269
|
version: OCMClusterVersion
|
|
270
270
|
|
|
271
271
|
hypershift: OCMClusterFlag
|
|
272
272
|
|
|
273
|
-
console: OCMClusterConsole | None
|
|
273
|
+
console: OCMClusterConsole | None = None
|
|
274
274
|
|
|
275
|
-
api: OCMClusterAPI | None
|
|
275
|
+
api: OCMClusterAPI | None = None
|
|
276
276
|
|
|
277
|
-
dns: OCMClusterDns | None
|
|
277
|
+
dns: OCMClusterDns | None = None
|
|
278
278
|
|
|
279
|
-
external_configuration: OCMExternalConfiguration | None
|
|
279
|
+
external_configuration: OCMExternalConfiguration | None = None
|
|
280
280
|
|
|
281
|
-
external_auth_config: OCMExternalAuthConfig | None
|
|
281
|
+
external_auth_config: OCMExternalAuthConfig | None = None
|
|
282
282
|
|
|
283
283
|
def minor_version(self) -> str:
|
|
284
284
|
version_info = parse_semver(self.version.raw_id)
|
|
@@ -570,15 +570,12 @@ class OCMOIdentityProviderGithub(OCMOIdentityProvider):
|
|
|
570
570
|
)
|
|
571
571
|
|
|
572
572
|
|
|
573
|
-
class OCMOIdentityProviderOidcOpenIdClaims(BaseModel):
|
|
573
|
+
class OCMOIdentityProviderOidcOpenIdClaims(BaseModel, frozen=True):
|
|
574
574
|
email: list[str]
|
|
575
|
-
name: list[str]
|
|
575
|
+
name: list[str] = []
|
|
576
576
|
preferred_username: list[str]
|
|
577
577
|
groups: list[str] = []
|
|
578
578
|
|
|
579
|
-
class Config:
|
|
580
|
-
frozen = True
|
|
581
|
-
|
|
582
579
|
|
|
583
580
|
class OCMOIdentityProviderOidcOpenId(BaseModel):
|
|
584
581
|
client_id: str
|
|
@@ -618,11 +615,11 @@ class OCMAddonUpgradePolicy(BaseModel):
|
|
|
618
615
|
id: str
|
|
619
616
|
addon_id: str
|
|
620
617
|
cluster_id: str
|
|
621
|
-
next_run: str | None
|
|
622
|
-
schedule: str | None
|
|
618
|
+
next_run: str | None = None
|
|
619
|
+
schedule: str | None = None
|
|
623
620
|
schedule_type: str
|
|
624
621
|
version: str
|
|
625
|
-
state: str | None
|
|
622
|
+
state: str | None = None
|
|
626
623
|
|
|
627
624
|
|
|
628
625
|
def build_label_container(
|
|
@@ -42,7 +42,7 @@ def add_identity_provider(
|
|
|
42
42
|
)
|
|
43
43
|
ocm_api.post(
|
|
44
44
|
api_path=ocm_cluster.identity_providers.href,
|
|
45
|
-
data=idp.
|
|
45
|
+
data=idp.model_dump(by_alias=True, exclude_none=True),
|
|
46
46
|
)
|
|
47
47
|
|
|
48
48
|
|
|
@@ -55,7 +55,7 @@ def update_identity_provider(
|
|
|
55
55
|
raise ValueError(f"IDP {idp.name} does not have a href!")
|
|
56
56
|
ocm_api.patch(
|
|
57
57
|
api_path=idp.href,
|
|
58
|
-
data=idp.
|
|
58
|
+
data=idp.model_dump(by_alias=True, exclude_none=True, exclude={"name"}),
|
|
59
59
|
)
|
|
60
60
|
|
|
61
61
|
|
reconcile/utils/ocm/labels.py
CHANGED
|
@@ -159,7 +159,7 @@ def build_container_for_prefix(
|
|
|
159
159
|
|
|
160
160
|
return LabelContainer(
|
|
161
161
|
labels={
|
|
162
|
-
strip_prefix_if_needed(label.key): label.
|
|
162
|
+
strip_prefix_if_needed(label.key): label.model_copy(
|
|
163
163
|
update={"key": strip_prefix_if_needed(label.key)}
|
|
164
164
|
)
|
|
165
165
|
for label in container.labels.values()
|
reconcile/utils/ocm/products.py
CHANGED
|
@@ -47,6 +47,7 @@ SPEC_ATTR_MULTI_AZ = "multi_az"
|
|
|
47
47
|
SPEC_ATTR_HYPERSHIFT = "hypershift"
|
|
48
48
|
SPEC_ATTR_SUBNET_IDS = "subnet_ids"
|
|
49
49
|
SPEC_ATTR_AVAILABILITY_ZONES = "availability_zones"
|
|
50
|
+
SPEC_ATTR_FIPS = "fips"
|
|
50
51
|
|
|
51
52
|
SPEC_ATTR_NETWORK = "network"
|
|
52
53
|
IGNORE_NETWORK_TYPE_ATTR = "type"
|
|
@@ -177,10 +178,11 @@ class OCMProductOsd(OCMProduct):
|
|
|
177
178
|
],
|
|
178
179
|
provision_shard_id=provision_shard_id,
|
|
179
180
|
hypershift=cluster["hypershift"]["enabled"],
|
|
181
|
+
fips=cluster.get("fips") or False,
|
|
180
182
|
)
|
|
181
183
|
|
|
182
184
|
if not cluster["ccs"]["enabled"]:
|
|
183
|
-
cluster_spec_data = spec.
|
|
185
|
+
cluster_spec_data = spec.model_dump()
|
|
184
186
|
cluster_spec_data["storage"] = (
|
|
185
187
|
cluster["storage_quota"]["value"] // BYTES_IN_GIGABYTE
|
|
186
188
|
)
|
|
@@ -227,7 +229,7 @@ class OCMProductOsd(OCMProduct):
|
|
|
227
229
|
"compute_machine_type": {"id": default_machine_pool.instance_type},
|
|
228
230
|
}
|
|
229
231
|
if default_machine_pool.autoscale is not None:
|
|
230
|
-
spec["autoscale_compute"] = default_machine_pool.autoscale.
|
|
232
|
+
spec["autoscale_compute"] = default_machine_pool.autoscale.model_dump()
|
|
231
233
|
else:
|
|
232
234
|
spec["compute"] = default_machine_pool.replicas
|
|
233
235
|
return spec
|
|
@@ -257,6 +259,7 @@ class OCMProductOsd(OCMProduct):
|
|
|
257
259
|
if (duwm := cluster.spec.disable_user_workload_monitoring) is not None
|
|
258
260
|
else True
|
|
259
261
|
),
|
|
262
|
+
"fips": cluster.spec.fips,
|
|
260
263
|
}
|
|
261
264
|
|
|
262
265
|
# Workaround to enable type checks.
|
|
@@ -426,6 +429,7 @@ class OCMProductRosa(OCMProduct):
|
|
|
426
429
|
subnet_ids=cluster["aws"].get("subnet_ids"),
|
|
427
430
|
availability_zones=cluster["nodes"].get("availability_zones"),
|
|
428
431
|
oidc_endpoint_url=oidc_endpoint_url,
|
|
432
|
+
fips=cluster.get("fips") or False,
|
|
429
433
|
)
|
|
430
434
|
|
|
431
435
|
machine_pools = [
|
|
@@ -470,7 +474,7 @@ class OCMProductRosa(OCMProduct):
|
|
|
470
474
|
"compute_machine_type": {"id": default_machine_pool.instance_type},
|
|
471
475
|
}
|
|
472
476
|
if default_machine_pool.autoscale is not None:
|
|
473
|
-
spec["autoscale_compute"] = default_machine_pool.autoscale.
|
|
477
|
+
spec["autoscale_compute"] = default_machine_pool.autoscale.model_dump()
|
|
474
478
|
else:
|
|
475
479
|
spec["compute"] = default_machine_pool.replicas
|
|
476
480
|
return spec
|
|
@@ -513,6 +517,7 @@ class OCMProductRosa(OCMProduct):
|
|
|
513
517
|
if (duwm := cluster.spec.disable_user_workload_monitoring) is not None
|
|
514
518
|
else True
|
|
515
519
|
),
|
|
520
|
+
"fips": cluster.spec.fips,
|
|
516
521
|
}
|
|
517
522
|
|
|
518
523
|
provision_shard_id = cluster.spec.provision_shard_id
|
|
@@ -701,6 +706,7 @@ class OCMProductHypershift(OCMProduct):
|
|
|
701
706
|
availability_zones=cluster["nodes"].get("availability_zones"),
|
|
702
707
|
hypershift=cluster["hypershift"]["enabled"],
|
|
703
708
|
oidc_endpoint_url=oidc_endpoint_url,
|
|
709
|
+
fips=cluster.get("fips") or False,
|
|
704
710
|
)
|
|
705
711
|
|
|
706
712
|
network = OCMClusterNetwork(
|
|
@@ -5,7 +5,6 @@ from abc import (
|
|
|
5
5
|
from collections.abc import Iterable
|
|
6
6
|
from dataclasses import dataclass
|
|
7
7
|
from datetime import (
|
|
8
|
-
UTC,
|
|
9
8
|
datetime,
|
|
10
9
|
)
|
|
11
10
|
from enum import Enum
|
|
@@ -16,6 +15,8 @@ from typing import (
|
|
|
16
15
|
|
|
17
16
|
import dateparser
|
|
18
17
|
|
|
18
|
+
from reconcile.utils.datetime_util import utc_now
|
|
19
|
+
|
|
19
20
|
|
|
20
21
|
@dataclass
|
|
21
22
|
class FilterCondition:
|
|
@@ -166,17 +167,13 @@ class DateRangeCondition(FilterCondition):
|
|
|
166
167
|
return date
|
|
167
168
|
parsed = dateparser.parse(
|
|
168
169
|
date,
|
|
169
|
-
settings={"RELATIVE_BASE":
|
|
170
|
+
settings={"RELATIVE_BASE": utc_now()},
|
|
170
171
|
)
|
|
171
172
|
if parsed is None:
|
|
172
173
|
raise InvalidFilterError(f"Invalid relative date: {date}")
|
|
173
174
|
|
|
174
175
|
return parsed
|
|
175
176
|
|
|
176
|
-
@staticmethod
|
|
177
|
-
def now() -> datetime:
|
|
178
|
-
return datetime.now(tz=UTC)
|
|
179
|
-
|
|
180
177
|
|
|
181
178
|
class InvalidFilterError(Exception):
|
|
182
179
|
pass
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
from collections.abc import Generator
|
|
2
|
-
from datetime import
|
|
3
|
-
datetime,
|
|
4
|
-
timedelta,
|
|
5
|
-
)
|
|
2
|
+
from datetime import timedelta
|
|
6
3
|
|
|
4
|
+
from reconcile.utils.datetime_util import utc_now
|
|
7
5
|
from reconcile.utils.ocm.base import (
|
|
8
6
|
OCMClusterServiceLog,
|
|
9
7
|
OCMClusterServiceLogCreateModel,
|
|
@@ -47,7 +45,7 @@ def create_service_log(
|
|
|
47
45
|
.eq("severity", service_log.severity.value)
|
|
48
46
|
.eq("summary", service_log.summary)
|
|
49
47
|
.eq("description", service_log.description)
|
|
50
|
-
.after("created_at",
|
|
48
|
+
.after("created_at", utc_now() - dedup_interval),
|
|
51
49
|
),
|
|
52
50
|
None,
|
|
53
51
|
)
|
|
@@ -57,6 +55,6 @@ def create_service_log(
|
|
|
57
55
|
return OCMClusterServiceLog(
|
|
58
56
|
**ocm_api.post(
|
|
59
57
|
api_path=CLUSTER_SERVICE_LOGS_CREATE_ENDPOINT,
|
|
60
|
-
data=service_log.
|
|
58
|
+
data=service_log.model_dump(by_alias=True),
|
|
61
59
|
)
|
|
62
60
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
|
|
3
|
-
from pydantic import
|
|
4
|
-
from pydantic.fields import
|
|
3
|
+
from pydantic import WithJsonSchema
|
|
4
|
+
from pydantic.fields import FieldInfo
|
|
5
5
|
|
|
6
6
|
from reconcile.utils.ocm.base import (
|
|
7
7
|
LabelContainer,
|
|
@@ -22,11 +22,11 @@ def sre_capability_label_key(
|
|
|
22
22
|
return f"sre-capabilities.{sre_capability}.{config_atom}"
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
def labelset_groupfield(group_prefix: str) ->
|
|
25
|
+
def labelset_groupfield(group_prefix: str) -> WithJsonSchema:
|
|
26
26
|
"""
|
|
27
27
|
Helper function to build the FieldMeta for a labelset field that groups labels.
|
|
28
28
|
"""
|
|
29
|
-
return
|
|
29
|
+
return WithJsonSchema({"group_by_prefix": group_prefix})
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def build_labelset(
|
|
@@ -36,16 +36,23 @@ def build_labelset(
|
|
|
36
36
|
Instantiates a dataclass from a set of labels.
|
|
37
37
|
"""
|
|
38
38
|
raw_data = {
|
|
39
|
-
field.alias: _labelset_field_value(labels, field)
|
|
40
|
-
for field in dataclass.
|
|
39
|
+
field.alias or name: _labelset_field_value(labels, name, field)
|
|
40
|
+
for name, field in dataclass.model_fields.items()
|
|
41
41
|
}
|
|
42
42
|
return dataclass(**raw_data)
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
def _labelset_field_value(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
def _labelset_field_value(
|
|
46
|
+
labels: LabelContainer, name: str, field: FieldInfo
|
|
47
|
+
) -> Any | None:
|
|
48
|
+
schema = next((m for m in field.metadata if isinstance(m, WithJsonSchema)), None)
|
|
49
|
+
if (
|
|
50
|
+
schema is None
|
|
51
|
+
or not schema.json_schema
|
|
52
|
+
or "group_by_prefix" not in schema.json_schema
|
|
53
|
+
):
|
|
54
|
+
return labels.get_label_value(field.alias or name)
|
|
55
|
+
|
|
56
|
+
return build_container_for_prefix(
|
|
57
|
+
labels, schema.json_schema["group_by_prefix"], strip_key_prefix=True
|
|
58
|
+
).get_values_dict()
|
|
@@ -4,9 +4,8 @@ from __future__ import annotations
|
|
|
4
4
|
import base64
|
|
5
5
|
import contextlib
|
|
6
6
|
import copy
|
|
7
|
-
import datetime
|
|
8
7
|
import hashlib
|
|
9
|
-
import
|
|
8
|
+
import logging
|
|
10
9
|
import re
|
|
11
10
|
from threading import Lock
|
|
12
11
|
from typing import TYPE_CHECKING, Any
|
|
@@ -15,6 +14,8 @@ import semver
|
|
|
15
14
|
from pydantic import BaseModel
|
|
16
15
|
|
|
17
16
|
from reconcile.external_resources.meta import SECRET_UPDATED_AT
|
|
17
|
+
from reconcile.utils.datetime_util import to_utc_seconds_iso_format, utc_now
|
|
18
|
+
from reconcile.utils.json import json_dumps
|
|
18
19
|
from reconcile.utils.metrics import GaugeMetric
|
|
19
20
|
|
|
20
21
|
if TYPE_CHECKING:
|
|
@@ -368,8 +369,8 @@ class OpenshiftResource:
|
|
|
368
369
|
annotations[QONTRACT_ANNOTATION_INTEGRATION] = self.integration
|
|
369
370
|
annotations[QONTRACT_ANNOTATION_INTEGRATION_VERSION] = self.integration_version
|
|
370
371
|
annotations[QONTRACT_ANNOTATION_SHA256SUM] = sha256sum
|
|
371
|
-
now =
|
|
372
|
-
annotations[QONTRACT_ANNOTATION_UPDATE] = now
|
|
372
|
+
now = utc_now()
|
|
373
|
+
annotations[QONTRACT_ANNOTATION_UPDATE] = to_utc_seconds_iso_format(now)
|
|
373
374
|
if self.caller_name:
|
|
374
375
|
annotations[QONTRACT_ANNOTATION_CALLER_NAME] = self.caller_name
|
|
375
376
|
|
|
@@ -530,7 +531,7 @@ class OpenshiftResource:
|
|
|
530
531
|
|
|
531
532
|
@staticmethod
|
|
532
533
|
def serialize(body: dict[str, Any]) -> str:
|
|
533
|
-
return
|
|
534
|
+
return json_dumps(body)
|
|
534
535
|
|
|
535
536
|
@staticmethod
|
|
536
537
|
def calculate_sha256sum(body: str) -> str:
|
|
@@ -601,6 +602,10 @@ class ResourceInventory:
|
|
|
601
602
|
resource: OpenshiftResource,
|
|
602
603
|
privileged: bool = False,
|
|
603
604
|
) -> None:
|
|
605
|
+
if cluster not in self._clusters:
|
|
606
|
+
logging.error(f"Cluster {cluster} not initialized in ResourceInventory")
|
|
607
|
+
return
|
|
608
|
+
|
|
604
609
|
if resource.kind_and_group in self._clusters[cluster][namespace]:
|
|
605
610
|
kind = resource.kind_and_group
|
|
606
611
|
else:
|
reconcile/utils/output.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import json
|
|
2
1
|
import re
|
|
3
2
|
from collections.abc import Iterable, Mapping
|
|
4
3
|
|
|
5
4
|
import yaml
|
|
6
5
|
from tabulate import tabulate
|
|
7
6
|
|
|
7
|
+
from reconcile.utils.json import json_dumps
|
|
8
|
+
|
|
8
9
|
|
|
9
10
|
def print_output(
|
|
10
11
|
options: Mapping[str, str | bool],
|
|
@@ -30,7 +31,7 @@ def print_output(
|
|
|
30
31
|
)
|
|
31
32
|
print(formatted_content)
|
|
32
33
|
elif output == "json":
|
|
33
|
-
formatted_content =
|
|
34
|
+
formatted_content = json_dumps(content)
|
|
34
35
|
print(formatted_content)
|
|
35
36
|
elif output == "yaml":
|
|
36
37
|
formatted_content = yaml.dump(content)
|
reconcile/utils/pagerduty_api.py
CHANGED
|
@@ -3,8 +3,7 @@ from collections.abc import (
|
|
|
3
3
|
Callable,
|
|
4
4
|
Iterable,
|
|
5
5
|
)
|
|
6
|
-
from datetime import datetime
|
|
7
|
-
from datetime import timedelta
|
|
6
|
+
from datetime import datetime, timedelta
|
|
8
7
|
from typing import (
|
|
9
8
|
Protocol,
|
|
10
9
|
)
|
|
@@ -14,6 +13,7 @@ import requests
|
|
|
14
13
|
from pydantic import BaseModel
|
|
15
14
|
from sretoolbox.utils import retry
|
|
16
15
|
|
|
16
|
+
from reconcile.utils.datetime_util import utc_now
|
|
17
17
|
from reconcile.utils.secret_reader import (
|
|
18
18
|
HasSecret,
|
|
19
19
|
SecretReader,
|
|
@@ -52,10 +52,13 @@ class PagerDutyTarget(Protocol):
|
|
|
52
52
|
which must be implemented by a class to be compatible."""
|
|
53
53
|
|
|
54
54
|
name: str
|
|
55
|
-
instance: PagerDutyInstance
|
|
56
55
|
escalation_policy_id: str | None
|
|
57
56
|
schedule_id: str | None
|
|
58
57
|
|
|
58
|
+
@property
|
|
59
|
+
def instance(self) -> PagerDutyInstance:
|
|
60
|
+
pass
|
|
61
|
+
|
|
59
62
|
|
|
60
63
|
class PagerDutyConfig(BaseModel):
|
|
61
64
|
"""PagerDuty Config."""
|
|
@@ -80,7 +83,7 @@ class PagerDutyApi:
|
|
|
80
83
|
def get_pagerduty_users(
|
|
81
84
|
self, resource_type: str, resource_id: str
|
|
82
85
|
) -> list[pypd.User]:
|
|
83
|
-
now =
|
|
86
|
+
now = utc_now()
|
|
84
87
|
|
|
85
88
|
try:
|
|
86
89
|
if resource_type == "schedule":
|
|
@@ -103,7 +106,7 @@ class PagerDutyApi:
|
|
|
103
106
|
self.users.append(user)
|
|
104
107
|
return user.email.split("@")[0]
|
|
105
108
|
|
|
106
|
-
def get_schedule_users(self, schedule_id: str, now:
|
|
109
|
+
def get_schedule_users(self, schedule_id: str, now: datetime) -> list[pypd.User]:
|
|
107
110
|
until = now + timedelta(seconds=60)
|
|
108
111
|
s = pypd.Schedule.fetch(id=schedule_id, since=now, until=until, time_zone="UTC")
|
|
109
112
|
entries = s["final_schedule"]["rendered_schedule_entries"]
|
|
@@ -115,7 +118,7 @@ class PagerDutyApi:
|
|
|
115
118
|
]
|
|
116
119
|
|
|
117
120
|
def get_escalation_policy_users(
|
|
118
|
-
self, escalation_policy_id: str, now:
|
|
121
|
+
self, escalation_policy_id: str, now: datetime
|
|
119
122
|
) -> list[pypd.User]:
|
|
120
123
|
ep = pypd.EscalationPolicy.fetch(
|
|
121
124
|
id=escalation_policy_id, since=now, until=now, time_zone="UTC"
|
|
@@ -189,7 +192,7 @@ def get_pagerduty_name(user: PagerDutyUser) -> str:
|
|
|
189
192
|
return user.pagerduty_username or user.org_username
|
|
190
193
|
|
|
191
194
|
|
|
192
|
-
@retry(no_retry_exceptions=PagerDutyTargetError)
|
|
195
|
+
@retry(no_retry_exceptions=(PagerDutyTargetError,))
|
|
193
196
|
def get_usernames_from_pagerduty(
|
|
194
197
|
pagerduties: Iterable[PagerDutyTarget],
|
|
195
198
|
users: Iterable[PagerDutyUser],
|
|
@@ -3,13 +3,12 @@ from collections import defaultdict
|
|
|
3
3
|
|
|
4
4
|
from pydantic import (
|
|
5
5
|
BaseModel,
|
|
6
|
-
Extra,
|
|
7
6
|
)
|
|
8
7
|
|
|
9
8
|
from reconcile.utils.state import State
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
class PromotionData(BaseModel):
|
|
11
|
+
class PromotionData(BaseModel, extra="forbid"):
|
|
13
12
|
"""
|
|
14
13
|
A class that strictly corresponds to the json stored in S3.
|
|
15
14
|
|
|
@@ -20,17 +19,13 @@ class PromotionData(BaseModel):
|
|
|
20
19
|
|
|
21
20
|
# The success is primarily used for SAPM auto-promotions
|
|
22
21
|
success: bool
|
|
23
|
-
target_config_hash: str | None
|
|
24
|
-
saas_file: str | None
|
|
25
|
-
check_in: str | None
|
|
22
|
+
target_config_hash: str | None = None
|
|
23
|
+
saas_file: str | None = None
|
|
24
|
+
check_in: str | None = None
|
|
26
25
|
# Whether this promotion has ever succeeded
|
|
27
26
|
# Note, this shouldnt be overridden on subsequent promotions of same ref
|
|
28
27
|
# This attribute is primarily used by saasherder validations
|
|
29
|
-
has_succeeded_once: bool | None
|
|
30
|
-
|
|
31
|
-
class Config:
|
|
32
|
-
smart_union = True
|
|
33
|
-
extra = Extra.forbid
|
|
28
|
+
has_succeeded_once: bool | None = None
|
|
34
29
|
|
|
35
30
|
|
|
36
31
|
class PromotionState:
|
|
@@ -107,5 +102,5 @@ class PromotionState:
|
|
|
107
102
|
self, sha: str, channel: str, target_uid: str, data: PromotionData
|
|
108
103
|
) -> None:
|
|
109
104
|
state_key_v2 = f"promotions_v2/{channel}/{target_uid}/{sha}"
|
|
110
|
-
self._state.add(state_key_v2, data.
|
|
105
|
+
self._state.add(state_key_v2, data.model_dump(), force=True)
|
|
111
106
|
logging.info("Uploaded %s to %s", data, state_key_v2)
|
|
@@ -76,7 +76,7 @@ class RawGithubApi:
|
|
|
76
76
|
if login is not None
|
|
77
77
|
]
|
|
78
78
|
|
|
79
|
-
def team_invitations(self, org_id: str, team_id: str) -> list[str]:
|
|
79
|
+
def team_invitations(self, org_id: str | int, team_id: str | int) -> list[str]:
|
|
80
80
|
invitations = self.query(f"/organizations/{org_id}/team/{team_id}/invitations")
|
|
81
81
|
|
|
82
82
|
return [
|