qontract-reconcile 0.10.2.dev361__py3-none-any.whl → 0.10.2.dev474__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.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/METADATA +14 -13
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/RECORD +371 -364
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/WHEEL +1 -1
- reconcile/acs_rbac.py +2 -2
- reconcile/aus/advanced_upgrade_service.py +18 -12
- reconcile/aus/aus_sts_gate_handler.py +59 -0
- reconcile/aus/base.py +137 -34
- 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_gate_approver.py +1 -16
- reconcile/aus/version_gates/sts_version_gate_handler.py +5 -72
- reconcile/automated_actions/config/integration.py +16 -4
- reconcile/aws_account_manager/integration.py +21 -9
- reconcile/aws_account_manager/reconciler.py +3 -3
- reconcile/aws_account_manager/utils.py +1 -1
- 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 +1 -1
- reconcile/aws_iam_keys.py +1 -0
- reconcile/aws_saml_idp/integration.py +12 -4
- reconcile/aws_saml_roles/integration.py +30 -23
- reconcile/aws_version_sync/integration.py +6 -12
- reconcile/change_owners/README.md +1 -1
- reconcile/change_owners/bundle.py +3 -3
- reconcile/change_owners/change_log_tracking.py +3 -2
- reconcile/change_owners/change_owners.py +108 -42
- reconcile/change_owners/decision.py +1 -1
- reconcile/change_owners/diff.py +0 -2
- reconcile/checkpoint.py +11 -3
- reconcile/cli.py +94 -11
- 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 +8 -8
- reconcile/external_resources/factories.py +4 -6
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +8 -6
- reconcile/external_resources/meta.py +0 -1
- reconcile/external_resources/metrics.py +1 -1
- reconcile/external_resources/model.py +19 -15
- reconcile/external_resources/reconciler.py +7 -4
- reconcile/external_resources/secrets_sync.py +6 -10
- reconcile/external_resources/state.py +26 -16
- reconcile/fleet_labeler/integration.py +1 -1
- reconcile/gabi_authorized_users.py +5 -2
- 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_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 +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 +14 -5
- reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +15 -5
- reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +27 -66
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +15 -5
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +15 -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 +18 -5
- reconcile/gql_definitions/common/aws_vpcs.py +5 -5
- reconcile/gql_definitions/common/clusters.py +7 -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 +38 -7
- 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 +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_organization.py +33 -0
- 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 +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 +775 -136
- 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 +9 -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 +25 -79
- reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +43 -0
- 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 +19 -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 +37 -7
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +15 -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 +8 -5
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +6 -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 -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 +33 -27
- reconcile/openshift_base.py +113 -4
- reconcile/openshift_cluster_bots.py +1 -1
- reconcile/openshift_namespace_labels.py +1 -1
- reconcile/openshift_namespaces.py +96 -101
- reconcile/openshift_resources_base.py +6 -2
- reconcile/openshift_rhcs_certs.py +74 -37
- reconcile/openshift_rolebindings.py +7 -11
- reconcile/openshift_saas_deploy.py +4 -5
- 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/oum/labelset.py +5 -3
- reconcile/oum/models.py +1 -4
- reconcile/prometheus_rules_tester/integration.py +3 -3
- reconcile/quay_base.py +25 -6
- reconcile/quay_membership.py +55 -29
- reconcile/quay_mirror.py +1 -1
- reconcile/quay_mirror_org.py +6 -4
- reconcile/quay_permissions.py +81 -75
- reconcile/quay_repos.py +35 -37
- reconcile/queries.py +132 -1
- 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 +1 -1
- reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +1 -1
- reconcile/templating/lib/rendering.py +3 -3
- reconcile/templating/renderer.py +2 -2
- reconcile/templating/validator.py +4 -4
- 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 +6 -6
- 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/terraform_vpc_resources/merge_request.py +12 -2
- reconcile/terraform_vpc_resources/merge_request_manager.py +43 -19
- 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 +20 -15
- 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/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/environ.py +5 -0
- reconcile/utils/expiration.py +7 -3
- reconcile/utils/external_resource_spec.py +2 -0
- reconcile/utils/filtering.py +1 -1
- reconcile/utils/gitlab_api.py +19 -5
- reconcile/utils/glitchtip/client.py +6 -2
- reconcile/utils/glitchtip/models.py +25 -28
- reconcile/utils/gql.py +4 -7
- 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 -101
- reconcile/utils/jira_client.py +82 -63
- reconcile/utils/jjb_client.py +26 -13
- reconcile/utils/jobcontroller/controller.py +2 -2
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/json.py +43 -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 +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/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 +252 -201
- reconcile/utils/oc_filters.py +3 -3
- 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/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 +8 -3
- reconcile/utils/pagerduty_api.py +10 -7
- reconcile/utils/promotion_state.py +6 -11
- reconcile/utils/quay_api.py +74 -87
- reconcile/utils/raw_github_api.py +1 -1
- reconcile/utils/rhcsv2_certs.py +86 -23
- 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 +23 -20
- reconcile/utils/saasherder/saasherder.py +50 -27
- reconcile/utils/slack_api.py +2 -2
- reconcile/utils/sloth.py +171 -2
- reconcile/utils/structs.py +1 -1
- reconcile/utils/terraform_client.py +5 -4
- reconcile/utils/terrascript_aws_client.py +274 -124
- 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
- reconcile/vpc_peerings_validator.py +13 -0
- 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/qontract_cli.py +28 -17
- tools/template_validation.py +3 -1
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/entry_points.txt +0 -0
reconcile/acs_rbac.py
CHANGED
|
@@ -65,7 +65,7 @@ class AcsRole(BaseModel):
|
|
|
65
65
|
assignments: list[AssignmentPair]
|
|
66
66
|
permission_set_name: str
|
|
67
67
|
access_scope: AcsAccessScope
|
|
68
|
-
system_default: bool | None
|
|
68
|
+
system_default: bool | None = None
|
|
69
69
|
|
|
70
70
|
@classmethod
|
|
71
71
|
def build(cls, permission: Permission, usernames: list[str]) -> Self:
|
|
@@ -151,7 +151,7 @@ class AcsRbacIntegration(QontractReconcileIntegration[NoParams]):
|
|
|
151
151
|
for permission in role.oidc_permissions or []:
|
|
152
152
|
if isinstance(permission, OidcPermissionAcsV1):
|
|
153
153
|
permission_usernames[
|
|
154
|
-
Permission(**permission.
|
|
154
|
+
Permission(**permission.model_dump(by_alias=True))
|
|
155
155
|
].append(user.org_username)
|
|
156
156
|
return list(starmap(AcsRole.build, permission_usernames.items()))
|
|
157
157
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from collections import defaultdict
|
|
3
3
|
from datetime import timedelta
|
|
4
|
-
from typing import Optional
|
|
4
|
+
from typing import Annotated, Optional
|
|
5
5
|
|
|
6
6
|
from pydantic import (
|
|
7
7
|
BaseModel,
|
|
8
8
|
Field,
|
|
9
9
|
ValidationError,
|
|
10
|
-
|
|
10
|
+
field_validator,
|
|
11
11
|
)
|
|
12
12
|
from pydantic.dataclasses import dataclass
|
|
13
13
|
|
|
@@ -75,8 +75,10 @@ from reconcile.utils.ocm_base_client import (
|
|
|
75
75
|
OCMBaseClient,
|
|
76
76
|
init_ocm_base_client,
|
|
77
77
|
)
|
|
78
|
+
from reconcile.utils.semver_helper import make_semver
|
|
78
79
|
|
|
79
80
|
QONTRACT_INTEGRATION = "advanced-upgrade-scheduler"
|
|
81
|
+
QONTRACT_INTEGRATION_VERSION = make_semver(0, 1, 0)
|
|
80
82
|
|
|
81
83
|
|
|
82
84
|
class AdvancedUpgradeServiceIntegration(OCMClusterUpgradeSchedulerOrgIntegration):
|
|
@@ -289,13 +291,16 @@ class OrganizationLabelSet(BaseModel):
|
|
|
289
291
|
|
|
290
292
|
blocked_versions: CSV | None = Field(alias=aus_label_key("blocked-versions"))
|
|
291
293
|
|
|
292
|
-
sector_max_parallel_upgrades:
|
|
293
|
-
|
|
294
|
-
|
|
294
|
+
sector_max_parallel_upgrades: Annotated[
|
|
295
|
+
dict[str, str],
|
|
296
|
+
labelset_groupfield(
|
|
297
|
+
group_prefix=aus_label_key("sector-max-parallel-upgrades.")
|
|
298
|
+
),
|
|
299
|
+
]
|
|
295
300
|
|
|
296
|
-
sector_deps:
|
|
297
|
-
group_prefix=aus_label_key("sector-deps.")
|
|
298
|
-
|
|
301
|
+
sector_deps: Annotated[
|
|
302
|
+
dict[str, CSV], labelset_groupfield(group_prefix=aus_label_key("sector-deps."))
|
|
303
|
+
]
|
|
299
304
|
"""
|
|
300
305
|
Each sector with dependencies is represented as a `sector-deps.<sector-name>` label
|
|
301
306
|
with a CSV formatted list of dependant sectors. The custom `labelset_groupfield``
|
|
@@ -357,7 +362,7 @@ def _build_org_upgrade_spec(
|
|
|
357
362
|
]
|
|
358
363
|
|
|
359
364
|
org_labelset = build_labelset(org_labels, OrganizationLabelSet)
|
|
360
|
-
final_org = org.
|
|
365
|
+
final_org = org.model_copy(deep=True)
|
|
361
366
|
final_org.blocked_versions = org_labelset.blocked_versions # type: ignore
|
|
362
367
|
final_org.sectors = org_labelset.sector_dependencies()
|
|
363
368
|
final_org.inherit_version_data = inherit_version_data
|
|
@@ -375,6 +380,7 @@ def _build_org_upgrade_spec(
|
|
|
375
380
|
org=org_upgrade_spec.org,
|
|
376
381
|
upgradePolicy=upgrade_policy,
|
|
377
382
|
cluster=c.ocm_cluster,
|
|
383
|
+
cluster_labels=c.labels,
|
|
378
384
|
health=cluster_health,
|
|
379
385
|
nodePools=node_pool_specs_by_cluster_id.get(c.ocm_cluster.id) or [],
|
|
380
386
|
)
|
|
@@ -411,7 +417,7 @@ class ClusterUpgradePolicyLabelSet(BaseModel):
|
|
|
411
417
|
"""
|
|
412
418
|
|
|
413
419
|
soak_days: int = Field(alias=aus_label_key("soak-days"), ge=0)
|
|
414
|
-
workloads: CSV = Field(alias=aus_label_key("workloads"),
|
|
420
|
+
workloads: CSV = Field(alias=aus_label_key("workloads"), min_length=1)
|
|
415
421
|
schedule: str = Field(alias=aus_label_key("schedule"))
|
|
416
422
|
mutexes: CSV | None = Field(alias=aus_label_key("mutexes"))
|
|
417
423
|
sector: str | None = Field(alias=aus_label_key("sector"))
|
|
@@ -419,14 +425,14 @@ class ClusterUpgradePolicyLabelSet(BaseModel):
|
|
|
419
425
|
version_gate_approvals: CSV | None = Field(
|
|
420
426
|
alias=aus_label_key("version-gate-approvals")
|
|
421
427
|
)
|
|
422
|
-
_schedule_validator =
|
|
428
|
+
_schedule_validator = field_validator("schedule")(cron_validator)
|
|
423
429
|
|
|
424
430
|
def build_labels_dict(self) -> dict[str, str]:
|
|
425
431
|
"""
|
|
426
432
|
Build a dictionary of all labels in this labelset.
|
|
427
433
|
"""
|
|
428
434
|
labels = {}
|
|
429
|
-
for k, v in self.
|
|
435
|
+
for k, v in self.model_dump(by_alias=True).items():
|
|
430
436
|
if v is None:
|
|
431
437
|
continue
|
|
432
438
|
if isinstance(v, list):
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from reconcile.utils.jobcontroller.controller import K8sJobController
|
|
4
|
+
from reconcile.utils.ocm.base import OCMCluster
|
|
5
|
+
from reconcile.utils.ocm_base_client import OCMBaseClient
|
|
6
|
+
from reconcile.utils.rosa.rosa_cli import RosaCliError
|
|
7
|
+
from reconcile.utils.rosa.session import RosaSession
|
|
8
|
+
from reconcile.utils.semver_helper import get_version_prefix
|
|
9
|
+
|
|
10
|
+
STS_GATE_LABEL = "api.openshift.com/gate-sts"
|
|
11
|
+
AUS_VERSION_GATE_APPROVALS_LABEL = "sre-capabilities.aus.version-gate-approvals"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AUSSTSGateHandler:
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
job_controller: K8sJobController,
|
|
18
|
+
aws_iam_role: str,
|
|
19
|
+
rosa_job_service_account: str | None = None,
|
|
20
|
+
rosa_job_image: str | None = None,
|
|
21
|
+
) -> None:
|
|
22
|
+
self.job_controller = job_controller
|
|
23
|
+
self.aws_iam_role = aws_iam_role
|
|
24
|
+
self.rosa_job_image = rosa_job_image
|
|
25
|
+
self.rosa_job_service_account = rosa_job_service_account
|
|
26
|
+
|
|
27
|
+
def upgrade_rosa_roles(
|
|
28
|
+
self,
|
|
29
|
+
cluster: OCMCluster,
|
|
30
|
+
upgrade_version: str,
|
|
31
|
+
dry_run: bool,
|
|
32
|
+
ocm_api: OCMBaseClient,
|
|
33
|
+
ocm_org_id: str,
|
|
34
|
+
) -> bool:
|
|
35
|
+
if not cluster.aws:
|
|
36
|
+
return False
|
|
37
|
+
rosa = RosaSession(
|
|
38
|
+
aws_account_id=cluster.aws.aws_account_id,
|
|
39
|
+
aws_region=cluster.region.id,
|
|
40
|
+
aws_iam_role=self.aws_iam_role,
|
|
41
|
+
ocm_org_id=ocm_org_id,
|
|
42
|
+
ocm_api=ocm_api,
|
|
43
|
+
job_controller=self.job_controller,
|
|
44
|
+
image=self.rosa_job_image,
|
|
45
|
+
service_account=self.rosa_job_service_account,
|
|
46
|
+
)
|
|
47
|
+
policy_version = get_version_prefix(upgrade_version)
|
|
48
|
+
try:
|
|
49
|
+
rosa.upgrade_rosa_roles(
|
|
50
|
+
cluster_name=cluster.name,
|
|
51
|
+
upgrade_version=upgrade_version,
|
|
52
|
+
policy_version=policy_version,
|
|
53
|
+
dry_run=dry_run,
|
|
54
|
+
)
|
|
55
|
+
except RosaCliError as e:
|
|
56
|
+
logging.error(f"Failed to upgrade roles for cluster {cluster.name}: {e}")
|
|
57
|
+
e.write_logs_to_logger(logging.error)
|
|
58
|
+
return False
|
|
59
|
+
return True
|
reconcile/aus/base.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import datetime as dt
|
|
2
1
|
import logging
|
|
3
2
|
import sys
|
|
4
3
|
from abc import (
|
|
@@ -17,10 +16,15 @@ from typing import (
|
|
|
17
16
|
)
|
|
18
17
|
|
|
19
18
|
from croniter import croniter
|
|
20
|
-
from pydantic import BaseModel
|
|
19
|
+
from pydantic import BaseModel
|
|
21
20
|
from requests.exceptions import HTTPError
|
|
22
21
|
from semver import VersionInfo
|
|
23
22
|
|
|
23
|
+
from reconcile.aus.aus_sts_gate_handler import (
|
|
24
|
+
AUS_VERSION_GATE_APPROVALS_LABEL,
|
|
25
|
+
STS_GATE_LABEL,
|
|
26
|
+
AUSSTSGateHandler,
|
|
27
|
+
)
|
|
24
28
|
from reconcile.aus.cluster_version_data import (
|
|
25
29
|
VersionData,
|
|
26
30
|
VersionDataMap,
|
|
@@ -71,10 +75,18 @@ from reconcile.utils.clusterhealth.telemeter import (
|
|
|
71
75
|
TELEMETER_SOURCE,
|
|
72
76
|
TelemeterClusterHealthProvider,
|
|
73
77
|
)
|
|
78
|
+
from reconcile.utils.datetime_util import (
|
|
79
|
+
ensure_utc,
|
|
80
|
+
from_utc_iso_format,
|
|
81
|
+
to_utc_seconds_iso_format,
|
|
82
|
+
utc_now,
|
|
83
|
+
)
|
|
74
84
|
from reconcile.utils.defer import defer
|
|
75
85
|
from reconcile.utils.disabled_integrations import integration_is_enabled
|
|
76
86
|
from reconcile.utils.filtering import remove_none_values_from_dict
|
|
87
|
+
from reconcile.utils.jobcontroller.controller import build_job_controller
|
|
77
88
|
from reconcile.utils.ocm.addons import AddonService, AddonServiceV1, AddonServiceV2
|
|
89
|
+
from reconcile.utils.ocm.base import LabelContainer
|
|
78
90
|
from reconcile.utils.ocm.clusters import (
|
|
79
91
|
OCMCluster,
|
|
80
92
|
)
|
|
@@ -97,6 +109,7 @@ from reconcile.utils.runtime.integration import (
|
|
|
97
109
|
PydanticRunParams,
|
|
98
110
|
QontractReconcileIntegration,
|
|
99
111
|
)
|
|
112
|
+
from reconcile.utils.secret_reader import SecretReaderBase
|
|
100
113
|
from reconcile.utils.semver_helper import (
|
|
101
114
|
get_version_prefix,
|
|
102
115
|
parse_semver,
|
|
@@ -107,11 +120,22 @@ from reconcile.utils.state import init_state
|
|
|
107
120
|
MIN_DELTA_MINUTES = 6
|
|
108
121
|
|
|
109
122
|
|
|
123
|
+
class RosaRoleUpgradeHandlerParams(PydanticRunParams):
|
|
124
|
+
job_controller_cluster: str
|
|
125
|
+
job_controller_namespace: str
|
|
126
|
+
rosa_job_service_account: str
|
|
127
|
+
rosa_role: str
|
|
128
|
+
rosa_job_image: str | None = None
|
|
129
|
+
integration_name: str
|
|
130
|
+
integration_version: str
|
|
131
|
+
|
|
132
|
+
|
|
110
133
|
class AdvancedUpgradeSchedulerBaseIntegrationParams(PydanticRunParams):
|
|
111
134
|
ocm_environment: str | None = None
|
|
112
135
|
ocm_organization_ids: set[str] | None = None
|
|
113
136
|
excluded_ocm_organization_ids: set[str] | None = None
|
|
114
137
|
ignore_sts_clusters: bool = False
|
|
138
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None
|
|
115
139
|
|
|
116
140
|
|
|
117
141
|
class ReconcileError(Exception):
|
|
@@ -399,15 +423,20 @@ class AbstractUpgradePolicy(ABC, BaseModel):
|
|
|
399
423
|
|
|
400
424
|
cluster: OCMCluster
|
|
401
425
|
|
|
402
|
-
id: str | None
|
|
403
|
-
next_run: str | None
|
|
404
|
-
schedule: str | None
|
|
426
|
+
id: str | None = None
|
|
427
|
+
next_run: str | None = None
|
|
428
|
+
schedule: str | None = None
|
|
405
429
|
schedule_type: str
|
|
406
430
|
version: str
|
|
407
|
-
state: str | None
|
|
431
|
+
state: str | None = None
|
|
408
432
|
|
|
409
433
|
@abstractmethod
|
|
410
|
-
def create(
|
|
434
|
+
def create(
|
|
435
|
+
self,
|
|
436
|
+
ocm_api: OCMBaseClient,
|
|
437
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None,
|
|
438
|
+
secret_reader: SecretReaderBase | None = None,
|
|
439
|
+
) -> None:
|
|
411
440
|
pass
|
|
412
441
|
|
|
413
442
|
@abstractmethod
|
|
@@ -420,21 +449,23 @@ class AbstractUpgradePolicy(ABC, BaseModel):
|
|
|
420
449
|
|
|
421
450
|
|
|
422
451
|
def addon_upgrade_policy_soonest_next_run() -> str:
|
|
423
|
-
now =
|
|
452
|
+
now = utc_now()
|
|
424
453
|
next_run = now + timedelta(minutes=MIN_DELTA_MINUTES)
|
|
425
|
-
return next_run
|
|
454
|
+
return to_utc_seconds_iso_format(next_run)
|
|
426
455
|
|
|
427
456
|
|
|
428
|
-
class AddonUpgradePolicy(AbstractUpgradePolicy):
|
|
457
|
+
class AddonUpgradePolicy(AbstractUpgradePolicy, arbitrary_types_allowed=True):
|
|
429
458
|
"""Class to create and delete Addon upgrade policies in OCM"""
|
|
430
459
|
|
|
431
460
|
addon_id: str
|
|
432
461
|
addon_service: AddonService
|
|
433
462
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
463
|
+
def create(
|
|
464
|
+
self,
|
|
465
|
+
ocm_api: OCMBaseClient,
|
|
466
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None,
|
|
467
|
+
secret_reader: SecretReaderBase | None = None,
|
|
468
|
+
) -> None:
|
|
438
469
|
self.addon_service.create_addon_upgrade_policy(
|
|
439
470
|
ocm_api=ocm_api,
|
|
440
471
|
cluster_id=self.cluster.id,
|
|
@@ -467,14 +498,64 @@ class AddonUpgradePolicy(AbstractUpgradePolicy):
|
|
|
467
498
|
class ClusterUpgradePolicy(AbstractUpgradePolicy):
|
|
468
499
|
"""Class to create ClusterUpgradePolicies in OCM"""
|
|
469
500
|
|
|
470
|
-
|
|
501
|
+
organization_id: str
|
|
502
|
+
cluster_labels: LabelContainer
|
|
503
|
+
|
|
504
|
+
def create(
|
|
505
|
+
self,
|
|
506
|
+
ocm_api: OCMBaseClient,
|
|
507
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None,
|
|
508
|
+
secret_reader: SecretReaderBase | None = None,
|
|
509
|
+
) -> None:
|
|
471
510
|
policy = {
|
|
472
511
|
"version": self.version,
|
|
473
512
|
"schedule_type": "manual",
|
|
474
513
|
"next_run": self.next_run,
|
|
475
514
|
}
|
|
515
|
+
if (
|
|
516
|
+
rosa_role_upgrade_handler_params
|
|
517
|
+
and secret_reader
|
|
518
|
+
and self.should_upgrade_roles()
|
|
519
|
+
):
|
|
520
|
+
logging.info(f"Updating account and operator roles for {self.cluster.name}")
|
|
521
|
+
aus_sts_gate_handler = AUSSTSGateHandler(
|
|
522
|
+
job_controller=build_job_controller(
|
|
523
|
+
integration=rosa_role_upgrade_handler_params.integration_name,
|
|
524
|
+
integration_version=rosa_role_upgrade_handler_params.integration_version,
|
|
525
|
+
cluster=rosa_role_upgrade_handler_params.job_controller_cluster,
|
|
526
|
+
namespace=rosa_role_upgrade_handler_params.job_controller_namespace,
|
|
527
|
+
secret_reader=secret_reader,
|
|
528
|
+
dry_run=False,
|
|
529
|
+
),
|
|
530
|
+
aws_iam_role=rosa_role_upgrade_handler_params.rosa_role,
|
|
531
|
+
rosa_job_service_account=rosa_role_upgrade_handler_params.rosa_job_service_account,
|
|
532
|
+
rosa_job_image=rosa_role_upgrade_handler_params.rosa_job_image,
|
|
533
|
+
)
|
|
534
|
+
if not aus_sts_gate_handler.upgrade_rosa_roles(
|
|
535
|
+
ocm_api=ocm_api,
|
|
536
|
+
cluster=self.cluster,
|
|
537
|
+
dry_run=False,
|
|
538
|
+
upgrade_version=self.version,
|
|
539
|
+
ocm_org_id=self.organization_id,
|
|
540
|
+
):
|
|
541
|
+
logging.error(
|
|
542
|
+
f"Failed to update account and operator roles for {self.cluster.name}"
|
|
543
|
+
)
|
|
476
544
|
create_upgrade_policy(ocm_api, self.cluster.id, policy)
|
|
477
545
|
|
|
546
|
+
def should_upgrade_roles(self) -> bool:
|
|
547
|
+
handler_csv = self.cluster_labels.get_label_value(
|
|
548
|
+
AUS_VERSION_GATE_APPROVALS_LABEL
|
|
549
|
+
)
|
|
550
|
+
if not handler_csv:
|
|
551
|
+
return False
|
|
552
|
+
|
|
553
|
+
return (
|
|
554
|
+
self.cluster.is_sts()
|
|
555
|
+
and self.cluster.is_rosa_classic()
|
|
556
|
+
and STS_GATE_LABEL in set(handler_csv.split(","))
|
|
557
|
+
)
|
|
558
|
+
|
|
478
559
|
def delete(self, ocm_api: OCMBaseClient) -> None:
|
|
479
560
|
raise NotImplementedError("ClusterUpgradePolicy.delete() not implemented")
|
|
480
561
|
|
|
@@ -492,7 +573,12 @@ class ClusterUpgradePolicy(AbstractUpgradePolicy):
|
|
|
492
573
|
class ControlPlaneUpgradePolicy(AbstractUpgradePolicy):
|
|
493
574
|
"""Class to create and delete ControlPlanUpgradePolicies in OCM"""
|
|
494
575
|
|
|
495
|
-
def create(
|
|
576
|
+
def create(
|
|
577
|
+
self,
|
|
578
|
+
ocm_api: OCMBaseClient,
|
|
579
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None,
|
|
580
|
+
secret_reader: SecretReaderBase | None = None,
|
|
581
|
+
) -> None:
|
|
496
582
|
policy = {
|
|
497
583
|
"version": self.version,
|
|
498
584
|
"schedule_type": "manual",
|
|
@@ -516,10 +602,16 @@ class ControlPlaneUpgradePolicy(AbstractUpgradePolicy):
|
|
|
516
602
|
|
|
517
603
|
|
|
518
604
|
class NodePoolUpgradePolicy(AbstractUpgradePolicy):
|
|
519
|
-
node_pool: str
|
|
520
605
|
"""Class to create NodePoolUpgradePolicies in OCM"""
|
|
521
606
|
|
|
522
|
-
|
|
607
|
+
node_pool: str
|
|
608
|
+
|
|
609
|
+
def create(
|
|
610
|
+
self,
|
|
611
|
+
ocm_api: OCMBaseClient,
|
|
612
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None,
|
|
613
|
+
secret_reader: SecretReaderBase | None = None,
|
|
614
|
+
) -> None:
|
|
523
615
|
policy = {
|
|
524
616
|
"version": self.version,
|
|
525
617
|
"schedule_type": "manual",
|
|
@@ -545,13 +637,19 @@ class NodePoolUpgradePolicy(AbstractUpgradePolicy):
|
|
|
545
637
|
return f"node pool upgrade policy - {remove_none_values_from_dict(details)}"
|
|
546
638
|
|
|
547
639
|
|
|
548
|
-
class UpgradePolicyHandler(BaseModel, extra=
|
|
640
|
+
class UpgradePolicyHandler(BaseModel, extra="forbid"):
|
|
549
641
|
"""Class to handle upgrade policy actions"""
|
|
550
642
|
|
|
551
643
|
action: str
|
|
552
644
|
policy: AbstractUpgradePolicy
|
|
553
645
|
|
|
554
|
-
def act(
|
|
646
|
+
def act(
|
|
647
|
+
self,
|
|
648
|
+
dry_run: bool,
|
|
649
|
+
ocm_api: OCMBaseClient,
|
|
650
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None,
|
|
651
|
+
secret_reader: SecretReaderBase | None = None,
|
|
652
|
+
) -> None:
|
|
555
653
|
logging.info(f"{self.action} {self.policy.summarize()}")
|
|
556
654
|
if dry_run:
|
|
557
655
|
return
|
|
@@ -561,7 +659,7 @@ class UpgradePolicyHandler(BaseModel, extra=Extra.forbid):
|
|
|
561
659
|
elif self.action == "delete":
|
|
562
660
|
self.policy.delete(ocm_api)
|
|
563
661
|
elif self.action == "create":
|
|
564
|
-
self.policy.create(ocm_api)
|
|
662
|
+
self.policy.create(ocm_api, rosa_role_upgrade_handler_params, secret_reader)
|
|
565
663
|
|
|
566
664
|
|
|
567
665
|
def fetch_current_state(
|
|
@@ -579,6 +677,7 @@ def fetch_current_state(
|
|
|
579
677
|
)
|
|
580
678
|
current_state.extend(
|
|
581
679
|
AddonUpgradePolicy(
|
|
680
|
+
organization_id=spec.org.org_id,
|
|
582
681
|
id=addon_upgrade_policy.id,
|
|
583
682
|
addon_id=addon_spec.addon.addon.id,
|
|
584
683
|
cluster=spec.cluster,
|
|
@@ -615,6 +714,8 @@ def fetch_current_state(
|
|
|
615
714
|
for upgrade_policy in upgrade_policies:
|
|
616
715
|
policy = upgrade_policy | {
|
|
617
716
|
"cluster": spec.cluster,
|
|
717
|
+
"organization_id": spec.org.org_id,
|
|
718
|
+
"cluster_labels": spec.cluster_labels,
|
|
618
719
|
}
|
|
619
720
|
current_state.append(ClusterUpgradePolicy(**policy))
|
|
620
721
|
|
|
@@ -638,8 +739,8 @@ def update_history(
|
|
|
638
739
|
version_data (VersionData): version data, including history of soakdays
|
|
639
740
|
upgrade_policies (list): query results of clusters upgrade policies
|
|
640
741
|
"""
|
|
641
|
-
now =
|
|
642
|
-
check_in = version_data.check_in or now
|
|
742
|
+
now = utc_now()
|
|
743
|
+
check_in = ensure_utc(version_data.check_in or now)
|
|
643
744
|
|
|
644
745
|
# we iterate over clusters upgrade policies and update the version history
|
|
645
746
|
for spec in org_upgrade_spec.specs:
|
|
@@ -930,7 +1031,7 @@ def verify_schedule_should_skip(
|
|
|
930
1031
|
# immediately
|
|
931
1032
|
delay_minutes = 1 if addon_id else MIN_DELTA_MINUTES
|
|
932
1033
|
next_schedule = iter.get_next(
|
|
933
|
-
|
|
1034
|
+
datetime, start_time=now + timedelta(minutes=delay_minutes)
|
|
934
1035
|
)
|
|
935
1036
|
next_schedule_in_seconds = (next_schedule - now).total_seconds()
|
|
936
1037
|
next_schedule_in_hours = next_schedule_in_seconds / 3600 # seconds in hour
|
|
@@ -947,7 +1048,7 @@ def verify_schedule_should_skip(
|
|
|
947
1048
|
f"[{desired.org.org_id}/{desired.org.name}/{desired.cluster.name}] skipping cluster with no upcoming upgrade"
|
|
948
1049
|
)
|
|
949
1050
|
return None
|
|
950
|
-
return next_schedule
|
|
1051
|
+
return to_utc_seconds_iso_format(next_schedule)
|
|
951
1052
|
|
|
952
1053
|
|
|
953
1054
|
def verify_max_upgrades_should_skip(
|
|
@@ -1013,6 +1114,8 @@ def _create_upgrade_policy(
|
|
|
1013
1114
|
)
|
|
1014
1115
|
return ClusterUpgradePolicy(
|
|
1015
1116
|
cluster=spec.cluster,
|
|
1117
|
+
organization_id=spec.org.org_id,
|
|
1118
|
+
cluster_labels=spec.cluster_labels,
|
|
1016
1119
|
version=version,
|
|
1017
1120
|
schedule_type="manual",
|
|
1018
1121
|
next_run=next_schedule,
|
|
@@ -1024,8 +1127,8 @@ def _calculate_node_pool_diffs(
|
|
|
1024
1127
|
) -> UpgradePolicyHandler | None:
|
|
1025
1128
|
for pool in spec.node_pools:
|
|
1026
1129
|
if parse_semver(pool.version).match(f"<{spec.current_version}"):
|
|
1027
|
-
next_schedule = (
|
|
1028
|
-
|
|
1130
|
+
next_schedule = to_utc_seconds_iso_format(
|
|
1131
|
+
now + timedelta(minutes=MIN_DELTA_MINUTES)
|
|
1029
1132
|
)
|
|
1030
1133
|
return UpgradePolicyHandler(
|
|
1031
1134
|
action="create",
|
|
@@ -1082,7 +1185,7 @@ def calculate_diff(
|
|
|
1082
1185
|
set_upgrading(spec.cluster.id, spec.effective_mutexes, sector_name)
|
|
1083
1186
|
|
|
1084
1187
|
addon_service = init_addon_service(desired_state.org.environment)
|
|
1085
|
-
now =
|
|
1188
|
+
now = utc_now()
|
|
1086
1189
|
gates = get_version_gates(ocm_api)
|
|
1087
1190
|
for spec in desired_state.specs:
|
|
1088
1191
|
sector_name = spec.upgrade_policy.conditions.sector
|
|
@@ -1120,11 +1223,11 @@ def calculate_diff(
|
|
|
1120
1223
|
action="create",
|
|
1121
1224
|
policy=AddonUpgradePolicy(
|
|
1122
1225
|
action="create",
|
|
1226
|
+
organization_id=spec.org.org_id,
|
|
1123
1227
|
cluster=spec.cluster,
|
|
1124
1228
|
version=version,
|
|
1125
1229
|
schedule_type="manual",
|
|
1126
1230
|
addon_id=addon_id,
|
|
1127
|
-
upgrade_type="ADDON",
|
|
1128
1231
|
addon_service=addon_service,
|
|
1129
1232
|
),
|
|
1130
1233
|
)
|
|
@@ -1185,6 +1288,8 @@ def act(
|
|
|
1185
1288
|
dry_run: bool,
|
|
1186
1289
|
diffs: list[UpgradePolicyHandler],
|
|
1187
1290
|
ocm_api: OCMBaseClient,
|
|
1291
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None,
|
|
1292
|
+
secret_reader: SecretReaderBase | None = None,
|
|
1188
1293
|
addon_id: str | None = None,
|
|
1189
1294
|
) -> None:
|
|
1190
1295
|
diffs.sort(key=sort_diffs)
|
|
@@ -1197,7 +1302,7 @@ def act(
|
|
|
1197
1302
|
):
|
|
1198
1303
|
continue
|
|
1199
1304
|
try:
|
|
1200
|
-
diff.act(dry_run, ocm_api)
|
|
1305
|
+
diff.act(dry_run, ocm_api, rosa_role_upgrade_handler_params, secret_reader)
|
|
1201
1306
|
except HTTPError as e:
|
|
1202
1307
|
logging.error(f"{policy.cluster.name}: {e}: {e.response.text}")
|
|
1203
1308
|
|
|
@@ -1297,10 +1402,8 @@ def remaining_soak_day_metric_values_for_cluster(
|
|
|
1297
1402
|
remaining_soakdays[idx] = UPGRADE_STARTED_METRIC_VALUE
|
|
1298
1403
|
if current_upgrade.next_run:
|
|
1299
1404
|
# if an upgrade runs for over 6 hours, we mark it as a long running upgrade
|
|
1300
|
-
next_run =
|
|
1301
|
-
|
|
1302
|
-
)
|
|
1303
|
-
now = datetime.utcnow()
|
|
1405
|
+
next_run = from_utc_iso_format(current_upgrade.next_run)
|
|
1406
|
+
now = utc_now()
|
|
1304
1407
|
hours_ago = (now - next_run).total_seconds() / 3600
|
|
1305
1408
|
if hours_ago >= 6:
|
|
1306
1409
|
remaining_soakdays[idx] = UPGRADE_LONG_RUNNING_METRIC_VALUE
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import json
|
|
2
1
|
from collections.abc import Iterable
|
|
3
2
|
from datetime import datetime
|
|
4
3
|
from typing import (
|
|
@@ -20,6 +19,17 @@ class WorkloadHistory(BaseModel):
|
|
|
20
19
|
soak_days: float = 0.0
|
|
21
20
|
reporting: list[str] = Field(default_factory=list)
|
|
22
21
|
|
|
22
|
+
def __eq__(self, value: Any) -> bool:
|
|
23
|
+
if isinstance(value, WorkloadHistory):
|
|
24
|
+
return super().__eq__(value)
|
|
25
|
+
|
|
26
|
+
if isinstance(value, dict):
|
|
27
|
+
return self.soak_days == value.get("soak_days", 0.0) and sorted(
|
|
28
|
+
self.reporting
|
|
29
|
+
) == sorted(value.get("reporting", []))
|
|
30
|
+
|
|
31
|
+
return False
|
|
32
|
+
|
|
23
33
|
|
|
24
34
|
class VersionHistory(BaseModel):
|
|
25
35
|
workloads: dict[str, WorkloadHistory] = Field(default_factory=dict)
|
|
@@ -38,7 +48,7 @@ class Stats(BaseModel):
|
|
|
38
48
|
|
|
39
49
|
min_version: str
|
|
40
50
|
min_version_per_workload: dict[str, str] = Field(default_factory=dict)
|
|
41
|
-
inherited: Optional["Stats"]
|
|
51
|
+
inherited: Optional["Stats"] = None
|
|
42
52
|
|
|
43
53
|
def inherit(self, added: "Stats") -> None:
|
|
44
54
|
"""adds the provided stats to our inherited data
|
|
@@ -93,12 +103,12 @@ class VersionData(BaseModel):
|
|
|
93
103
|
upgrade policies.
|
|
94
104
|
"""
|
|
95
105
|
|
|
96
|
-
check_in: datetime | None
|
|
106
|
+
check_in: datetime | None = None
|
|
97
107
|
versions: dict[str, VersionHistory] = Field(default_factory=dict)
|
|
98
|
-
stats: Stats | None
|
|
108
|
+
stats: Stats | None = None
|
|
99
109
|
|
|
100
110
|
def jsondict(self) -> dict[str, Any]:
|
|
101
|
-
return
|
|
111
|
+
return self.model_dump(mode="json", exclude_none=True)
|
|
102
112
|
|
|
103
113
|
def save(self, state: State, ocm_name: str) -> None:
|
|
104
114
|
state.add(ocm_name, self.jsondict(), force=True)
|
reconcile/aus/models.py
CHANGED
|
@@ -14,6 +14,7 @@ from reconcile.aus.healthchecks import AUSClusterHealth
|
|
|
14
14
|
from reconcile.gql_definitions.fragments.aus_organization import AUSOCMOrganization
|
|
15
15
|
from reconcile.gql_definitions.fragments.upgrade_policy import ClusterUpgradePolicyV1
|
|
16
16
|
from reconcile.utils.ocm.addons import OCMAddonInstallation
|
|
17
|
+
from reconcile.utils.ocm.base import LabelContainer
|
|
17
18
|
from reconcile.utils.ocm.clusters import OCMCluster
|
|
18
19
|
from reconcile.utils.semver_helper import parse_semver
|
|
19
20
|
|
|
@@ -33,6 +34,7 @@ class ClusterUpgradeSpec(BaseModel):
|
|
|
33
34
|
|
|
34
35
|
org: AUSOCMOrganization
|
|
35
36
|
cluster: OCMCluster
|
|
37
|
+
cluster_labels: LabelContainer | None = None
|
|
36
38
|
upgrade_policy: ClusterUpgradePolicyV1 = Field(..., alias="upgradePolicy")
|
|
37
39
|
health: AUSClusterHealth
|
|
38
40
|
node_pools: list[NodePoolSpec] = Field(default_factory=list, alias="nodePools")
|
|
@@ -232,7 +234,7 @@ class SectorConfigError(Exception):
|
|
|
232
234
|
|
|
233
235
|
class Sector(BaseModel):
|
|
234
236
|
name: str
|
|
235
|
-
max_parallel_upgrades: str | None
|
|
237
|
+
max_parallel_upgrades: str | None = None
|
|
236
238
|
dependencies: list[Sector] = Field(default_factory=list)
|
|
237
239
|
_specs: dict[str, ClusterUpgradeSpec] = PrivateAttr(default_factory=dict)
|
|
238
240
|
|
|
@@ -82,7 +82,14 @@ class OCMClusterUpgradeSchedulerIntegration(
|
|
|
82
82
|
version_data,
|
|
83
83
|
integration=self.name,
|
|
84
84
|
)
|
|
85
|
-
|
|
85
|
+
|
|
86
|
+
aus.act(
|
|
87
|
+
dry_run,
|
|
88
|
+
diffs,
|
|
89
|
+
ocm_api,
|
|
90
|
+
self.params.rosa_role_upgrade_handler_params,
|
|
91
|
+
self.secret_reader,
|
|
92
|
+
)
|
|
86
93
|
|
|
87
94
|
def expose_version_data_metrics(
|
|
88
95
|
self,
|