qontract-reconcile 0.10.2.dev361__py3-none-any.whl → 0.10.2.dev474__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/METADATA +14 -13
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/RECORD +371 -364
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/WHEEL +1 -1
- reconcile/acs_rbac.py +2 -2
- reconcile/aus/advanced_upgrade_service.py +18 -12
- reconcile/aus/aus_sts_gate_handler.py +59 -0
- reconcile/aus/base.py +137 -34
- reconcile/aus/cluster_version_data.py +15 -5
- reconcile/aus/models.py +3 -1
- reconcile/aus/ocm_addons_upgrade_scheduler_org.py +1 -0
- reconcile/aus/ocm_upgrade_scheduler.py +8 -1
- reconcile/aus/ocm_upgrade_scheduler_org.py +20 -5
- reconcile/aus/version_gate_approver.py +1 -16
- reconcile/aus/version_gates/sts_version_gate_handler.py +5 -72
- reconcile/automated_actions/config/integration.py +16 -4
- reconcile/aws_account_manager/integration.py +21 -9
- reconcile/aws_account_manager/reconciler.py +3 -3
- reconcile/aws_account_manager/utils.py +1 -1
- reconcile/aws_ami_cleanup/integration.py +8 -12
- reconcile/aws_ami_share.py +69 -62
- reconcile/aws_cloudwatch_log_retention/integration.py +155 -126
- reconcile/aws_ecr_image_pull_secrets.py +1 -1
- reconcile/aws_iam_keys.py +1 -0
- reconcile/aws_saml_idp/integration.py +12 -4
- reconcile/aws_saml_roles/integration.py +30 -23
- reconcile/aws_version_sync/integration.py +6 -12
- reconcile/change_owners/README.md +1 -1
- reconcile/change_owners/bundle.py +3 -3
- reconcile/change_owners/change_log_tracking.py +3 -2
- reconcile/change_owners/change_owners.py +108 -42
- reconcile/change_owners/decision.py +1 -1
- reconcile/change_owners/diff.py +0 -2
- reconcile/checkpoint.py +11 -3
- reconcile/cli.py +94 -11
- reconcile/dashdotdb_dora.py +5 -12
- reconcile/dashdotdb_slo.py +1 -1
- reconcile/database_access_manager.py +123 -117
- reconcile/dynatrace_token_provider/integration.py +1 -1
- reconcile/endpoints_discovery/integration.py +4 -1
- reconcile/endpoints_discovery/merge_request.py +1 -1
- reconcile/endpoints_discovery/merge_request_manager.py +8 -8
- reconcile/external_resources/factories.py +4 -6
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +8 -6
- reconcile/external_resources/meta.py +0 -1
- reconcile/external_resources/metrics.py +1 -1
- reconcile/external_resources/model.py +19 -15
- reconcile/external_resources/reconciler.py +7 -4
- reconcile/external_resources/secrets_sync.py +6 -10
- reconcile/external_resources/state.py +26 -16
- reconcile/fleet_labeler/integration.py +1 -1
- reconcile/gabi_authorized_users.py +5 -2
- reconcile/gcp_image_mirror.py +2 -2
- reconcile/github_org.py +1 -1
- reconcile/github_owners.py +4 -0
- reconcile/gitlab_housekeeping.py +13 -15
- reconcile/gitlab_members.py +6 -12
- reconcile/gitlab_owners.py +15 -11
- reconcile/gitlab_permissions.py +8 -12
- reconcile/glitchtip_project_alerts/integration.py +3 -1
- reconcile/gql_definitions/acs/acs_instances.py +5 -5
- reconcile/gql_definitions/acs/acs_policies.py +5 -5
- reconcile/gql_definitions/acs/acs_rbac.py +5 -5
- reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +5 -5
- reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +5 -5
- reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +5 -5
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
- reconcile/gql_definitions/automated_actions/instance.py +46 -7
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +14 -5
- reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +15 -5
- reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +27 -66
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +15 -5
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +15 -5
- reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
- reconcile/gql_definitions/aws_version_sync/clusters.py +5 -5
- reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
- reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
- reconcile/gql_definitions/change_owners/queries/self_service_roles.py +5 -5
- reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +5 -5
- reconcile/gql_definitions/common/alerting_services_settings.py +5 -5
- reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
- reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
- reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_roles.py +5 -5
- reconcile/gql_definitions/common/app_interface_state_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
- reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
- reconcile/gql_definitions/common/apps.py +5 -5
- reconcile/gql_definitions/common/aws_vpc_requests.py +18 -5
- reconcile/gql_definitions/common/aws_vpcs.py +5 -5
- reconcile/gql_definitions/common/clusters.py +7 -5
- reconcile/gql_definitions/common/clusters_minimal.py +5 -5
- reconcile/gql_definitions/common/clusters_with_dms.py +5 -5
- reconcile/gql_definitions/common/clusters_with_peering.py +5 -5
- reconcile/gql_definitions/common/github_orgs.py +5 -5
- reconcile/gql_definitions/common/jira_settings.py +5 -5
- reconcile/gql_definitions/common/jiralert_settings.py +5 -5
- reconcile/gql_definitions/common/ldap_settings.py +5 -5
- reconcile/gql_definitions/common/namespaces.py +5 -5
- reconcile/gql_definitions/common/namespaces_minimal.py +7 -5
- reconcile/gql_definitions/common/ocm_env_telemeter.py +5 -5
- reconcile/gql_definitions/common/ocm_environments.py +5 -5
- reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
- reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -5
- reconcile/gql_definitions/common/pipeline_providers.py +5 -5
- reconcile/gql_definitions/common/quay_instances.py +5 -5
- reconcile/gql_definitions/common/quay_orgs.py +5 -5
- reconcile/gql_definitions/common/reserved_networks.py +5 -5
- reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
- reconcile/gql_definitions/common/saas_files.py +5 -5
- reconcile/gql_definitions/common/saas_target_namespaces.py +5 -5
- reconcile/gql_definitions/common/saasherder_settings.py +5 -5
- reconcile/gql_definitions/common/slack_workspaces.py +5 -5
- reconcile/gql_definitions/common/smtp_client_settings.py +5 -5
- reconcile/gql_definitions/common/state_aws_account.py +5 -5
- reconcile/gql_definitions/common/users.py +5 -5
- reconcile/gql_definitions/common/users_with_paths.py +5 -5
- reconcile/gql_definitions/cost_report/app_names.py +5 -5
- reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
- reconcile/gql_definitions/cost_report/settings.py +5 -5
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +5 -5
- reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +5 -5
- reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
- reconcile/gql_definitions/email_sender/apps.py +5 -5
- reconcile/gql_definitions/email_sender/emails.py +5 -5
- reconcile/gql_definitions/email_sender/users.py +5 -5
- reconcile/gql_definitions/endpoints_discovery/apps.py +5 -5
- reconcile/gql_definitions/external_resources/aws_accounts.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_modules.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py +38 -7
- reconcile/gql_definitions/external_resources/external_resources_settings.py +5 -5
- reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
- reconcile/gql_definitions/fleet_labeler/fleet_labels.py +5 -5
- reconcile/gql_definitions/fragments/aus_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_common.py +7 -5
- reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
- reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
- reconcile/gql_definitions/fragments/aws_organization.py +33 -0
- reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc_request.py +12 -5
- reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
- reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
- reconcile/gql_definitions/fragments/disable.py +5 -5
- reconcile/gql_definitions/fragments/email_service.py +5 -5
- reconcile/gql_definitions/fragments/email_user.py +5 -5
- reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
- reconcile/gql_definitions/fragments/membership_source.py +5 -5
- reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
- reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
- reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
- reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
- reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
- reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_values.py +5 -5
- reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
- reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
- reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
- reconcile/gql_definitions/fragments/terraform_state.py +5 -5
- reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
- reconcile/gql_definitions/fragments/user.py +5 -5
- reconcile/gql_definitions/fragments/vault_secret.py +5 -5
- reconcile/gql_definitions/gcp/gcp_docker_repos.py +5 -5
- reconcile/gql_definitions/gcp/gcp_projects.py +5 -5
- reconcile/gql_definitions/gitlab_members/gitlab_instances.py +5 -5
- reconcile/gql_definitions/gitlab_members/permissions.py +5 -5
- reconcile/gql_definitions/glitchtip/glitchtip_instance.py +5 -5
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +5 -5
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +5 -5
- reconcile/gql_definitions/integrations/integrations.py +5 -5
- reconcile/gql_definitions/introspection.json +775 -136
- reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +5 -5
- reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +5 -5
- reconcile/gql_definitions/jira/jira_servers.py +5 -5
- reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +9 -5
- reconcile/gql_definitions/jumphosts/jumphosts.py +5 -5
- reconcile/gql_definitions/ldap_groups/roles.py +5 -5
- reconcile/gql_definitions/ldap_groups/settings.py +5 -5
- reconcile/gql_definitions/maintenance/maintenances.py +5 -5
- reconcile/gql_definitions/membershipsources/roles.py +5 -5
- reconcile/gql_definitions/ocm_labels/clusters.py +5 -5
- reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
- reconcile/gql_definitions/openshift_cluster_bots/clusters.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_roles.py +5 -5
- reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +5 -5
- reconcile/gql_definitions/quay_membership/quay_membership.py +5 -5
- reconcile/gql_definitions/rhcs/certs.py +25 -79
- reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +43 -0
- reconcile/gql_definitions/rhidp/organizations.py +5 -5
- reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
- reconcile/gql_definitions/service_dependencies/service_dependencies.py +5 -5
- reconcile/gql_definitions/sharding/aws_accounts.py +5 -5
- reconcile/gql_definitions/sharding/ocm_organization.py +5 -5
- reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
- reconcile/gql_definitions/skupper_network/skupper_networks.py +5 -5
- reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
- reconcile/gql_definitions/slack_usergroups/permissions.py +5 -5
- reconcile/gql_definitions/slack_usergroups/users.py +5 -5
- reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
- reconcile/gql_definitions/status_board/status_board.py +5 -5
- reconcile/gql_definitions/statuspage/statuspages.py +5 -5
- reconcile/gql_definitions/templating/template_collection.py +5 -5
- reconcile/gql_definitions/templating/templates.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +5 -5
- reconcile/gql_definitions/terraform_init/aws_accounts.py +19 -5
- reconcile/gql_definitions/terraform_repo/terraform_repo.py +5 -5
- reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +37 -7
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +15 -5
- reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +5 -5
- reconcile/gql_definitions/vault_instances/vault_instances.py +5 -5
- reconcile/gql_definitions/vault_policies/vault_policies.py +5 -5
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +8 -5
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +6 -5
- reconcile/integrations_manager.py +3 -3
- reconcile/jenkins_worker_fleets.py +10 -8
- reconcile/jira_permissions_validator.py +237 -122
- reconcile/ldap_groups/integration.py +1 -1
- reconcile/ocm/types.py +35 -57
- reconcile/ocm_aws_infrastructure_access.py +1 -1
- reconcile/ocm_clusters.py +4 -4
- reconcile/ocm_labels/integration.py +3 -2
- reconcile/ocm_machine_pools.py +33 -27
- reconcile/openshift_base.py +113 -4
- reconcile/openshift_cluster_bots.py +1 -1
- reconcile/openshift_namespace_labels.py +1 -1
- reconcile/openshift_namespaces.py +96 -101
- reconcile/openshift_resources_base.py +6 -2
- reconcile/openshift_rhcs_certs.py +74 -37
- reconcile/openshift_rolebindings.py +7 -11
- reconcile/openshift_saas_deploy.py +4 -5
- reconcile/openshift_saas_deploy_change_tester.py +9 -7
- reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
- reconcile/openshift_serviceaccount_tokens.py +2 -2
- reconcile/openshift_upgrade_watcher.py +4 -4
- reconcile/oum/labelset.py +5 -3
- reconcile/oum/models.py +1 -4
- reconcile/prometheus_rules_tester/integration.py +3 -3
- reconcile/quay_base.py +25 -6
- reconcile/quay_membership.py +55 -29
- reconcile/quay_mirror.py +1 -1
- reconcile/quay_mirror_org.py +6 -4
- reconcile/quay_permissions.py +81 -75
- reconcile/quay_repos.py +35 -37
- reconcile/queries.py +132 -1
- reconcile/rhidp/common.py +3 -5
- reconcile/rhidp/sso_client/base.py +16 -5
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
- reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
- reconcile/skupper_network/integration.py +2 -2
- reconcile/slack_usergroups.py +35 -14
- reconcile/sql_query.py +1 -0
- reconcile/status_board.py +6 -6
- reconcile/statuspage/atlassian.py +7 -7
- reconcile/statuspage/integrations/maintenances.py +4 -3
- reconcile/statuspage/page.py +4 -9
- reconcile/statuspage/status.py +5 -8
- reconcile/templates/rosa-classic-cluster-creation.sh.j2 +1 -1
- reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +1 -1
- reconcile/templating/lib/rendering.py +3 -3
- reconcile/templating/renderer.py +2 -2
- reconcile/templating/validator.py +4 -4
- reconcile/terraform_aws_route53.py +7 -1
- reconcile/terraform_cloudflare_dns.py +3 -3
- reconcile/terraform_cloudflare_resources.py +5 -5
- reconcile/terraform_cloudflare_users.py +3 -2
- reconcile/terraform_init/integration.py +187 -23
- reconcile/terraform_repo.py +16 -12
- reconcile/terraform_resources.py +6 -6
- reconcile/terraform_tgw_attachments.py +27 -19
- reconcile/terraform_users.py +7 -0
- reconcile/terraform_vpc_peerings.py +14 -3
- reconcile/terraform_vpc_resources/integration.py +20 -8
- reconcile/terraform_vpc_resources/merge_request.py +12 -2
- reconcile/terraform_vpc_resources/merge_request_manager.py +43 -19
- reconcile/typed_queries/aws_account_tags.py +41 -0
- reconcile/typed_queries/cost_report/app_names.py +1 -1
- reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
- reconcile/typed_queries/saas_files.py +20 -15
- reconcile/typed_queries/status_board.py +2 -2
- reconcile/unleash_feature_toggles/integration.py +4 -2
- reconcile/utils/acs/base.py +6 -3
- reconcile/utils/acs/policies.py +2 -2
- reconcile/utils/aws_api.py +51 -20
- reconcile/utils/aws_api_typed/api.py +38 -9
- reconcile/utils/aws_api_typed/cloudformation.py +149 -0
- reconcile/utils/aws_api_typed/logs.py +73 -0
- reconcile/utils/aws_api_typed/organization.py +4 -2
- reconcile/utils/binary.py +7 -12
- reconcile/utils/datetime_util.py +67 -0
- reconcile/utils/deadmanssnitch_api.py +1 -1
- reconcile/utils/differ.py +2 -3
- reconcile/utils/early_exit_cache.py +11 -12
- reconcile/utils/environ.py +5 -0
- reconcile/utils/expiration.py +7 -3
- reconcile/utils/external_resource_spec.py +2 -0
- reconcile/utils/filtering.py +1 -1
- reconcile/utils/gitlab_api.py +19 -5
- reconcile/utils/glitchtip/client.py +6 -2
- reconcile/utils/glitchtip/models.py +25 -28
- reconcile/utils/gql.py +4 -7
- reconcile/utils/helpers.py +1 -1
- reconcile/utils/instrumented_wrappers.py +1 -1
- reconcile/utils/internal_groups/client.py +2 -2
- reconcile/utils/internal_groups/models.py +8 -17
- reconcile/utils/jinja2/utils.py +6 -101
- reconcile/utils/jira_client.py +82 -63
- reconcile/utils/jjb_client.py +26 -13
- reconcile/utils/jobcontroller/controller.py +2 -2
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/json.py +43 -1
- reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
- reconcile/utils/membershipsources/models.py +16 -23
- reconcile/utils/membershipsources/resolver.py +4 -2
- reconcile/utils/merge_request_manager/merge_request_manager.py +4 -4
- reconcile/utils/merge_request_manager/parser.py +6 -6
- reconcile/utils/metrics.py +5 -5
- reconcile/utils/models.py +304 -82
- reconcile/utils/mr/app_interface_reporter.py +2 -2
- reconcile/utils/mr/notificator.py +3 -3
- reconcile/utils/mr/update_access_report_base.py +3 -4
- reconcile/utils/mr/user_maintenance.py +3 -2
- reconcile/utils/oc.py +252 -201
- reconcile/utils/oc_filters.py +3 -3
- reconcile/utils/ocm/addons.py +0 -1
- reconcile/utils/ocm/base.py +17 -20
- reconcile/utils/ocm/cluster_groups.py +1 -1
- reconcile/utils/ocm/identity_providers.py +2 -2
- reconcile/utils/ocm/labels.py +1 -1
- reconcile/utils/ocm/products.py +8 -8
- reconcile/utils/ocm/search_filters.py +3 -6
- reconcile/utils/ocm/service_log.py +4 -6
- reconcile/utils/ocm/sre_capability_labels.py +20 -13
- reconcile/utils/openshift_resource.py +8 -3
- reconcile/utils/pagerduty_api.py +10 -7
- reconcile/utils/promotion_state.py +6 -11
- reconcile/utils/quay_api.py +74 -87
- reconcile/utils/raw_github_api.py +1 -1
- reconcile/utils/rhcsv2_certs.py +86 -23
- reconcile/utils/rosa/session.py +16 -0
- reconcile/utils/runtime/integration.py +2 -3
- reconcile/utils/runtime/runner.py +2 -2
- reconcile/utils/saasherder/interfaces.py +13 -20
- reconcile/utils/saasherder/models.py +23 -20
- reconcile/utils/saasherder/saasherder.py +50 -27
- reconcile/utils/slack_api.py +2 -2
- reconcile/utils/sloth.py +171 -2
- reconcile/utils/structs.py +1 -1
- reconcile/utils/terraform_client.py +5 -4
- reconcile/utils/terrascript_aws_client.py +274 -124
- reconcile/utils/unleash/server.py +2 -8
- reconcile/utils/vault.py +5 -12
- reconcile/utils/vcs.py +8 -8
- reconcile/vault_replication.py +107 -42
- reconcile/vpc_peerings_validator.py +13 -0
- tools/app_interface_reporter.py +4 -4
- tools/cli_commands/cost_report/cost_management_api.py +3 -3
- tools/cli_commands/cost_report/view.py +7 -6
- tools/cli_commands/erv2.py +1 -1
- tools/qontract_cli.py +28 -17
- tools/template_validation.py +3 -1
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/entry_points.txt +0 -0
|
@@ -806,7 +806,11 @@ def fetch_data(
|
|
|
806
806
|
init_api_resources=init_api_resources,
|
|
807
807
|
)
|
|
808
808
|
state_specs = ob.init_specs_to_fetch(
|
|
809
|
-
ri,
|
|
809
|
+
ri,
|
|
810
|
+
oc_map,
|
|
811
|
+
namespaces=namespaces,
|
|
812
|
+
override_managed_types=overrides,
|
|
813
|
+
cluster_scope_resource_validation=True,
|
|
810
814
|
)
|
|
811
815
|
threaded.run(fetch_states, state_specs, thread_pool_size, ri=ri, settings=settings)
|
|
812
816
|
|
|
@@ -861,7 +865,7 @@ def canonicalize_namespaces(
|
|
|
861
865
|
elif providers[0] == "route":
|
|
862
866
|
override = ["Route"]
|
|
863
867
|
elif providers[0] == "prometheus-rule":
|
|
864
|
-
override = ["PrometheusRule"]
|
|
868
|
+
override = ["PrometheusRule.monitoring.coreos.com"]
|
|
865
869
|
|
|
866
870
|
namespace_info["openshiftResources"] = ors
|
|
867
871
|
canonicalized_namespaces.append(namespace_info)
|
|
@@ -2,7 +2,7 @@ import logging
|
|
|
2
2
|
import sys
|
|
3
3
|
import time
|
|
4
4
|
from collections.abc import Callable, Iterable, Mapping
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import Any
|
|
6
6
|
|
|
7
7
|
import reconcile.openshift_base as ob
|
|
8
8
|
import reconcile.openshift_resources_base as orb
|
|
@@ -10,8 +10,8 @@ from reconcile.gql_definitions.common.rhcs_provider_settings import (
|
|
|
10
10
|
RhcsProviderSettingsV1,
|
|
11
11
|
)
|
|
12
12
|
from reconcile.gql_definitions.rhcs.certs import (
|
|
13
|
-
NamespaceOpenshiftResourceRhcsCertV1,
|
|
14
13
|
NamespaceV1,
|
|
14
|
+
OpenshiftResourceRhcsCert,
|
|
15
15
|
)
|
|
16
16
|
from reconcile.gql_definitions.rhcs.certs import (
|
|
17
17
|
query as rhcs_certs_query,
|
|
@@ -32,7 +32,12 @@ from reconcile.utils.openshift_resource import (
|
|
|
32
32
|
ResourceInventory,
|
|
33
33
|
base64_encode_secret_field_value,
|
|
34
34
|
)
|
|
35
|
-
from reconcile.utils.rhcsv2_certs import
|
|
35
|
+
from reconcile.utils.rhcsv2_certs import (
|
|
36
|
+
CertificateFormat,
|
|
37
|
+
RhcsV2CertPem,
|
|
38
|
+
RhcsV2CertPkcs12,
|
|
39
|
+
generate_cert,
|
|
40
|
+
)
|
|
36
41
|
from reconcile.utils.runtime.integration import DesiredStateShardConfig
|
|
37
42
|
from reconcile.utils.secret_reader import create_secret_reader
|
|
38
43
|
from reconcile.utils.semver_helper import make_semver
|
|
@@ -40,7 +45,6 @@ from reconcile.utils.vault import SecretNotFoundError, VaultClient
|
|
|
40
45
|
|
|
41
46
|
QONTRACT_INTEGRATION = "openshift-rhcs-certs"
|
|
42
47
|
QONTRACT_INTEGRATION_VERSION = make_semver(1, 9, 3)
|
|
43
|
-
PROVIDERS = ["rhcs-cert"]
|
|
44
48
|
|
|
45
49
|
|
|
46
50
|
def desired_state_shard_config() -> DesiredStateShardConfig:
|
|
@@ -67,8 +71,29 @@ class OpenshiftRhcsCertExpiration(GaugeMetric):
|
|
|
67
71
|
return "qontract_reconcile_rhcs_cert_expiration_timestamp"
|
|
68
72
|
|
|
69
73
|
|
|
70
|
-
def
|
|
71
|
-
|
|
74
|
+
def _generate_placeholder_cert(
|
|
75
|
+
cert_format: CertificateFormat,
|
|
76
|
+
) -> RhcsV2CertPem | RhcsV2CertPkcs12:
|
|
77
|
+
match cert_format:
|
|
78
|
+
case CertificateFormat.PKCS12:
|
|
79
|
+
return RhcsV2CertPkcs12(
|
|
80
|
+
pkcs12_keystore="PLACEHOLDER_KEYSTORE",
|
|
81
|
+
pkcs12_truststore="PLACEHOLDER_TRUSTSTORE",
|
|
82
|
+
expiration_timestamp=int(time.time()),
|
|
83
|
+
)
|
|
84
|
+
case CertificateFormat.PEM:
|
|
85
|
+
return RhcsV2CertPem(
|
|
86
|
+
certificate="PLACEHOLDER_CERT",
|
|
87
|
+
private_key="PLACEHOLDER_PRIVATE_KEY",
|
|
88
|
+
ca_cert="PLACEHOLDER_CA_CERT",
|
|
89
|
+
expiration_timestamp=int(time.time()),
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def get_certificate_format(
|
|
94
|
+
cert_resource: OpenshiftResourceRhcsCert,
|
|
95
|
+
) -> CertificateFormat:
|
|
96
|
+
return CertificateFormat(cert_resource.certificate_format or "PEM")
|
|
72
97
|
|
|
73
98
|
|
|
74
99
|
def get_namespaces_with_rhcs_certs(
|
|
@@ -77,26 +102,33 @@ def get_namespaces_with_rhcs_certs(
|
|
|
77
102
|
) -> list[NamespaceV1]:
|
|
78
103
|
result: list[NamespaceV1] = []
|
|
79
104
|
for ns in rhcs_certs_query(query_func=query_func).namespaces or []:
|
|
80
|
-
ob.aggregate_shared_resources_typed(
|
|
105
|
+
ob.aggregate_shared_resources_typed(ns)
|
|
81
106
|
if (
|
|
82
107
|
integration_is_enabled(QONTRACT_INTEGRATION, ns.cluster)
|
|
83
108
|
and not bool(ns.delete)
|
|
84
109
|
and (not cluster_name or ns.cluster.name in cluster_name)
|
|
85
|
-
and
|
|
110
|
+
and ns.openshift_resources
|
|
86
111
|
):
|
|
87
112
|
result.append(ns)
|
|
88
113
|
return result
|
|
89
114
|
|
|
90
115
|
|
|
91
116
|
def construct_rhcs_cert_oc_secret(
|
|
92
|
-
secret_name: str,
|
|
117
|
+
secret_name: str,
|
|
118
|
+
cert: Mapping[str, Any],
|
|
119
|
+
annotations: Mapping[str, str],
|
|
120
|
+
certificate_format: CertificateFormat,
|
|
93
121
|
) -> OR:
|
|
94
122
|
body: dict[str, Any] = {
|
|
95
123
|
"apiVersion": "v1",
|
|
96
124
|
"kind": "Secret",
|
|
97
|
-
"type": "kubernetes.io/tls",
|
|
98
125
|
"metadata": {"name": secret_name, "annotations": annotations},
|
|
99
126
|
}
|
|
127
|
+
match certificate_format:
|
|
128
|
+
case CertificateFormat.PKCS12:
|
|
129
|
+
body["type"] = "Opaque"
|
|
130
|
+
case CertificateFormat.PEM:
|
|
131
|
+
body["type"] = "kubernetes.io/tls"
|
|
100
132
|
for k, v in cert.items():
|
|
101
133
|
v = base64_encode_secret_field_value(v)
|
|
102
134
|
body.setdefault("data", {})[k] = v
|
|
@@ -105,7 +137,7 @@ def construct_rhcs_cert_oc_secret(
|
|
|
105
137
|
|
|
106
138
|
def cert_expires_within_threshold(
|
|
107
139
|
ns: NamespaceV1,
|
|
108
|
-
cert_resource:
|
|
140
|
+
cert_resource: OpenshiftResourceRhcsCert,
|
|
109
141
|
vault_cert_secret: Mapping[str, Any],
|
|
110
142
|
) -> bool:
|
|
111
143
|
auto_renew_threshold_days = cert_resource.auto_renew_threshold_days or 7
|
|
@@ -121,7 +153,7 @@ def cert_expires_within_threshold(
|
|
|
121
153
|
|
|
122
154
|
def get_vault_cert_secret(
|
|
123
155
|
ns: NamespaceV1,
|
|
124
|
-
cert_resource:
|
|
156
|
+
cert_resource: OpenshiftResourceRhcsCert,
|
|
125
157
|
vault: VaultClient,
|
|
126
158
|
vault_base_path: str,
|
|
127
159
|
) -> dict | None:
|
|
@@ -140,7 +172,7 @@ def get_vault_cert_secret(
|
|
|
140
172
|
def generate_vault_cert_secret(
|
|
141
173
|
dry_run: bool,
|
|
142
174
|
ns: NamespaceV1,
|
|
143
|
-
cert_resource:
|
|
175
|
+
cert_resource: OpenshiftResourceRhcsCert,
|
|
144
176
|
vault: VaultClient,
|
|
145
177
|
vault_base_path: str,
|
|
146
178
|
issuer_url: str,
|
|
@@ -149,18 +181,19 @@ def generate_vault_cert_secret(
|
|
|
149
181
|
logging.info(
|
|
150
182
|
f"Creating cert with service account credentials for '{cert_resource.service_account_name}'. cluster='{ns.cluster.name}', namespace='{ns.name}', secret='{cert_resource.secret_name}'"
|
|
151
183
|
)
|
|
152
|
-
sa_password = vault.read(cert_resource.service_account_password.
|
|
184
|
+
sa_password = vault.read(cert_resource.service_account_password.model_dump())
|
|
185
|
+
cert_format = get_certificate_format(cert_resource)
|
|
186
|
+
|
|
153
187
|
if dry_run:
|
|
154
|
-
rhcs_cert =
|
|
155
|
-
certificate="PLACEHOLDER_CERT",
|
|
156
|
-
private_key="PLACEHOLDER_PRIVATE_KEY",
|
|
157
|
-
ca_cert="PLACEHOLDER_CA_CERT",
|
|
158
|
-
expiration_timestamp=int(time.time()),
|
|
159
|
-
)
|
|
188
|
+
rhcs_cert = _generate_placeholder_cert(cert_format)
|
|
160
189
|
else:
|
|
161
190
|
try:
|
|
162
191
|
rhcs_cert = generate_cert(
|
|
163
|
-
issuer_url,
|
|
192
|
+
issuer_url=issuer_url,
|
|
193
|
+
uid=cert_resource.service_account_name,
|
|
194
|
+
pwd=sa_password,
|
|
195
|
+
ca_url=ca_cert_url,
|
|
196
|
+
cert_format=cert_format,
|
|
164
197
|
)
|
|
165
198
|
except ValueError as e:
|
|
166
199
|
raise Exception(
|
|
@@ -171,18 +204,18 @@ def generate_vault_cert_secret(
|
|
|
171
204
|
)
|
|
172
205
|
vault.write(
|
|
173
206
|
secret={
|
|
174
|
-
"data": rhcs_cert.
|
|
207
|
+
"data": rhcs_cert.model_dump(by_alias=True, exclude_none=True),
|
|
175
208
|
"path": f"{vault_base_path}/{ns.cluster.name}/{ns.name}/{cert_resource.secret_name}",
|
|
176
209
|
},
|
|
177
210
|
decode_base64=False,
|
|
178
211
|
)
|
|
179
|
-
return rhcs_cert.
|
|
212
|
+
return rhcs_cert.model_dump(by_alias=True, exclude_none=True)
|
|
180
213
|
|
|
181
214
|
|
|
182
215
|
def fetch_openshift_resource_for_cert_resource(
|
|
183
216
|
dry_run: bool,
|
|
184
217
|
ns: NamespaceV1,
|
|
185
|
-
cert_resource:
|
|
218
|
+
cert_resource: OpenshiftResourceRhcsCert,
|
|
186
219
|
vault: VaultClient,
|
|
187
220
|
rhcs_settings: RhcsProviderSettingsV1,
|
|
188
221
|
) -> OR:
|
|
@@ -218,6 +251,7 @@ def fetch_openshift_resource_for_cert_resource(
|
|
|
218
251
|
secret_name=cert_resource.secret_name,
|
|
219
252
|
cert=vault_cert_secret,
|
|
220
253
|
annotations=cert_resource.annotations or {},
|
|
254
|
+
certificate_format=get_certificate_format(cert_resource),
|
|
221
255
|
)
|
|
222
256
|
|
|
223
257
|
|
|
@@ -231,18 +265,13 @@ def fetch_desired_state(
|
|
|
231
265
|
cert_provider = get_rhcs_provider_settings(query_func=query_func)
|
|
232
266
|
for ns in namespaces:
|
|
233
267
|
for cert_resource in ns.openshift_resources or []:
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
cast("NamespaceOpenshiftResourceRhcsCertV1", cert_resource),
|
|
242
|
-
vault,
|
|
243
|
-
cert_provider,
|
|
244
|
-
),
|
|
245
|
-
)
|
|
268
|
+
ri.add_desired_resource(
|
|
269
|
+
cluster=ns.cluster.name,
|
|
270
|
+
namespace=ns.name,
|
|
271
|
+
resource=fetch_openshift_resource_for_cert_resource(
|
|
272
|
+
dry_run, ns, cert_resource, vault, cert_provider
|
|
273
|
+
),
|
|
274
|
+
)
|
|
246
275
|
|
|
247
276
|
|
|
248
277
|
@defer
|
|
@@ -277,7 +306,7 @@ def run(
|
|
|
277
306
|
state_specs = ob.init_specs_to_fetch(
|
|
278
307
|
ri,
|
|
279
308
|
oc_map,
|
|
280
|
-
namespaces=[ns.
|
|
309
|
+
namespaces=[ns.model_dump(by_alias=True) for ns in namespaces],
|
|
281
310
|
override_managed_types=["Secret"],
|
|
282
311
|
)
|
|
283
312
|
for spec in state_specs:
|
|
@@ -295,3 +324,11 @@ def run(
|
|
|
295
324
|
ob.publish_metrics(ri, QONTRACT_INTEGRATION)
|
|
296
325
|
if ri.has_error_registered():
|
|
297
326
|
sys.exit(1)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
|
|
330
|
+
if not (query_func := kwargs.get("query_func")):
|
|
331
|
+
query_func = gql.get_api().query
|
|
332
|
+
|
|
333
|
+
cluster_name = kwargs.get("cluster_name")
|
|
334
|
+
return {"namespace": get_namespaces_with_rhcs_certs(query_func, cluster_name)}
|
|
@@ -33,14 +33,11 @@ QONTRACT_INTEGRATION = "openshift-rolebindings"
|
|
|
33
33
|
QONTRACT_INTEGRATION_VERSION = make_semver(0, 3, 0)
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
class OCResource(BaseModel):
|
|
36
|
+
class OCResource(BaseModel, arbitrary_types_allowed=True):
|
|
37
37
|
resource: OR
|
|
38
38
|
resource_name: str
|
|
39
39
|
privileged: bool
|
|
40
40
|
|
|
41
|
-
class Config:
|
|
42
|
-
arbitrary_types_allowed = True
|
|
43
|
-
|
|
44
41
|
|
|
45
42
|
@dataclass
|
|
46
43
|
class ServiceAccountSpec:
|
|
@@ -61,7 +58,7 @@ class ServiceAccountSpec:
|
|
|
61
58
|
]
|
|
62
59
|
|
|
63
60
|
|
|
64
|
-
class RoleBindingSpec(BaseModel):
|
|
61
|
+
class RoleBindingSpec(BaseModel, validate_by_alias=True, arbitrary_types_allowed=True):
|
|
65
62
|
role_name: str
|
|
66
63
|
role_kind: str
|
|
67
64
|
namespace: NamespaceV1
|
|
@@ -70,9 +67,6 @@ class RoleBindingSpec(BaseModel):
|
|
|
70
67
|
usernames: set[str]
|
|
71
68
|
openshift_service_accounts: list[ServiceAccountSpec]
|
|
72
69
|
|
|
73
|
-
class Config:
|
|
74
|
-
arbitrary_types_allowed = True
|
|
75
|
-
|
|
76
70
|
def get_users_desired_state(self) -> list[dict[str, str]]:
|
|
77
71
|
return [
|
|
78
72
|
{"cluster": self.cluster.name, "user": username}
|
|
@@ -93,7 +87,9 @@ class RoleBindingSpec(BaseModel):
|
|
|
93
87
|
if not (access.role or access.cluster_role):
|
|
94
88
|
return None
|
|
95
89
|
privileged = access.namespace.cluster_admin or False
|
|
96
|
-
auth_dict = [
|
|
90
|
+
auth_dict = [
|
|
91
|
+
auth.model_dump(by_alias=True) for auth in access.namespace.cluster.auth
|
|
92
|
+
]
|
|
97
93
|
usernames = RoleBindingSpec.get_usernames_from_users(
|
|
98
94
|
users,
|
|
99
95
|
ob.determine_user_keys_for_access(
|
|
@@ -290,7 +286,7 @@ def is_valid_namespace(namespace: NamespaceV1 | CommonNamespaceV1) -> bool:
|
|
|
290
286
|
return (
|
|
291
287
|
bool(namespace.managed_roles)
|
|
292
288
|
and is_in_shard(f"{namespace.cluster.name}/{namespace.name}")
|
|
293
|
-
and not ob.is_namespace_deleted(namespace.
|
|
289
|
+
and not ob.is_namespace_deleted(namespace.model_dump(by_alias=True))
|
|
294
290
|
)
|
|
295
291
|
|
|
296
292
|
|
|
@@ -304,7 +300,7 @@ def run(
|
|
|
304
300
|
defer: Callable | None = None,
|
|
305
301
|
) -> None:
|
|
306
302
|
namespaces = [
|
|
307
|
-
namespace.
|
|
303
|
+
namespace.model_dump(by_alias=True, exclude={"openshift_resources"})
|
|
308
304
|
for namespace in get_namespaces()
|
|
309
305
|
if is_valid_namespace(namespace)
|
|
310
306
|
]
|
|
@@ -150,7 +150,7 @@ def run(
|
|
|
150
150
|
+ "when using slack notifications"
|
|
151
151
|
)
|
|
152
152
|
slack = slackapi_from_slack_workspace(
|
|
153
|
-
saas_file.slack.
|
|
153
|
+
saas_file.slack.model_dump(by_alias=True),
|
|
154
154
|
secret_reader,
|
|
155
155
|
QONTRACT_INTEGRATION,
|
|
156
156
|
init_usergroups=False,
|
|
@@ -224,7 +224,7 @@ def run(
|
|
|
224
224
|
default=False,
|
|
225
225
|
)
|
|
226
226
|
ri, oc_map = ob.fetch_current_state(
|
|
227
|
-
namespaces=[ns.
|
|
227
|
+
namespaces=[ns.model_dump(by_alias=True) for ns in saasherder.namespaces],
|
|
228
228
|
thread_pool_size=thread_pool_size,
|
|
229
229
|
integration=QONTRACT_INTEGRATION,
|
|
230
230
|
integration_version=QONTRACT_INTEGRATION_VERSION,
|
|
@@ -319,14 +319,13 @@ def run(
|
|
|
319
319
|
openshift_saas_deploy_trigger_upstream_jobs.QONTRACT_INTEGRATION,
|
|
320
320
|
openshift_saas_deploy_trigger_images.QONTRACT_INTEGRATION,
|
|
321
321
|
]
|
|
322
|
-
|
|
322
|
+
if (
|
|
323
323
|
not dry_run
|
|
324
324
|
and len(saas_files) == 1
|
|
325
325
|
and trigger_integration
|
|
326
326
|
and trigger_integration in allowed_integration
|
|
327
327
|
and trigger_reason
|
|
328
|
-
)
|
|
329
|
-
if scan:
|
|
328
|
+
):
|
|
330
329
|
saas_file = saas_files[0]
|
|
331
330
|
owners = saas_file.app.service_owners or []
|
|
332
331
|
emails = " ".join([o.email for o in owners])
|
|
@@ -34,7 +34,7 @@ class Definition(BaseModel):
|
|
|
34
34
|
class State(BaseModel):
|
|
35
35
|
saas_file_path: str
|
|
36
36
|
saas_file_name: str
|
|
37
|
-
saas_file_deploy_resources: DeployResourcesV1 | None
|
|
37
|
+
saas_file_deploy_resources: DeployResourcesV1 | None = None
|
|
38
38
|
resource_template_name: str
|
|
39
39
|
cluster: str
|
|
40
40
|
namespace: str
|
|
@@ -44,10 +44,10 @@ class State(BaseModel):
|
|
|
44
44
|
parameters: dict[str, Any]
|
|
45
45
|
secret_parameters: dict[str, VaultSecret]
|
|
46
46
|
saas_file_definitions: Definition
|
|
47
|
-
upstream: SaasResourceTemplateTargetUpstreamV1 | None
|
|
48
|
-
disable: bool | None
|
|
49
|
-
delete: bool | None
|
|
50
|
-
target_path: str | None
|
|
47
|
+
upstream: SaasResourceTemplateTargetUpstreamV1 | None = None
|
|
48
|
+
disable: bool | None = None
|
|
49
|
+
delete: bool | None = None
|
|
50
|
+
target_path: str | None = None
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
def osd_run_wrapper(
|
|
@@ -213,11 +213,13 @@ def run(
|
|
|
213
213
|
saas_file_list = SaasFileList()
|
|
214
214
|
desired_saas_file_state = collect_state(saas_file_list.saas_files)
|
|
215
215
|
# compare dicts against dicts which is much faster than comparing BaseModel objects
|
|
216
|
-
comparison_saas_file_state_dicts = [
|
|
216
|
+
comparison_saas_file_state_dicts = [
|
|
217
|
+
s.model_dump() for s in comparison_saas_file_state
|
|
218
|
+
]
|
|
217
219
|
saas_file_state_diffs = [
|
|
218
220
|
s
|
|
219
221
|
for s in desired_saas_file_state
|
|
220
|
-
if s.
|
|
222
|
+
if s.model_dump() not in comparison_saas_file_state_dicts
|
|
221
223
|
]
|
|
222
224
|
if not saas_file_state_diffs:
|
|
223
225
|
return
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from collections.abc import Callable
|
|
3
3
|
from datetime import (
|
|
4
|
-
UTC,
|
|
5
4
|
datetime,
|
|
6
5
|
timedelta,
|
|
7
6
|
)
|
|
8
7
|
from typing import Any
|
|
9
8
|
|
|
10
|
-
from dateutil import parser
|
|
11
|
-
|
|
12
9
|
from reconcile.gql_definitions.fragments.pipeline_provider_retention import (
|
|
13
10
|
PipelineProviderRetention,
|
|
14
11
|
)
|
|
@@ -19,6 +16,7 @@ from reconcile.typed_queries.tekton_pipeline_providers import (
|
|
|
19
16
|
get_tekton_pipeline_providers,
|
|
20
17
|
)
|
|
21
18
|
from reconcile.utils.constants import DEFAULT_THREAD_POOL_SIZE
|
|
19
|
+
from reconcile.utils.datetime_util import from_utc_iso_format, utc_now
|
|
22
20
|
from reconcile.utils.defer import defer
|
|
23
21
|
from reconcile.utils.oc_map import (
|
|
24
22
|
OCLogMsg,
|
|
@@ -35,7 +33,7 @@ def within_retention_days(
|
|
|
35
33
|
resource: dict[str, Any], days: int, now_date: datetime
|
|
36
34
|
) -> bool:
|
|
37
35
|
metadata = resource["metadata"]
|
|
38
|
-
creation_date =
|
|
36
|
+
creation_date = from_utc_iso_format(metadata["creationTimestamp"])
|
|
39
37
|
interval = now_date.timestamp() - creation_date.timestamp()
|
|
40
38
|
|
|
41
39
|
return interval < timedelta(days=days).total_seconds()
|
|
@@ -69,7 +67,7 @@ def run(
|
|
|
69
67
|
use_jump_host: bool = True,
|
|
70
68
|
defer: Callable | None = None,
|
|
71
69
|
) -> None:
|
|
72
|
-
now_date =
|
|
70
|
+
now_date = utc_now()
|
|
73
71
|
vault_settings = get_app_interface_vault_settings()
|
|
74
72
|
secret_reader = create_secret_reader(use_vault=vault_settings.vault)
|
|
75
73
|
pipeline_providers = get_tekton_pipeline_providers()
|
|
@@ -177,7 +177,7 @@ def canonicalize_namespaces(namespaces: Iterable[NamespaceV1]) -> list[Namespace
|
|
|
177
177
|
key = f"{sat.namespace.cluster.name}/{sat.namespace.name}"
|
|
178
178
|
if key not in canonicalized_namespaces:
|
|
179
179
|
canonicalized_namespaces[key] = NamespaceV1(
|
|
180
|
-
**sat.namespace.
|
|
180
|
+
**sat.namespace.model_dump(by_alias=True),
|
|
181
181
|
sharedResources=None,
|
|
182
182
|
openshiftServiceAccountTokens=None,
|
|
183
183
|
)
|
|
@@ -217,7 +217,7 @@ def run(
|
|
|
217
217
|
get_namespaces_with_serviceaccount_tokens(gql_api.query)
|
|
218
218
|
)
|
|
219
219
|
ri, oc_map = ob.fetch_current_state(
|
|
220
|
-
namespaces=[ns.
|
|
220
|
+
namespaces=[ns.model_dump(by_alias=True) for ns in namespaces],
|
|
221
221
|
thread_pool_size=thread_pool_size,
|
|
222
222
|
integration=QONTRACT_INTEGRATION,
|
|
223
223
|
integration_version=QONTRACT_INTEGRATION_VERSION,
|
|
@@ -3,7 +3,6 @@ from collections.abc import (
|
|
|
3
3
|
Callable,
|
|
4
4
|
Iterable,
|
|
5
5
|
)
|
|
6
|
-
from datetime import datetime
|
|
7
6
|
|
|
8
7
|
from reconcile import queries
|
|
9
8
|
from reconcile.gql_definitions.common.clusters import ClusterV1
|
|
@@ -13,6 +12,7 @@ from reconcile.typed_queries.app_interface_vault_settings import (
|
|
|
13
12
|
)
|
|
14
13
|
from reconcile.typed_queries.clusters import get_clusters
|
|
15
14
|
from reconcile.utils.constants import DEFAULT_THREAD_POOL_SIZE
|
|
15
|
+
from reconcile.utils.datetime_util import from_utc_iso_format, utc_now
|
|
16
16
|
from reconcile.utils.defer import defer
|
|
17
17
|
from reconcile.utils.oc_map import (
|
|
18
18
|
OCLogMsg,
|
|
@@ -101,7 +101,7 @@ def notify_upgrades_start(
|
|
|
101
101
|
state: State,
|
|
102
102
|
slack: SlackApi | None,
|
|
103
103
|
) -> None:
|
|
104
|
-
now =
|
|
104
|
+
now = utc_now()
|
|
105
105
|
for cluster in clusters:
|
|
106
106
|
if cluster.spec and not cluster.spec.hypershift:
|
|
107
107
|
upgrade_at, version = _get_start_osd(oc_map, cluster.name)
|
|
@@ -113,7 +113,7 @@ def notify_upgrades_start(
|
|
|
113
113
|
continue
|
|
114
114
|
|
|
115
115
|
if upgrade_at and version:
|
|
116
|
-
upgrade_at_obj =
|
|
116
|
+
upgrade_at_obj = from_utc_iso_format(upgrade_at)
|
|
117
117
|
state_key = f"{cluster.name}-{upgrade_at}1"
|
|
118
118
|
# if this is the first iteration in which 'now' had passed
|
|
119
119
|
# the upgrade at date time, we send a notification
|
|
@@ -185,7 +185,7 @@ def run(
|
|
|
185
185
|
if defer:
|
|
186
186
|
defer(oc_map.cleanup)
|
|
187
187
|
|
|
188
|
-
cluster_like_objects = [cluster.
|
|
188
|
+
cluster_like_objects = [cluster.model_dump(by_alias=True) for cluster in clusters]
|
|
189
189
|
ocm_map = OCMMap(
|
|
190
190
|
clusters=cluster_like_objects,
|
|
191
191
|
integration=QONTRACT_INTEGRATION,
|
reconcile/oum/labelset.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from collections import defaultdict
|
|
2
|
+
from typing import Annotated
|
|
2
3
|
|
|
3
4
|
from pydantic import BaseModel
|
|
4
5
|
|
|
@@ -22,9 +23,10 @@ class _GroupMappingLabelset(BaseModel):
|
|
|
22
23
|
the sre-capabilities.user-mgmt.$provider prefix.
|
|
23
24
|
"""
|
|
24
25
|
|
|
25
|
-
authz_roles:
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
authz_roles: Annotated[
|
|
27
|
+
dict[str, CSV] | None,
|
|
28
|
+
sre_capability_labels.labelset_groupfield(group_prefix="authz."),
|
|
29
|
+
]
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
def build_cluster_config_from_labels(
|
reconcile/oum/models.py
CHANGED
|
@@ -56,7 +56,7 @@ class ClusterUserManagementSpec(BaseModel):
|
|
|
56
56
|
errors: list[ClusterError] = Field(default_factory=list)
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
class ClusterRoleReconcileResult(BaseModel):
|
|
59
|
+
class ClusterRoleReconcileResult(BaseModel, arbitrary_types_allowed=True):
|
|
60
60
|
"""
|
|
61
61
|
Holds the result of a cluster role reconciliation.
|
|
62
62
|
"""
|
|
@@ -64,6 +64,3 @@ class ClusterRoleReconcileResult(BaseModel):
|
|
|
64
64
|
users_added: int = 0
|
|
65
65
|
users_removed: int = 0
|
|
66
66
|
error: Exception | None = None
|
|
67
|
-
|
|
68
|
-
class Config:
|
|
69
|
-
arbitrary_types_allowed = True
|
|
@@ -56,7 +56,7 @@ class Test(BaseModel):
|
|
|
56
56
|
rule_path: str
|
|
57
57
|
rule: dict
|
|
58
58
|
rule_length: int
|
|
59
|
-
tests: list[TestContent] | None
|
|
59
|
+
tests: list[TestContent] | None = None
|
|
60
60
|
result: CommandExecutionResult | None = None
|
|
61
61
|
promtool_version: str
|
|
62
62
|
|
|
@@ -76,7 +76,7 @@ def fetch_rule_and_tests(
|
|
|
76
76
|
openshift_resource = orb.fetch_openshift_resource(
|
|
77
77
|
resource=rule.resource,
|
|
78
78
|
parent=rule.namespace,
|
|
79
|
-
settings=vault_settings.
|
|
79
|
+
settings=vault_settings.model_dump(by_alias=True),
|
|
80
80
|
)
|
|
81
81
|
|
|
82
82
|
rule_body = openshift_resource.body
|
|
@@ -96,7 +96,7 @@ def fetch_rule_and_tests(
|
|
|
96
96
|
test_raw_yaml = process_extracurlyjinja2_template(
|
|
97
97
|
body=test_raw_yaml,
|
|
98
98
|
vars=variables,
|
|
99
|
-
settings=vault_settings.
|
|
99
|
+
settings=vault_settings.model_dump(by_alias=True),
|
|
100
100
|
)
|
|
101
101
|
|
|
102
102
|
test_yaml_spec = yaml.safe_load(test_raw_yaml)
|
reconcile/quay_base.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from collections import namedtuple
|
|
1
|
+
from collections import UserDict, namedtuple
|
|
2
2
|
from typing import Any, TypedDict
|
|
3
3
|
|
|
4
4
|
from reconcile import queries
|
|
@@ -10,22 +10,34 @@ OrgKey = namedtuple("OrgKey", ["instance", "org_name"])
|
|
|
10
10
|
|
|
11
11
|
class OrgInfo(TypedDict):
|
|
12
12
|
url: str
|
|
13
|
-
api: QuayApi
|
|
14
13
|
push_token: dict[str, str] | None
|
|
15
14
|
teams: list[str]
|
|
16
15
|
managedRepos: bool
|
|
17
16
|
mirror: OrgKey | None
|
|
18
17
|
mirror_filters: dict[str, Any]
|
|
18
|
+
api: QuayApi
|
|
19
|
+
|
|
19
20
|
|
|
21
|
+
class QuayApiStore(UserDict[OrgKey, OrgInfo]):
|
|
22
|
+
def __init__(self) -> None:
|
|
23
|
+
super().__init__(get_quay_api_store())
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
def cleanup(self) -> None:
|
|
26
|
+
"""Close all QuayApi sessions."""
|
|
27
|
+
for org_info in self.data.values():
|
|
28
|
+
org_info["api"].cleanup()
|
|
22
29
|
|
|
30
|
+
def __enter__(self) -> "QuayApiStore":
|
|
31
|
+
return self
|
|
23
32
|
|
|
24
|
-
def
|
|
33
|
+
def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
|
34
|
+
self.cleanup()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def get_quay_api_store() -> dict[OrgKey, OrgInfo]:
|
|
25
38
|
"""
|
|
26
39
|
Returns a dictionary with a key for each Quay organization
|
|
27
40
|
managed in app-interface.
|
|
28
|
-
Each key contains an initiated QuayApi instance.
|
|
29
41
|
"""
|
|
30
42
|
quay_orgs = queries.get_quay_orgs()
|
|
31
43
|
settings = queries.get_app_interface_settings()
|
|
@@ -61,14 +73,21 @@ def get_quay_api_store() -> QuayApiStore:
|
|
|
61
73
|
else:
|
|
62
74
|
push_token = None
|
|
63
75
|
|
|
76
|
+
# Create QuayApi instance for this org
|
|
77
|
+
api = QuayApi(
|
|
78
|
+
token=token,
|
|
79
|
+
organization=org_name,
|
|
80
|
+
base_url=base_url,
|
|
81
|
+
)
|
|
82
|
+
|
|
64
83
|
org_info: OrgInfo = {
|
|
65
84
|
"url": base_url,
|
|
66
|
-
"api": QuayApi(token, org_name, base_url=base_url),
|
|
67
85
|
"push_token": push_token,
|
|
68
86
|
"teams": org_data.get("managedTeams") or [],
|
|
69
87
|
"managedRepos": bool(org_data.get("managedRepos")),
|
|
70
88
|
"mirror": mirror,
|
|
71
89
|
"mirror_filters": mirror_filters,
|
|
90
|
+
"api": api,
|
|
72
91
|
}
|
|
73
92
|
|
|
74
93
|
store[org_key] = org_info
|