qontract-reconcile 0.10.2.dev361__py3-none-any.whl → 0.10.2.dev430__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.dev430.dist-info}/METADATA +13 -12
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/RECORD +351 -345
- 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_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/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 +0 -2
- reconcile/checkpoint.py +11 -3
- reconcile/cli.py +93 -10
- 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 +4 -7
- 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 +5 -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 +15 -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 +33 -6
- 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 +7 -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 +724 -129
- 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 +30 -6
- 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 +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 +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 +97 -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_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/templating/lib/rendering.py +3 -3
- reconcile/templating/renderer.py +2 -2
- 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 +10 -1
- 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 +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/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/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/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 +7 -10
- 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 +246 -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/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 +134 -74
- 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/qontract_cli.py +28 -17
- tools/template_validation.py +3 -1
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev430.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):
|
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,7 +16,7 @@ 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
|
|
|
@@ -47,7 +46,7 @@ from reconcile.aus.models import (
|
|
|
47
46
|
OrganizationUpgradeSpec,
|
|
48
47
|
Sector,
|
|
49
48
|
)
|
|
50
|
-
from reconcile.aus.version_gates import HANDLERS
|
|
49
|
+
from reconcile.aus.version_gates import HANDLERS, sts_version_gate_handler
|
|
51
50
|
from reconcile.gql_definitions.advanced_upgrade_service.aus_organization import (
|
|
52
51
|
query as aus_organizations_query,
|
|
53
52
|
)
|
|
@@ -71,10 +70,18 @@ from reconcile.utils.clusterhealth.telemeter import (
|
|
|
71
70
|
TELEMETER_SOURCE,
|
|
72
71
|
TelemeterClusterHealthProvider,
|
|
73
72
|
)
|
|
73
|
+
from reconcile.utils.datetime_util import (
|
|
74
|
+
ensure_utc,
|
|
75
|
+
from_utc_iso_format,
|
|
76
|
+
to_utc_seconds_iso_format,
|
|
77
|
+
utc_now,
|
|
78
|
+
)
|
|
74
79
|
from reconcile.utils.defer import defer
|
|
75
80
|
from reconcile.utils.disabled_integrations import integration_is_enabled
|
|
76
81
|
from reconcile.utils.filtering import remove_none_values_from_dict
|
|
82
|
+
from reconcile.utils.jobcontroller.controller import build_job_controller
|
|
77
83
|
from reconcile.utils.ocm.addons import AddonService, AddonServiceV1, AddonServiceV2
|
|
84
|
+
from reconcile.utils.ocm.base import LabelContainer
|
|
78
85
|
from reconcile.utils.ocm.clusters import (
|
|
79
86
|
OCMCluster,
|
|
80
87
|
)
|
|
@@ -97,6 +104,7 @@ from reconcile.utils.runtime.integration import (
|
|
|
97
104
|
PydanticRunParams,
|
|
98
105
|
QontractReconcileIntegration,
|
|
99
106
|
)
|
|
107
|
+
from reconcile.utils.secret_reader import SecretReaderBase
|
|
100
108
|
from reconcile.utils.semver_helper import (
|
|
101
109
|
get_version_prefix,
|
|
102
110
|
parse_semver,
|
|
@@ -105,6 +113,18 @@ from reconcile.utils.semver_helper import (
|
|
|
105
113
|
from reconcile.utils.state import init_state
|
|
106
114
|
|
|
107
115
|
MIN_DELTA_MINUTES = 6
|
|
116
|
+
STS_GATE_LABEL = "api.openshift.com/gate-sts"
|
|
117
|
+
AUS_VERSION_GATE_APPROVALS_LABEL = "sre-capabilities.aus.version-gate-approvals"
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class RosaRoleUpgradeHandlerParams(PydanticRunParams):
|
|
121
|
+
job_controller_cluster: str
|
|
122
|
+
job_controller_namespace: str
|
|
123
|
+
rosa_job_service_account: str
|
|
124
|
+
rosa_role: str
|
|
125
|
+
rosa_job_image: str | None = None
|
|
126
|
+
integration_name: str
|
|
127
|
+
integration_version: str
|
|
108
128
|
|
|
109
129
|
|
|
110
130
|
class AdvancedUpgradeSchedulerBaseIntegrationParams(PydanticRunParams):
|
|
@@ -112,6 +132,7 @@ class AdvancedUpgradeSchedulerBaseIntegrationParams(PydanticRunParams):
|
|
|
112
132
|
ocm_organization_ids: set[str] | None = None
|
|
113
133
|
excluded_ocm_organization_ids: set[str] | None = None
|
|
114
134
|
ignore_sts_clusters: bool = False
|
|
135
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None
|
|
115
136
|
|
|
116
137
|
|
|
117
138
|
class ReconcileError(Exception):
|
|
@@ -399,15 +420,20 @@ class AbstractUpgradePolicy(ABC, BaseModel):
|
|
|
399
420
|
|
|
400
421
|
cluster: OCMCluster
|
|
401
422
|
|
|
402
|
-
id: str | None
|
|
403
|
-
next_run: str | None
|
|
404
|
-
schedule: str | None
|
|
423
|
+
id: str | None = None
|
|
424
|
+
next_run: str | None = None
|
|
425
|
+
schedule: str | None = None
|
|
405
426
|
schedule_type: str
|
|
406
427
|
version: str
|
|
407
|
-
state: str | None
|
|
428
|
+
state: str | None = None
|
|
408
429
|
|
|
409
430
|
@abstractmethod
|
|
410
|
-
def create(
|
|
431
|
+
def create(
|
|
432
|
+
self,
|
|
433
|
+
ocm_api: OCMBaseClient,
|
|
434
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None,
|
|
435
|
+
secret_reader: SecretReaderBase | None = None,
|
|
436
|
+
) -> None:
|
|
411
437
|
pass
|
|
412
438
|
|
|
413
439
|
@abstractmethod
|
|
@@ -420,12 +446,12 @@ class AbstractUpgradePolicy(ABC, BaseModel):
|
|
|
420
446
|
|
|
421
447
|
|
|
422
448
|
def addon_upgrade_policy_soonest_next_run() -> str:
|
|
423
|
-
now =
|
|
449
|
+
now = utc_now()
|
|
424
450
|
next_run = now + timedelta(minutes=MIN_DELTA_MINUTES)
|
|
425
|
-
return next_run
|
|
451
|
+
return to_utc_seconds_iso_format(next_run)
|
|
426
452
|
|
|
427
453
|
|
|
428
|
-
class AddonUpgradePolicy(AbstractUpgradePolicy):
|
|
454
|
+
class AddonUpgradePolicy(AbstractUpgradePolicy, arbitrary_types_allowed=True):
|
|
429
455
|
"""Class to create and delete Addon upgrade policies in OCM"""
|
|
430
456
|
|
|
431
457
|
addon_id: str
|
|
@@ -434,7 +460,12 @@ class AddonUpgradePolicy(AbstractUpgradePolicy):
|
|
|
434
460
|
class Config:
|
|
435
461
|
arbitrary_types_allowed = True
|
|
436
462
|
|
|
437
|
-
def create(
|
|
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,63 @@ 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
|
+
sts_gate_handler = sts_version_gate_handler.STSGateHandler(
|
|
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 sts_gate_handler.upgrade_rosa_roles_v2(
|
|
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
|
+
return (
|
|
553
|
+
self.cluster.is_sts()
|
|
554
|
+
and self.cluster.is_rosa_classic()
|
|
555
|
+
and STS_GATE_LABEL in set(handler_csv.split(","))
|
|
556
|
+
)
|
|
557
|
+
|
|
478
558
|
def delete(self, ocm_api: OCMBaseClient) -> None:
|
|
479
559
|
raise NotImplementedError("ClusterUpgradePolicy.delete() not implemented")
|
|
480
560
|
|
|
@@ -492,7 +572,12 @@ class ClusterUpgradePolicy(AbstractUpgradePolicy):
|
|
|
492
572
|
class ControlPlaneUpgradePolicy(AbstractUpgradePolicy):
|
|
493
573
|
"""Class to create and delete ControlPlanUpgradePolicies in OCM"""
|
|
494
574
|
|
|
495
|
-
def create(
|
|
575
|
+
def create(
|
|
576
|
+
self,
|
|
577
|
+
ocm_api: OCMBaseClient,
|
|
578
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None,
|
|
579
|
+
secret_reader: SecretReaderBase | None = None,
|
|
580
|
+
) -> None:
|
|
496
581
|
policy = {
|
|
497
582
|
"version": self.version,
|
|
498
583
|
"schedule_type": "manual",
|
|
@@ -516,10 +601,16 @@ class ControlPlaneUpgradePolicy(AbstractUpgradePolicy):
|
|
|
516
601
|
|
|
517
602
|
|
|
518
603
|
class NodePoolUpgradePolicy(AbstractUpgradePolicy):
|
|
519
|
-
node_pool: str
|
|
520
604
|
"""Class to create NodePoolUpgradePolicies in OCM"""
|
|
521
605
|
|
|
522
|
-
|
|
606
|
+
node_pool: str
|
|
607
|
+
|
|
608
|
+
def create(
|
|
609
|
+
self,
|
|
610
|
+
ocm_api: OCMBaseClient,
|
|
611
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None,
|
|
612
|
+
secret_reader: SecretReaderBase | None = None,
|
|
613
|
+
) -> None:
|
|
523
614
|
policy = {
|
|
524
615
|
"version": self.version,
|
|
525
616
|
"schedule_type": "manual",
|
|
@@ -545,13 +636,19 @@ class NodePoolUpgradePolicy(AbstractUpgradePolicy):
|
|
|
545
636
|
return f"node pool upgrade policy - {remove_none_values_from_dict(details)}"
|
|
546
637
|
|
|
547
638
|
|
|
548
|
-
class UpgradePolicyHandler(BaseModel, extra=
|
|
639
|
+
class UpgradePolicyHandler(BaseModel, extra="forbid"):
|
|
549
640
|
"""Class to handle upgrade policy actions"""
|
|
550
641
|
|
|
551
642
|
action: str
|
|
552
643
|
policy: AbstractUpgradePolicy
|
|
553
644
|
|
|
554
|
-
def act(
|
|
645
|
+
def act(
|
|
646
|
+
self,
|
|
647
|
+
dry_run: bool,
|
|
648
|
+
ocm_api: OCMBaseClient,
|
|
649
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None,
|
|
650
|
+
secret_reader: SecretReaderBase | None = None,
|
|
651
|
+
) -> None:
|
|
555
652
|
logging.info(f"{self.action} {self.policy.summarize()}")
|
|
556
653
|
if dry_run:
|
|
557
654
|
return
|
|
@@ -561,7 +658,7 @@ class UpgradePolicyHandler(BaseModel, extra=Extra.forbid):
|
|
|
561
658
|
elif self.action == "delete":
|
|
562
659
|
self.policy.delete(ocm_api)
|
|
563
660
|
elif self.action == "create":
|
|
564
|
-
self.policy.create(ocm_api)
|
|
661
|
+
self.policy.create(ocm_api, rosa_role_upgrade_handler_params, secret_reader)
|
|
565
662
|
|
|
566
663
|
|
|
567
664
|
def fetch_current_state(
|
|
@@ -579,6 +676,7 @@ def fetch_current_state(
|
|
|
579
676
|
)
|
|
580
677
|
current_state.extend(
|
|
581
678
|
AddonUpgradePolicy(
|
|
679
|
+
organization_id=spec.org.org_id,
|
|
582
680
|
id=addon_upgrade_policy.id,
|
|
583
681
|
addon_id=addon_spec.addon.addon.id,
|
|
584
682
|
cluster=spec.cluster,
|
|
@@ -615,6 +713,8 @@ def fetch_current_state(
|
|
|
615
713
|
for upgrade_policy in upgrade_policies:
|
|
616
714
|
policy = upgrade_policy | {
|
|
617
715
|
"cluster": spec.cluster,
|
|
716
|
+
"organization_id": spec.org.org_id,
|
|
717
|
+
"cluster_labels": spec.cluster_labels,
|
|
618
718
|
}
|
|
619
719
|
current_state.append(ClusterUpgradePolicy(**policy))
|
|
620
720
|
|
|
@@ -638,8 +738,8 @@ def update_history(
|
|
|
638
738
|
version_data (VersionData): version data, including history of soakdays
|
|
639
739
|
upgrade_policies (list): query results of clusters upgrade policies
|
|
640
740
|
"""
|
|
641
|
-
now =
|
|
642
|
-
check_in = version_data.check_in or now
|
|
741
|
+
now = utc_now()
|
|
742
|
+
check_in = ensure_utc(version_data.check_in or now)
|
|
643
743
|
|
|
644
744
|
# we iterate over clusters upgrade policies and update the version history
|
|
645
745
|
for spec in org_upgrade_spec.specs:
|
|
@@ -930,7 +1030,7 @@ def verify_schedule_should_skip(
|
|
|
930
1030
|
# immediately
|
|
931
1031
|
delay_minutes = 1 if addon_id else MIN_DELTA_MINUTES
|
|
932
1032
|
next_schedule = iter.get_next(
|
|
933
|
-
|
|
1033
|
+
datetime, start_time=now + timedelta(minutes=delay_minutes)
|
|
934
1034
|
)
|
|
935
1035
|
next_schedule_in_seconds = (next_schedule - now).total_seconds()
|
|
936
1036
|
next_schedule_in_hours = next_schedule_in_seconds / 3600 # seconds in hour
|
|
@@ -947,7 +1047,7 @@ def verify_schedule_should_skip(
|
|
|
947
1047
|
f"[{desired.org.org_id}/{desired.org.name}/{desired.cluster.name}] skipping cluster with no upcoming upgrade"
|
|
948
1048
|
)
|
|
949
1049
|
return None
|
|
950
|
-
return next_schedule
|
|
1050
|
+
return to_utc_seconds_iso_format(next_schedule)
|
|
951
1051
|
|
|
952
1052
|
|
|
953
1053
|
def verify_max_upgrades_should_skip(
|
|
@@ -1013,6 +1113,8 @@ def _create_upgrade_policy(
|
|
|
1013
1113
|
)
|
|
1014
1114
|
return ClusterUpgradePolicy(
|
|
1015
1115
|
cluster=spec.cluster,
|
|
1116
|
+
organization_id=spec.org.org_id,
|
|
1117
|
+
cluster_labels=spec.cluster_labels,
|
|
1016
1118
|
version=version,
|
|
1017
1119
|
schedule_type="manual",
|
|
1018
1120
|
next_run=next_schedule,
|
|
@@ -1024,8 +1126,8 @@ def _calculate_node_pool_diffs(
|
|
|
1024
1126
|
) -> UpgradePolicyHandler | None:
|
|
1025
1127
|
for pool in spec.node_pools:
|
|
1026
1128
|
if parse_semver(pool.version).match(f"<{spec.current_version}"):
|
|
1027
|
-
next_schedule = (
|
|
1028
|
-
|
|
1129
|
+
next_schedule = to_utc_seconds_iso_format(
|
|
1130
|
+
now + timedelta(minutes=MIN_DELTA_MINUTES)
|
|
1029
1131
|
)
|
|
1030
1132
|
return UpgradePolicyHandler(
|
|
1031
1133
|
action="create",
|
|
@@ -1082,7 +1184,7 @@ def calculate_diff(
|
|
|
1082
1184
|
set_upgrading(spec.cluster.id, spec.effective_mutexes, sector_name)
|
|
1083
1185
|
|
|
1084
1186
|
addon_service = init_addon_service(desired_state.org.environment)
|
|
1085
|
-
now =
|
|
1187
|
+
now = utc_now()
|
|
1086
1188
|
gates = get_version_gates(ocm_api)
|
|
1087
1189
|
for spec in desired_state.specs:
|
|
1088
1190
|
sector_name = spec.upgrade_policy.conditions.sector
|
|
@@ -1120,11 +1222,11 @@ def calculate_diff(
|
|
|
1120
1222
|
action="create",
|
|
1121
1223
|
policy=AddonUpgradePolicy(
|
|
1122
1224
|
action="create",
|
|
1225
|
+
organization_id=spec.org.org_id,
|
|
1123
1226
|
cluster=spec.cluster,
|
|
1124
1227
|
version=version,
|
|
1125
1228
|
schedule_type="manual",
|
|
1126
1229
|
addon_id=addon_id,
|
|
1127
|
-
upgrade_type="ADDON",
|
|
1128
1230
|
addon_service=addon_service,
|
|
1129
1231
|
),
|
|
1130
1232
|
)
|
|
@@ -1185,6 +1287,8 @@ def act(
|
|
|
1185
1287
|
dry_run: bool,
|
|
1186
1288
|
diffs: list[UpgradePolicyHandler],
|
|
1187
1289
|
ocm_api: OCMBaseClient,
|
|
1290
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None,
|
|
1291
|
+
secret_reader: SecretReaderBase | None = None,
|
|
1188
1292
|
addon_id: str | None = None,
|
|
1189
1293
|
) -> None:
|
|
1190
1294
|
diffs.sort(key=sort_diffs)
|
|
@@ -1197,7 +1301,7 @@ def act(
|
|
|
1197
1301
|
):
|
|
1198
1302
|
continue
|
|
1199
1303
|
try:
|
|
1200
|
-
diff.act(dry_run, ocm_api)
|
|
1304
|
+
diff.act(dry_run, ocm_api, rosa_role_upgrade_handler_params, secret_reader)
|
|
1201
1305
|
except HTTPError as e:
|
|
1202
1306
|
logging.error(f"{policy.cluster.name}: {e}: {e.response.text}")
|
|
1203
1307
|
|
|
@@ -1297,10 +1401,8 @@ def remaining_soak_day_metric_values_for_cluster(
|
|
|
1297
1401
|
remaining_soakdays[idx] = UPGRADE_STARTED_METRIC_VALUE
|
|
1298
1402
|
if current_upgrade.next_run:
|
|
1299
1403
|
# 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()
|
|
1404
|
+
next_run = from_utc_iso_format(current_upgrade.next_run)
|
|
1405
|
+
now = utc_now()
|
|
1304
1406
|
hours_ago = (now - next_run).total_seconds() / 3600
|
|
1305
1407
|
if hours_ago >= 6:
|
|
1306
1408
|
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,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from collections import defaultdict
|
|
2
|
+
from dataclasses import dataclass
|
|
2
3
|
|
|
3
4
|
from reconcile.aus.healthchecks import (
|
|
4
5
|
AUSClusterHealthCheckProvider,
|
|
@@ -13,6 +14,7 @@ from reconcile.aus.node_pool_spec import get_node_pool_specs_by_org_cluster
|
|
|
13
14
|
from reconcile.aus.ocm_upgrade_scheduler import OCMClusterUpgradeSchedulerIntegration
|
|
14
15
|
from reconcile.gql_definitions.fragments.aus_organization import AUSOCMOrganization
|
|
15
16
|
from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment
|
|
17
|
+
from reconcile.utils.ocm.base import LabelContainer
|
|
16
18
|
from reconcile.utils.ocm.clusters import (
|
|
17
19
|
OCMCluster,
|
|
18
20
|
discover_clusters_for_organizations,
|
|
@@ -22,6 +24,12 @@ from reconcile.utils.ocm_base_client import init_ocm_base_client
|
|
|
22
24
|
QONTRACT_INTEGRATION = "ocm-upgrade-scheduler-org"
|
|
23
25
|
|
|
24
26
|
|
|
27
|
+
@dataclass
|
|
28
|
+
class ClusterUpgradeSpecWithLabels:
|
|
29
|
+
cluster: OCMCluster
|
|
30
|
+
cluster_labels: LabelContainer
|
|
31
|
+
|
|
32
|
+
|
|
25
33
|
class OCMClusterUpgradeSchedulerOrgIntegration(OCMClusterUpgradeSchedulerIntegration):
|
|
26
34
|
@property
|
|
27
35
|
def name(self) -> str:
|
|
@@ -60,7 +68,10 @@ class OCMClusterUpgradeSchedulerOrgIntegration(OCMClusterUpgradeSchedulerIntegra
|
|
|
60
68
|
specs=self._build_cluster_upgrade_specs(
|
|
61
69
|
org=org,
|
|
62
70
|
clusters_by_name={
|
|
63
|
-
c.ocm_cluster.name:
|
|
71
|
+
c.ocm_cluster.name: ClusterUpgradeSpecWithLabels(
|
|
72
|
+
cluster=c.ocm_cluster,
|
|
73
|
+
cluster_labels=c.labels,
|
|
74
|
+
)
|
|
64
75
|
for c in clusters_by_org[org.org_id]
|
|
65
76
|
},
|
|
66
77
|
cluster_health_provider=build_cluster_health_providers_for_organization(
|
|
@@ -79,7 +90,7 @@ class OCMClusterUpgradeSchedulerOrgIntegration(OCMClusterUpgradeSchedulerIntegra
|
|
|
79
90
|
def _build_cluster_upgrade_specs(
|
|
80
91
|
self,
|
|
81
92
|
org: AUSOCMOrganization,
|
|
82
|
-
clusters_by_name: dict[str,
|
|
93
|
+
clusters_by_name: dict[str, ClusterUpgradeSpecWithLabels],
|
|
83
94
|
cluster_health_provider: AUSClusterHealthCheckProvider,
|
|
84
95
|
node_pool_specs_by_cluster_id: dict[str, list[NodePoolSpec]],
|
|
85
96
|
) -> list[ClusterUpgradeSpec]:
|
|
@@ -87,12 +98,16 @@ class OCMClusterUpgradeSchedulerOrgIntegration(OCMClusterUpgradeSchedulerIntegra
|
|
|
87
98
|
ClusterUpgradeSpec(
|
|
88
99
|
org=org,
|
|
89
100
|
upgradePolicy=cluster.upgrade_policy,
|
|
90
|
-
cluster=clusters_by_name[cluster.name],
|
|
101
|
+
cluster=clusters_by_name[cluster.name].cluster,
|
|
102
|
+
cluster_labels=clusters_by_name[cluster.name].cluster_labels,
|
|
91
103
|
health=cluster_health_provider.cluster_health(
|
|
92
|
-
cluster_external_id=clusters_by_name[
|
|
104
|
+
cluster_external_id=clusters_by_name[
|
|
105
|
+
cluster.name
|
|
106
|
+
].cluster.external_id,
|
|
93
107
|
org_id=org.org_id,
|
|
94
108
|
),
|
|
95
|
-
nodePools=node_pool_specs_by_cluster_id.get(ocm_cluster.id)
|
|
109
|
+
nodePools=node_pool_specs_by_cluster_id.get(ocm_cluster.cluster.id)
|
|
110
|
+
or [],
|
|
96
111
|
)
|
|
97
112
|
for cluster in org.upgrade_policy_clusters or []
|
|
98
113
|
# clusters that are not in the UUID dict will be ignored because
|