qontract-reconcile 0.10.2.dev394__py3-none-any.whl → 0.10.2.dev427__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev427.dist-info}/METADATA +5 -4
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev427.dist-info}/RECORD +316 -315
- reconcile/acs_rbac.py +2 -2
- reconcile/aus/advanced_upgrade_service.py +18 -12
- reconcile/aus/base.py +117 -18
- 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 +6 -6
- reconcile/aws_account_manager/reconciler.py +3 -3
- reconcile/aws_ami_cleanup/integration.py +2 -5
- reconcile/aws_ami_share.py +69 -62
- reconcile/aws_saml_idp/integration.py +5 -3
- reconcile/aws_saml_roles/integration.py +23 -22
- reconcile/aws_version_sync/integration.py +6 -12
- reconcile/change_owners/bundle.py +3 -3
- reconcile/change_owners/change_log_tracking.py +3 -2
- reconcile/change_owners/change_owners.py +1 -1
- reconcile/cli.py +62 -4
- reconcile/dashdotdb_dora.py +1 -1
- reconcile/dashdotdb_slo.py +1 -1
- reconcile/database_access_manager.py +8 -9
- reconcile/dynatrace_token_provider/integration.py +1 -1
- reconcile/endpoints_discovery/integration.py +4 -1
- reconcile/endpoints_discovery/merge_request.py +1 -1
- reconcile/endpoints_discovery/merge_request_manager.py +1 -1
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +3 -2
- reconcile/external_resources/metrics.py +1 -1
- reconcile/external_resources/model.py +13 -13
- reconcile/external_resources/reconciler.py +7 -4
- reconcile/external_resources/secrets_sync.py +2 -2
- reconcile/external_resources/state.py +22 -13
- reconcile/fleet_labeler/integration.py +1 -1
- reconcile/gcp_image_mirror.py +2 -2
- reconcile/github_org.py +1 -1
- reconcile/github_owners.py +4 -0
- reconcile/gitlab_members.py +6 -12
- reconcile/gitlab_permissions.py +8 -12
- reconcile/glitchtip_project_alerts/integration.py +3 -1
- reconcile/gql_definitions/acs/acs_instances.py +5 -5
- reconcile/gql_definitions/acs/acs_policies.py +5 -5
- reconcile/gql_definitions/acs/acs_rbac.py +5 -5
- reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +5 -5
- reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +5 -5
- reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +5 -5
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
- reconcile/gql_definitions/automated_actions/instance.py +46 -7
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +5 -5
- reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
- reconcile/gql_definitions/aws_version_sync/clusters.py +5 -5
- reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
- reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
- reconcile/gql_definitions/change_owners/queries/self_service_roles.py +5 -5
- reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +5 -5
- reconcile/gql_definitions/common/alerting_services_settings.py +5 -5
- reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
- reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
- reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_roles.py +5 -5
- reconcile/gql_definitions/common/app_interface_state_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
- reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
- reconcile/gql_definitions/common/apps.py +5 -5
- reconcile/gql_definitions/common/aws_vpc_requests.py +5 -5
- reconcile/gql_definitions/common/aws_vpcs.py +5 -5
- reconcile/gql_definitions/common/clusters.py +5 -5
- reconcile/gql_definitions/common/clusters_minimal.py +5 -5
- reconcile/gql_definitions/common/clusters_with_dms.py +5 -5
- reconcile/gql_definitions/common/clusters_with_peering.py +5 -5
- reconcile/gql_definitions/common/github_orgs.py +5 -5
- reconcile/gql_definitions/common/jira_settings.py +5 -5
- reconcile/gql_definitions/common/jiralert_settings.py +5 -5
- reconcile/gql_definitions/common/ldap_settings.py +5 -5
- reconcile/gql_definitions/common/namespaces.py +5 -5
- reconcile/gql_definitions/common/namespaces_minimal.py +7 -5
- reconcile/gql_definitions/common/ocm_env_telemeter.py +5 -5
- reconcile/gql_definitions/common/ocm_environments.py +5 -5
- reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
- reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -5
- reconcile/gql_definitions/common/pipeline_providers.py +5 -5
- reconcile/gql_definitions/common/quay_instances.py +5 -5
- reconcile/gql_definitions/common/quay_orgs.py +5 -5
- reconcile/gql_definitions/common/reserved_networks.py +5 -5
- reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
- reconcile/gql_definitions/common/saas_files.py +5 -5
- reconcile/gql_definitions/common/saas_target_namespaces.py +5 -5
- reconcile/gql_definitions/common/saasherder_settings.py +5 -5
- reconcile/gql_definitions/common/slack_workspaces.py +5 -5
- reconcile/gql_definitions/common/smtp_client_settings.py +5 -5
- reconcile/gql_definitions/common/state_aws_account.py +5 -5
- reconcile/gql_definitions/common/users.py +5 -5
- reconcile/gql_definitions/common/users_with_paths.py +5 -5
- reconcile/gql_definitions/cost_report/app_names.py +5 -5
- reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
- reconcile/gql_definitions/cost_report/settings.py +5 -5
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +5 -5
- reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +5 -5
- reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
- reconcile/gql_definitions/email_sender/apps.py +5 -5
- reconcile/gql_definitions/email_sender/emails.py +5 -5
- reconcile/gql_definitions/email_sender/users.py +5 -5
- reconcile/gql_definitions/endpoints_discovery/apps.py +5 -5
- reconcile/gql_definitions/external_resources/aws_accounts.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_modules.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_settings.py +5 -5
- reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
- reconcile/gql_definitions/fleet_labeler/fleet_labels.py +5 -5
- reconcile/gql_definitions/fragments/aus_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_common.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
- reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
- reconcile/gql_definitions/fragments/aws_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc_request.py +5 -5
- reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
- reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
- reconcile/gql_definitions/fragments/disable.py +5 -5
- reconcile/gql_definitions/fragments/email_service.py +5 -5
- reconcile/gql_definitions/fragments/email_user.py +5 -5
- reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
- reconcile/gql_definitions/fragments/membership_source.py +5 -5
- reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
- reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
- reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
- reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
- reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
- reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_values.py +5 -5
- reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
- reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
- reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
- reconcile/gql_definitions/fragments/terraform_state.py +5 -5
- reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
- reconcile/gql_definitions/fragments/user.py +5 -5
- reconcile/gql_definitions/fragments/vault_secret.py +5 -5
- reconcile/gql_definitions/gcp/gcp_docker_repos.py +5 -5
- reconcile/gql_definitions/gcp/gcp_projects.py +5 -5
- reconcile/gql_definitions/gitlab_members/gitlab_instances.py +5 -5
- reconcile/gql_definitions/gitlab_members/permissions.py +5 -5
- reconcile/gql_definitions/glitchtip/glitchtip_instance.py +5 -5
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +5 -5
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +5 -5
- reconcile/gql_definitions/integrations/integrations.py +5 -5
- reconcile/gql_definitions/introspection.json +231 -0
- reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +5 -5
- reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +5 -5
- reconcile/gql_definitions/jira/jira_servers.py +5 -5
- reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +5 -5
- reconcile/gql_definitions/jumphosts/jumphosts.py +5 -5
- reconcile/gql_definitions/ldap_groups/roles.py +5 -5
- reconcile/gql_definitions/ldap_groups/settings.py +5 -5
- reconcile/gql_definitions/maintenance/maintenances.py +5 -5
- reconcile/gql_definitions/membershipsources/roles.py +5 -5
- reconcile/gql_definitions/ocm_labels/clusters.py +5 -5
- reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
- reconcile/gql_definitions/openshift_cluster_bots/clusters.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_roles.py +5 -5
- reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +5 -5
- reconcile/gql_definitions/quay_membership/quay_membership.py +5 -5
- reconcile/gql_definitions/rhcs/certs.py +24 -79
- reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +42 -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 +5 -5
- reconcile/gql_definitions/terraform_repo/terraform_repo.py +5 -5
- reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +5 -5
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +5 -5
- reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +5 -5
- reconcile/gql_definitions/vault_instances/vault_instances.py +5 -5
- reconcile/gql_definitions/vault_policies/vault_policies.py +5 -5
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +5 -5
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
- reconcile/integrations_manager.py +3 -3
- reconcile/jenkins_worker_fleets.py +9 -8
- reconcile/jira_permissions_validator.py +2 -2
- reconcile/ldap_groups/integration.py +1 -1
- reconcile/ocm/types.py +35 -57
- reconcile/ocm_aws_infrastructure_access.py +1 -1
- reconcile/ocm_clusters.py +4 -4
- reconcile/ocm_labels/integration.py +3 -2
- reconcile/ocm_machine_pools.py +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 +27 -29
- reconcile/openshift_rolebindings.py +7 -11
- reconcile/openshift_saas_deploy.py +4 -5
- reconcile/openshift_saas_deploy_change_tester.py +9 -7
- reconcile/openshift_serviceaccount_tokens.py +2 -2
- reconcile/openshift_upgrade_watcher.py +1 -1
- reconcile/oum/labelset.py +5 -3
- reconcile/oum/models.py +1 -4
- reconcile/prometheus_rules_tester/integration.py +3 -3
- reconcile/quay_mirror.py +1 -1
- reconcile/queries.py +6 -0
- reconcile/rhidp/common.py +3 -5
- reconcile/rhidp/sso_client/base.py +16 -5
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
- reconcile/skupper_network/integration.py +2 -2
- reconcile/slack_usergroups.py +31 -11
- reconcile/status_board.py +6 -6
- reconcile/statuspage/atlassian.py +7 -7
- reconcile/statuspage/page.py +4 -9
- reconcile/templating/lib/rendering.py +3 -3
- reconcile/templating/renderer.py +2 -2
- reconcile/terraform_cloudflare_dns.py +3 -3
- reconcile/terraform_cloudflare_resources.py +5 -5
- reconcile/terraform_cloudflare_users.py +3 -2
- reconcile/terraform_init/integration.py +2 -2
- reconcile/terraform_repo.py +16 -12
- reconcile/terraform_resources.py +6 -6
- reconcile/terraform_tgw_attachments.py +20 -18
- reconcile/terraform_vpc_resources/integration.py +3 -1
- reconcile/typed_queries/cost_report/app_names.py +1 -1
- reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
- reconcile/typed_queries/saas_files.py +11 -11
- reconcile/typed_queries/status_board.py +2 -2
- reconcile/unleash_feature_toggles/integration.py +4 -2
- reconcile/utils/acs/base.py +6 -3
- reconcile/utils/acs/policies.py +2 -2
- reconcile/utils/aws_api.py +51 -20
- reconcile/utils/aws_api_typed/organization.py +4 -2
- reconcile/utils/binary.py +7 -12
- reconcile/utils/deadmanssnitch_api.py +1 -1
- reconcile/utils/early_exit_cache.py +8 -10
- reconcile/utils/gitlab_api.py +7 -5
- reconcile/utils/glitchtip/client.py +6 -2
- reconcile/utils/glitchtip/models.py +25 -28
- reconcile/utils/gql.py +4 -7
- reconcile/utils/instrumented_wrappers.py +1 -1
- reconcile/utils/internal_groups/client.py +2 -2
- reconcile/utils/internal_groups/models.py +8 -17
- reconcile/utils/jinja2/utils.py +2 -5
- reconcile/utils/jobcontroller/controller.py +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 +1 -1
- reconcile/utils/merge_request_manager/parser.py +4 -4
- reconcile/utils/metrics.py +5 -5
- reconcile/utils/models.py +304 -82
- reconcile/utils/mr/notificator.py +1 -1
- reconcile/utils/mr/user_maintenance.py +3 -2
- reconcile/utils/oc.py +246 -201
- reconcile/utils/ocm/addons.py +0 -1
- reconcile/utils/ocm/base.py +17 -20
- reconcile/utils/ocm/cluster_groups.py +1 -1
- reconcile/utils/ocm/identity_providers.py +2 -2
- reconcile/utils/ocm/labels.py +1 -1
- reconcile/utils/ocm/products.py +8 -8
- reconcile/utils/ocm/service_log.py +1 -1
- reconcile/utils/ocm/sre_capability_labels.py +20 -13
- reconcile/utils/openshift_resource.py +5 -0
- reconcile/utils/pagerduty_api.py +5 -2
- reconcile/utils/promotion_state.py +6 -11
- reconcile/utils/raw_github_api.py +1 -1
- reconcile/utils/rhcsv2_certs.py +1 -4
- reconcile/utils/rosa/session.py +16 -0
- reconcile/utils/runtime/integration.py +1 -1
- reconcile/utils/saasherder/interfaces.py +13 -20
- reconcile/utils/saasherder/models.py +23 -20
- reconcile/utils/saasherder/saasherder.py +46 -24
- reconcile/utils/slack_api.py +2 -2
- reconcile/utils/structs.py +1 -1
- reconcile/utils/terraform_client.py +1 -1
- reconcile/utils/terrascript_aws_client.py +47 -43
- reconcile/utils/unleash/server.py +2 -8
- reconcile/utils/vault.py +5 -12
- reconcile/utils/vcs.py +8 -8
- reconcile/vault_replication.py +1 -1
- tools/cli_commands/cost_report/cost_management_api.py +3 -3
- tools/cli_commands/cost_report/view.py +7 -6
- tools/cli_commands/erv2.py +1 -1
- tools/qontract_cli.py +6 -5
- tools/template_validation.py +3 -1
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev427.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev394.dist-info → qontract_reconcile-0.10.2.dev427.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
|
@@ -16,7 +16,7 @@ from typing import (
|
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
from croniter import croniter
|
|
19
|
-
from pydantic import BaseModel
|
|
19
|
+
from pydantic import BaseModel
|
|
20
20
|
from requests.exceptions import HTTPError
|
|
21
21
|
from semver import VersionInfo
|
|
22
22
|
|
|
@@ -46,7 +46,7 @@ from reconcile.aus.models import (
|
|
|
46
46
|
OrganizationUpgradeSpec,
|
|
47
47
|
Sector,
|
|
48
48
|
)
|
|
49
|
-
from reconcile.aus.version_gates import HANDLERS
|
|
49
|
+
from reconcile.aus.version_gates import HANDLERS, sts_version_gate_handler
|
|
50
50
|
from reconcile.gql_definitions.advanced_upgrade_service.aus_organization import (
|
|
51
51
|
query as aus_organizations_query,
|
|
52
52
|
)
|
|
@@ -79,7 +79,9 @@ from reconcile.utils.datetime_util import (
|
|
|
79
79
|
from reconcile.utils.defer import defer
|
|
80
80
|
from reconcile.utils.disabled_integrations import integration_is_enabled
|
|
81
81
|
from reconcile.utils.filtering import remove_none_values_from_dict
|
|
82
|
+
from reconcile.utils.jobcontroller.controller import build_job_controller
|
|
82
83
|
from reconcile.utils.ocm.addons import AddonService, AddonServiceV1, AddonServiceV2
|
|
84
|
+
from reconcile.utils.ocm.base import LabelContainer
|
|
83
85
|
from reconcile.utils.ocm.clusters import (
|
|
84
86
|
OCMCluster,
|
|
85
87
|
)
|
|
@@ -102,6 +104,7 @@ from reconcile.utils.runtime.integration import (
|
|
|
102
104
|
PydanticRunParams,
|
|
103
105
|
QontractReconcileIntegration,
|
|
104
106
|
)
|
|
107
|
+
from reconcile.utils.secret_reader import SecretReaderBase
|
|
105
108
|
from reconcile.utils.semver_helper import (
|
|
106
109
|
get_version_prefix,
|
|
107
110
|
parse_semver,
|
|
@@ -110,6 +113,18 @@ from reconcile.utils.semver_helper import (
|
|
|
110
113
|
from reconcile.utils.state import init_state
|
|
111
114
|
|
|
112
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
|
|
113
128
|
|
|
114
129
|
|
|
115
130
|
class AdvancedUpgradeSchedulerBaseIntegrationParams(PydanticRunParams):
|
|
@@ -117,6 +132,7 @@ class AdvancedUpgradeSchedulerBaseIntegrationParams(PydanticRunParams):
|
|
|
117
132
|
ocm_organization_ids: set[str] | None = None
|
|
118
133
|
excluded_ocm_organization_ids: set[str] | None = None
|
|
119
134
|
ignore_sts_clusters: bool = False
|
|
135
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None
|
|
120
136
|
|
|
121
137
|
|
|
122
138
|
class ReconcileError(Exception):
|
|
@@ -404,15 +420,20 @@ class AbstractUpgradePolicy(ABC, BaseModel):
|
|
|
404
420
|
|
|
405
421
|
cluster: OCMCluster
|
|
406
422
|
|
|
407
|
-
id: str | None
|
|
408
|
-
next_run: str | None
|
|
409
|
-
schedule: str | None
|
|
423
|
+
id: str | None = None
|
|
424
|
+
next_run: str | None = None
|
|
425
|
+
schedule: str | None = None
|
|
410
426
|
schedule_type: str
|
|
411
427
|
version: str
|
|
412
|
-
state: str | None
|
|
428
|
+
state: str | None = None
|
|
413
429
|
|
|
414
430
|
@abstractmethod
|
|
415
|
-
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:
|
|
416
437
|
pass
|
|
417
438
|
|
|
418
439
|
@abstractmethod
|
|
@@ -430,7 +451,7 @@ def addon_upgrade_policy_soonest_next_run() -> str:
|
|
|
430
451
|
return to_utc_seconds_iso_format(next_run)
|
|
431
452
|
|
|
432
453
|
|
|
433
|
-
class AddonUpgradePolicy(AbstractUpgradePolicy):
|
|
454
|
+
class AddonUpgradePolicy(AbstractUpgradePolicy, arbitrary_types_allowed=True):
|
|
434
455
|
"""Class to create and delete Addon upgrade policies in OCM"""
|
|
435
456
|
|
|
436
457
|
addon_id: str
|
|
@@ -439,7 +460,12 @@ class AddonUpgradePolicy(AbstractUpgradePolicy):
|
|
|
439
460
|
class Config:
|
|
440
461
|
arbitrary_types_allowed = True
|
|
441
462
|
|
|
442
|
-
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:
|
|
443
469
|
self.addon_service.create_addon_upgrade_policy(
|
|
444
470
|
ocm_api=ocm_api,
|
|
445
471
|
cluster_id=self.cluster.id,
|
|
@@ -472,14 +498,63 @@ class AddonUpgradePolicy(AbstractUpgradePolicy):
|
|
|
472
498
|
class ClusterUpgradePolicy(AbstractUpgradePolicy):
|
|
473
499
|
"""Class to create ClusterUpgradePolicies in OCM"""
|
|
474
500
|
|
|
475
|
-
|
|
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:
|
|
476
510
|
policy = {
|
|
477
511
|
"version": self.version,
|
|
478
512
|
"schedule_type": "manual",
|
|
479
513
|
"next_run": self.next_run,
|
|
480
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
|
+
)
|
|
481
544
|
create_upgrade_policy(ocm_api, self.cluster.id, policy)
|
|
482
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
|
+
|
|
483
558
|
def delete(self, ocm_api: OCMBaseClient) -> None:
|
|
484
559
|
raise NotImplementedError("ClusterUpgradePolicy.delete() not implemented")
|
|
485
560
|
|
|
@@ -497,7 +572,12 @@ class ClusterUpgradePolicy(AbstractUpgradePolicy):
|
|
|
497
572
|
class ControlPlaneUpgradePolicy(AbstractUpgradePolicy):
|
|
498
573
|
"""Class to create and delete ControlPlanUpgradePolicies in OCM"""
|
|
499
574
|
|
|
500
|
-
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:
|
|
501
581
|
policy = {
|
|
502
582
|
"version": self.version,
|
|
503
583
|
"schedule_type": "manual",
|
|
@@ -521,10 +601,16 @@ class ControlPlaneUpgradePolicy(AbstractUpgradePolicy):
|
|
|
521
601
|
|
|
522
602
|
|
|
523
603
|
class NodePoolUpgradePolicy(AbstractUpgradePolicy):
|
|
524
|
-
node_pool: str
|
|
525
604
|
"""Class to create NodePoolUpgradePolicies in OCM"""
|
|
526
605
|
|
|
527
|
-
|
|
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:
|
|
528
614
|
policy = {
|
|
529
615
|
"version": self.version,
|
|
530
616
|
"schedule_type": "manual",
|
|
@@ -550,13 +636,19 @@ class NodePoolUpgradePolicy(AbstractUpgradePolicy):
|
|
|
550
636
|
return f"node pool upgrade policy - {remove_none_values_from_dict(details)}"
|
|
551
637
|
|
|
552
638
|
|
|
553
|
-
class UpgradePolicyHandler(BaseModel, extra=
|
|
639
|
+
class UpgradePolicyHandler(BaseModel, extra="forbid"):
|
|
554
640
|
"""Class to handle upgrade policy actions"""
|
|
555
641
|
|
|
556
642
|
action: str
|
|
557
643
|
policy: AbstractUpgradePolicy
|
|
558
644
|
|
|
559
|
-
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:
|
|
560
652
|
logging.info(f"{self.action} {self.policy.summarize()}")
|
|
561
653
|
if dry_run:
|
|
562
654
|
return
|
|
@@ -566,7 +658,7 @@ class UpgradePolicyHandler(BaseModel, extra=Extra.forbid):
|
|
|
566
658
|
elif self.action == "delete":
|
|
567
659
|
self.policy.delete(ocm_api)
|
|
568
660
|
elif self.action == "create":
|
|
569
|
-
self.policy.create(ocm_api)
|
|
661
|
+
self.policy.create(ocm_api, rosa_role_upgrade_handler_params, secret_reader)
|
|
570
662
|
|
|
571
663
|
|
|
572
664
|
def fetch_current_state(
|
|
@@ -584,6 +676,7 @@ def fetch_current_state(
|
|
|
584
676
|
)
|
|
585
677
|
current_state.extend(
|
|
586
678
|
AddonUpgradePolicy(
|
|
679
|
+
organization_id=spec.org.org_id,
|
|
587
680
|
id=addon_upgrade_policy.id,
|
|
588
681
|
addon_id=addon_spec.addon.addon.id,
|
|
589
682
|
cluster=spec.cluster,
|
|
@@ -620,6 +713,8 @@ def fetch_current_state(
|
|
|
620
713
|
for upgrade_policy in upgrade_policies:
|
|
621
714
|
policy = upgrade_policy | {
|
|
622
715
|
"cluster": spec.cluster,
|
|
716
|
+
"organization_id": spec.org.org_id,
|
|
717
|
+
"cluster_labels": spec.cluster_labels,
|
|
623
718
|
}
|
|
624
719
|
current_state.append(ClusterUpgradePolicy(**policy))
|
|
625
720
|
|
|
@@ -1018,6 +1113,8 @@ def _create_upgrade_policy(
|
|
|
1018
1113
|
)
|
|
1019
1114
|
return ClusterUpgradePolicy(
|
|
1020
1115
|
cluster=spec.cluster,
|
|
1116
|
+
organization_id=spec.org.org_id,
|
|
1117
|
+
cluster_labels=spec.cluster_labels,
|
|
1021
1118
|
version=version,
|
|
1022
1119
|
schedule_type="manual",
|
|
1023
1120
|
next_run=next_schedule,
|
|
@@ -1125,11 +1222,11 @@ def calculate_diff(
|
|
|
1125
1222
|
action="create",
|
|
1126
1223
|
policy=AddonUpgradePolicy(
|
|
1127
1224
|
action="create",
|
|
1225
|
+
organization_id=spec.org.org_id,
|
|
1128
1226
|
cluster=spec.cluster,
|
|
1129
1227
|
version=version,
|
|
1130
1228
|
schedule_type="manual",
|
|
1131
1229
|
addon_id=addon_id,
|
|
1132
|
-
upgrade_type="ADDON",
|
|
1133
1230
|
addon_service=addon_service,
|
|
1134
1231
|
),
|
|
1135
1232
|
)
|
|
@@ -1190,6 +1287,8 @@ def act(
|
|
|
1190
1287
|
dry_run: bool,
|
|
1191
1288
|
diffs: list[UpgradePolicyHandler],
|
|
1192
1289
|
ocm_api: OCMBaseClient,
|
|
1290
|
+
rosa_role_upgrade_handler_params: RosaRoleUpgradeHandlerParams | None = None,
|
|
1291
|
+
secret_reader: SecretReaderBase | None = None,
|
|
1193
1292
|
addon_id: str | None = None,
|
|
1194
1293
|
) -> None:
|
|
1195
1294
|
diffs.sort(key=sort_diffs)
|
|
@@ -1202,7 +1301,7 @@ def act(
|
|
|
1202
1301
|
):
|
|
1203
1302
|
continue
|
|
1204
1303
|
try:
|
|
1205
|
-
diff.act(dry_run, ocm_api)
|
|
1304
|
+
diff.act(dry_run, ocm_api, rosa_role_upgrade_handler_params, secret_reader)
|
|
1206
1305
|
except HTTPError as e:
|
|
1207
1306
|
logging.error(f"{policy.cluster.name}: {e}: {e.response.text}")
|
|
1208
1307
|
|
|
@@ -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
|
|
@@ -6,6 +6,7 @@ from reconcile.utils.ocm.base import OCMCluster, OCMVersionGate
|
|
|
6
6
|
from reconcile.utils.ocm_base_client import OCMBaseClient
|
|
7
7
|
from reconcile.utils.rosa.rosa_cli import RosaCliError
|
|
8
8
|
from reconcile.utils.rosa.session import RosaSession
|
|
9
|
+
from reconcile.utils.semver_helper import get_version_prefix
|
|
9
10
|
|
|
10
11
|
GATE_LABEL = "api.openshift.com/gate-sts"
|
|
11
12
|
|
|
@@ -63,6 +64,24 @@ class STSGateHandler(GateHandler):
|
|
|
63
64
|
)
|
|
64
65
|
return False
|
|
65
66
|
|
|
67
|
+
return self.upgrade_rosa_roles(
|
|
68
|
+
cluster=cluster,
|
|
69
|
+
version_raw_id_prefix=gate.version_raw_id_prefix,
|
|
70
|
+
dry_run=dry_run,
|
|
71
|
+
ocm_api=ocm_api,
|
|
72
|
+
ocm_org_id=ocm_org_id,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
def upgrade_rosa_roles(
|
|
76
|
+
self,
|
|
77
|
+
cluster: OCMCluster,
|
|
78
|
+
version_raw_id_prefix: str,
|
|
79
|
+
dry_run: bool,
|
|
80
|
+
ocm_api: OCMBaseClient,
|
|
81
|
+
ocm_org_id: str,
|
|
82
|
+
) -> bool:
|
|
83
|
+
if not cluster.aws:
|
|
84
|
+
return False
|
|
66
85
|
rosa = RosaSession(
|
|
67
86
|
aws_account_id=cluster.aws.aws_account_id,
|
|
68
87
|
aws_region=cluster.region.id,
|
|
@@ -83,7 +102,7 @@ class STSGateHandler(GateHandler):
|
|
|
83
102
|
)
|
|
84
103
|
rosa.upgrade_account_roles(
|
|
85
104
|
role_prefix=account_role_prefix,
|
|
86
|
-
minor_version=
|
|
105
|
+
minor_version=version_raw_id_prefix,
|
|
87
106
|
channel_group=cluster.version.channel_group,
|
|
88
107
|
dry_run=dry_run,
|
|
89
108
|
)
|
|
@@ -98,3 +117,37 @@ class STSGateHandler(GateHandler):
|
|
|
98
117
|
e.write_logs_to_logger(logging.error)
|
|
99
118
|
return False
|
|
100
119
|
return True
|
|
120
|
+
|
|
121
|
+
def upgrade_rosa_roles_v2(
|
|
122
|
+
self,
|
|
123
|
+
cluster: OCMCluster,
|
|
124
|
+
upgrade_version: str,
|
|
125
|
+
dry_run: bool,
|
|
126
|
+
ocm_api: OCMBaseClient,
|
|
127
|
+
ocm_org_id: str,
|
|
128
|
+
) -> bool:
|
|
129
|
+
if not cluster.aws:
|
|
130
|
+
return False
|
|
131
|
+
rosa = RosaSession(
|
|
132
|
+
aws_account_id=cluster.aws.aws_account_id,
|
|
133
|
+
aws_region=cluster.region.id,
|
|
134
|
+
aws_iam_role=self.aws_iam_role,
|
|
135
|
+
ocm_org_id=ocm_org_id,
|
|
136
|
+
ocm_api=ocm_api,
|
|
137
|
+
job_controller=self.job_controller,
|
|
138
|
+
image=self.rosa_job_image,
|
|
139
|
+
service_account=self.rosa_job_service_account,
|
|
140
|
+
)
|
|
141
|
+
policy_version = get_version_prefix(upgrade_version)
|
|
142
|
+
try:
|
|
143
|
+
rosa.upgrade_rosa_roles(
|
|
144
|
+
cluster_name=cluster.name,
|
|
145
|
+
upgrade_version=upgrade_version,
|
|
146
|
+
policy_version=policy_version,
|
|
147
|
+
dry_run=dry_run,
|
|
148
|
+
)
|
|
149
|
+
except RosaCliError as e:
|
|
150
|
+
logging.error(f"Failed to upgrade roles for cluster {cluster.name}: {e}")
|
|
151
|
+
e.write_logs_to_logger(logging.error)
|
|
152
|
+
return False
|
|
153
|
+
return True
|