qontract-reconcile 0.10.2.dev310__py3-none-any.whl → 0.10.2.dev439__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of qontract-reconcile might be problematic. Click here for more details.
- {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/METADATA +13 -12
- {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/RECORD +396 -391
- reconcile/acs_rbac.py +2 -2
- reconcile/aus/advanced_upgrade_service.py +18 -12
- reconcile/aus/base.py +134 -32
- reconcile/aus/cluster_version_data.py +15 -5
- reconcile/aus/models.py +3 -1
- reconcile/aus/ocm_addons_upgrade_scheduler_org.py +1 -0
- reconcile/aus/ocm_upgrade_scheduler.py +8 -1
- reconcile/aus/ocm_upgrade_scheduler_org.py +20 -5
- reconcile/aus/version_gates/sts_version_gate_handler.py +54 -1
- reconcile/automated_actions/config/integration.py +16 -4
- reconcile/aws_account_manager/integration.py +8 -8
- reconcile/aws_account_manager/reconciler.py +3 -3
- reconcile/aws_ami_cleanup/integration.py +8 -12
- reconcile/aws_ami_share.py +69 -62
- reconcile/aws_cloudwatch_log_retention/integration.py +155 -126
- reconcile/aws_ecr_image_pull_secrets.py +5 -5
- reconcile/aws_iam_keys.py +1 -0
- reconcile/aws_saml_idp/integration.py +12 -4
- reconcile/aws_saml_roles/integration.py +32 -25
- reconcile/aws_version_sync/integration.py +125 -84
- reconcile/change_owners/bundle.py +3 -3
- reconcile/change_owners/change_log_tracking.py +3 -2
- reconcile/change_owners/change_owners.py +1 -1
- reconcile/change_owners/diff.py +2 -4
- reconcile/checkpoint.py +12 -4
- reconcile/cli.py +111 -18
- reconcile/cluster_deployment_mapper.py +2 -3
- reconcile/dashdotdb_dora.py +5 -12
- reconcile/dashdotdb_slo.py +1 -1
- reconcile/database_access_manager.py +125 -121
- reconcile/deadmanssnitch.py +1 -5
- reconcile/dynatrace_token_provider/integration.py +1 -1
- reconcile/endpoints_discovery/integration.py +4 -1
- reconcile/endpoints_discovery/merge_request.py +1 -1
- reconcile/endpoints_discovery/merge_request_manager.py +9 -11
- reconcile/external_resources/factories.py +5 -12
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +8 -5
- reconcile/external_resources/meta.py +0 -1
- reconcile/external_resources/metrics.py +1 -1
- reconcile/external_resources/model.py +20 -20
- reconcile/external_resources/reconciler.py +7 -4
- reconcile/external_resources/secrets_sync.py +10 -14
- reconcile/external_resources/state.py +26 -16
- reconcile/fleet_labeler/integration.py +1 -1
- reconcile/gabi_authorized_users.py +8 -5
- reconcile/gcp_image_mirror.py +2 -2
- reconcile/github_org.py +1 -1
- reconcile/github_owners.py +4 -0
- reconcile/gitlab_housekeeping.py +13 -15
- reconcile/gitlab_members.py +6 -12
- reconcile/gitlab_mr_sqs_consumer.py +2 -2
- reconcile/gitlab_owners.py +15 -11
- reconcile/gitlab_permissions.py +8 -12
- reconcile/glitchtip_project_alerts/integration.py +3 -1
- reconcile/gql_definitions/acs/acs_instances.py +10 -10
- reconcile/gql_definitions/acs/acs_policies.py +5 -5
- reconcile/gql_definitions/acs/acs_rbac.py +6 -6
- reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +32 -32
- reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +26 -26
- reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +6 -7
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
- reconcile/gql_definitions/automated_actions/instance.py +51 -12
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +11 -11
- reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +20 -10
- reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +28 -68
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +20 -10
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +20 -10
- reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
- reconcile/gql_definitions/aws_version_sync/clusters.py +10 -10
- reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
- reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
- reconcile/gql_definitions/change_owners/queries/self_service_roles.py +9 -9
- reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +18 -18
- reconcile/gql_definitions/common/alerting_services_settings.py +9 -9
- reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
- reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
- reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_roles.py +120 -0
- reconcile/gql_definitions/common/app_interface_state_settings.py +10 -10
- reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
- reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
- reconcile/gql_definitions/common/apps.py +5 -5
- reconcile/gql_definitions/common/aws_vpc_requests.py +22 -9
- reconcile/gql_definitions/common/aws_vpcs.py +11 -11
- reconcile/gql_definitions/common/clusters.py +37 -35
- reconcile/gql_definitions/common/clusters_minimal.py +14 -14
- reconcile/gql_definitions/common/clusters_with_dms.py +6 -6
- reconcile/gql_definitions/common/clusters_with_peering.py +29 -30
- reconcile/gql_definitions/common/github_orgs.py +10 -10
- reconcile/gql_definitions/common/jira_settings.py +10 -10
- reconcile/gql_definitions/common/jiralert_settings.py +5 -5
- reconcile/gql_definitions/common/ldap_settings.py +5 -5
- reconcile/gql_definitions/common/namespaces.py +42 -44
- reconcile/gql_definitions/common/namespaces_minimal.py +15 -13
- reconcile/gql_definitions/common/ocm_env_telemeter.py +12 -12
- reconcile/gql_definitions/common/ocm_environments.py +19 -19
- reconcile/gql_definitions/common/pagerduty_instances.py +9 -9
- reconcile/gql_definitions/common/pgp_reencryption_settings.py +6 -6
- reconcile/gql_definitions/common/pipeline_providers.py +29 -29
- reconcile/gql_definitions/common/quay_instances.py +5 -5
- reconcile/gql_definitions/common/quay_orgs.py +5 -5
- reconcile/gql_definitions/common/reserved_networks.py +5 -5
- reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
- reconcile/gql_definitions/common/saas_files.py +44 -44
- reconcile/gql_definitions/common/saas_target_namespaces.py +10 -10
- reconcile/gql_definitions/common/saasherder_settings.py +5 -5
- reconcile/gql_definitions/common/slack_workspaces.py +5 -5
- reconcile/gql_definitions/common/smtp_client_settings.py +19 -19
- reconcile/gql_definitions/common/state_aws_account.py +7 -8
- reconcile/gql_definitions/common/users.py +5 -5
- reconcile/gql_definitions/common/users_with_paths.py +5 -5
- reconcile/gql_definitions/cost_report/app_names.py +5 -5
- reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
- reconcile/gql_definitions/cost_report/settings.py +9 -9
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +43 -43
- reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +10 -10
- reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
- reconcile/gql_definitions/email_sender/apps.py +5 -5
- reconcile/gql_definitions/email_sender/emails.py +8 -8
- reconcile/gql_definitions/email_sender/users.py +6 -6
- reconcile/gql_definitions/endpoints_discovery/apps.py +10 -10
- reconcile/gql_definitions/external_resources/aws_accounts.py +9 -9
- reconcile/gql_definitions/external_resources/external_resources_modules.py +23 -23
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py +494 -410
- reconcile/gql_definitions/external_resources/external_resources_settings.py +28 -26
- reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
- reconcile/gql_definitions/fleet_labeler/fleet_labels.py +40 -40
- reconcile/gql_definitions/fragments/aus_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_common.py +7 -5
- reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
- reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
- reconcile/gql_definitions/fragments/{aws_vpc_request_subnet.py → aws_organization.py} +12 -8
- reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc_request.py +12 -5
- reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
- reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
- reconcile/gql_definitions/fragments/disable.py +5 -5
- reconcile/gql_definitions/fragments/email_service.py +5 -5
- reconcile/gql_definitions/fragments/email_user.py +5 -5
- reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
- reconcile/gql_definitions/fragments/membership_source.py +5 -5
- reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
- reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
- reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
- reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
- reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
- reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_values.py +5 -5
- reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
- reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
- reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
- reconcile/gql_definitions/fragments/terraform_state.py +5 -5
- reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
- reconcile/gql_definitions/fragments/user.py +5 -5
- reconcile/gql_definitions/fragments/vault_secret.py +5 -5
- reconcile/gql_definitions/gcp/gcp_docker_repos.py +9 -9
- reconcile/gql_definitions/gcp/gcp_projects.py +9 -9
- reconcile/gql_definitions/gitlab_members/gitlab_instances.py +9 -9
- reconcile/gql_definitions/gitlab_members/permissions.py +9 -9
- reconcile/gql_definitions/glitchtip/glitchtip_instance.py +9 -9
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +11 -11
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +9 -9
- reconcile/gql_definitions/integrations/integrations.py +48 -51
- reconcile/gql_definitions/introspection.json +3510 -1865
- reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +11 -11
- reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +10 -10
- reconcile/gql_definitions/jira/jira_servers.py +5 -5
- reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +14 -10
- reconcile/gql_definitions/jumphosts/jumphosts.py +13 -13
- reconcile/gql_definitions/ldap_groups/roles.py +5 -5
- reconcile/gql_definitions/ldap_groups/settings.py +9 -9
- reconcile/gql_definitions/maintenance/maintenances.py +5 -5
- reconcile/gql_definitions/membershipsources/roles.py +5 -5
- reconcile/gql_definitions/ocm_labels/clusters.py +18 -19
- reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
- reconcile/gql_definitions/openshift_cluster_bots/clusters.py +22 -22
- reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_roles.py +6 -6
- reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +10 -10
- reconcile/gql_definitions/quay_membership/quay_membership.py +6 -6
- reconcile/gql_definitions/rhcs/certs.py +33 -87
- reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +43 -0
- reconcile/gql_definitions/rhidp/organizations.py +18 -18
- reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
- reconcile/gql_definitions/service_dependencies/service_dependencies.py +8 -8
- reconcile/gql_definitions/sharding/aws_accounts.py +10 -10
- reconcile/gql_definitions/sharding/ocm_organization.py +8 -8
- reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
- reconcile/gql_definitions/skupper_network/skupper_networks.py +10 -10
- reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
- reconcile/gql_definitions/slack_usergroups/permissions.py +9 -9
- reconcile/gql_definitions/slack_usergroups/users.py +5 -5
- reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
- reconcile/gql_definitions/status_board/status_board.py +6 -7
- reconcile/gql_definitions/statuspage/statuspages.py +9 -9
- reconcile/gql_definitions/templating/template_collection.py +5 -5
- reconcile/gql_definitions/templating/templates.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +6 -6
- reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +11 -11
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +11 -11
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +20 -25
- reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +6 -6
- reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +12 -12
- reconcile/gql_definitions/terraform_init/aws_accounts.py +23 -9
- reconcile/gql_definitions/terraform_repo/terraform_repo.py +9 -9
- reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +450 -402
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +23 -17
- reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +9 -9
- reconcile/gql_definitions/vault_instances/vault_instances.py +61 -61
- reconcile/gql_definitions/vault_policies/vault_policies.py +11 -11
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +8 -8
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
- reconcile/integrations_manager.py +3 -3
- reconcile/jenkins_job_builder.py +1 -1
- reconcile/jenkins_worker_fleets.py +80 -11
- reconcile/jira_permissions_validator.py +237 -122
- reconcile/ldap_groups/integration.py +1 -1
- reconcile/ocm/types.py +35 -56
- reconcile/ocm_aws_infrastructure_access.py +1 -1
- reconcile/ocm_clusters.py +4 -4
- reconcile/ocm_labels/integration.py +3 -2
- reconcile/ocm_machine_pools.py +33 -27
- reconcile/openshift_base.py +122 -10
- reconcile/openshift_cluster_bots.py +5 -5
- reconcile/openshift_groups.py +5 -0
- reconcile/openshift_limitranges.py +1 -1
- reconcile/openshift_namespace_labels.py +1 -1
- reconcile/openshift_namespaces.py +97 -101
- reconcile/openshift_resources_base.py +10 -5
- reconcile/openshift_rhcs_certs.py +77 -40
- reconcile/openshift_rolebindings.py +230 -130
- reconcile/openshift_saas_deploy.py +6 -7
- reconcile/openshift_saas_deploy_change_tester.py +9 -7
- reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
- reconcile/openshift_serviceaccount_tokens.py +8 -7
- reconcile/openshift_tekton_resources.py +1 -1
- reconcile/openshift_upgrade_watcher.py +4 -4
- reconcile/openshift_users.py +5 -3
- reconcile/oum/labelset.py +5 -3
- reconcile/oum/models.py +1 -4
- reconcile/oum/providers.py +1 -1
- reconcile/prometheus_rules_tester/integration.py +4 -4
- reconcile/quay_mirror.py +1 -1
- reconcile/queries.py +131 -0
- reconcile/requests_sender.py +8 -3
- reconcile/resource_scraper.py +1 -5
- reconcile/rhidp/common.py +3 -5
- reconcile/rhidp/sso_client/base.py +19 -10
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
- reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
- reconcile/sendgrid_teammates.py +20 -9
- reconcile/skupper_network/integration.py +2 -2
- reconcile/slack_usergroups.py +35 -14
- reconcile/sql_query.py +1 -0
- reconcile/status.py +2 -2
- reconcile/status_board.py +6 -6
- reconcile/statuspage/atlassian.py +7 -7
- reconcile/statuspage/integrations/maintenances.py +4 -3
- reconcile/statuspage/page.py +4 -9
- reconcile/statuspage/status.py +5 -8
- reconcile/templates/rosa-classic-cluster-creation.sh.j2 +5 -1
- reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +4 -1
- reconcile/templating/lib/merge_request_manager.py +2 -2
- reconcile/templating/lib/rendering.py +3 -3
- reconcile/templating/renderer.py +12 -13
- reconcile/terraform_aws_route53.py +18 -8
- reconcile/terraform_cloudflare_dns.py +3 -3
- reconcile/terraform_cloudflare_resources.py +12 -13
- reconcile/terraform_cloudflare_users.py +3 -2
- reconcile/terraform_init/integration.py +187 -23
- reconcile/terraform_repo.py +16 -12
- reconcile/terraform_resources.py +18 -10
- reconcile/terraform_tgw_attachments.py +28 -20
- reconcile/terraform_users.py +27 -22
- reconcile/terraform_vpc_peerings.py +15 -3
- reconcile/terraform_vpc_resources/integration.py +23 -8
- reconcile/typed_queries/app_interface_roles.py +10 -0
- reconcile/typed_queries/aws_account_tags.py +41 -0
- reconcile/typed_queries/cost_report/app_names.py +1 -1
- reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
- reconcile/typed_queries/saas_files.py +13 -13
- reconcile/typed_queries/status_board.py +2 -2
- reconcile/unleash_feature_toggles/integration.py +4 -2
- reconcile/utils/acs/base.py +6 -3
- reconcile/utils/acs/policies.py +2 -2
- reconcile/utils/aggregated_list.py +4 -3
- reconcile/utils/aws_api.py +51 -20
- reconcile/utils/aws_api_typed/api.py +38 -9
- reconcile/utils/aws_api_typed/cloudformation.py +149 -0
- reconcile/utils/aws_api_typed/logs.py +73 -0
- reconcile/utils/aws_api_typed/organization.py +4 -2
- reconcile/utils/binary.py +7 -12
- reconcile/utils/datetime_util.py +67 -0
- reconcile/utils/deadmanssnitch_api.py +1 -1
- reconcile/utils/differ.py +2 -3
- reconcile/utils/early_exit_cache.py +11 -12
- reconcile/utils/expiration.py +7 -3
- reconcile/utils/external_resource_spec.py +24 -1
- reconcile/utils/filtering.py +1 -1
- reconcile/utils/gitlab_api.py +7 -5
- reconcile/utils/glitchtip/client.py +6 -2
- reconcile/utils/glitchtip/models.py +25 -28
- reconcile/utils/gpg.py +5 -3
- reconcile/utils/gql.py +4 -7
- reconcile/utils/helm.py +2 -1
- reconcile/utils/helpers.py +1 -1
- reconcile/utils/imap_client.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/jenkins_api.py +24 -1
- reconcile/utils/jinja2/utils.py +6 -8
- reconcile/utils/jira_client.py +82 -63
- reconcile/utils/jjb_client.py +78 -46
- reconcile/utils/jobcontroller/controller.py +2 -2
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/json.py +74 -0
- reconcile/utils/ldap_client.py +4 -3
- reconcile/utils/lean_terraform_client.py +3 -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/__init__.py +3 -1
- reconcile/utils/mr/app_interface_reporter.py +6 -3
- reconcile/utils/mr/aws_access.py +1 -1
- reconcile/utils/mr/base.py +7 -13
- reconcile/utils/mr/clusters_updates.py +4 -2
- reconcile/utils/mr/notificator.py +3 -3
- reconcile/utils/mr/ocm_upgrade_scheduler_org_updates.py +4 -1
- reconcile/utils/mr/promote_qontract.py +28 -12
- reconcile/utils/mr/update_access_report_base.py +3 -4
- reconcile/utils/mr/user_maintenance.py +7 -6
- reconcile/utils/oc.py +445 -336
- reconcile/utils/oc_filters.py +3 -3
- reconcile/utils/ocm/addons.py +0 -1
- reconcile/utils/ocm/base.py +18 -21
- reconcile/utils/ocm/cluster_groups.py +1 -1
- reconcile/utils/ocm/identity_providers.py +2 -2
- reconcile/utils/ocm/labels.py +1 -1
- reconcile/utils/ocm/ocm.py +81 -71
- reconcile/utils/ocm/products.py +9 -3
- reconcile/utils/ocm/search_filters.py +3 -6
- reconcile/utils/ocm/service_log.py +4 -6
- reconcile/utils/ocm/sre_capability_labels.py +20 -13
- reconcile/utils/ocm_base_client.py +4 -4
- reconcile/utils/openshift_resource.py +83 -52
- reconcile/utils/openssl.py +2 -2
- reconcile/utils/output.py +3 -2
- reconcile/utils/pagerduty_api.py +10 -7
- reconcile/utils/promotion_state.py +6 -11
- reconcile/utils/raw_github_api.py +11 -8
- reconcile/utils/repo_owners.py +21 -29
- reconcile/utils/rhcsv2_certs.py +138 -35
- reconcile/utils/rosa/session.py +16 -0
- reconcile/utils/runtime/integration.py +2 -3
- reconcile/utils/runtime/meta.py +2 -1
- reconcile/utils/runtime/runner.py +2 -2
- reconcile/utils/saasherder/interfaces.py +13 -20
- reconcile/utils/saasherder/models.py +25 -21
- reconcile/utils/saasherder/saasherder.py +60 -32
- reconcile/utils/secret_reader.py +6 -6
- reconcile/utils/sharding.py +1 -1
- reconcile/utils/slack_api.py +26 -4
- reconcile/utils/sloth.py +224 -0
- reconcile/utils/sqs_gateway.py +16 -11
- reconcile/utils/state.py +2 -1
- reconcile/utils/structs.py +1 -1
- reconcile/utils/terraform_client.py +29 -26
- reconcile/utils/terrascript_aws_client.py +200 -116
- reconcile/utils/three_way_diff_strategy.py +1 -1
- reconcile/utils/unleash/server.py +2 -8
- reconcile/utils/vault.py +44 -41
- reconcile/utils/vcs.py +8 -8
- reconcile/vault_replication.py +119 -58
- tools/app_interface_reporter.py +4 -4
- tools/cli_commands/cost_report/cost_management_api.py +3 -3
- tools/cli_commands/cost_report/view.py +7 -6
- tools/cli_commands/erv2.py +1 -1
- tools/cli_commands/gpg_encrypt.py +4 -1
- tools/cli_commands/systems_and_tools.py +5 -1
- tools/qontract_cli.py +36 -21
- tools/template_validation.py +3 -1
- reconcile/gql_definitions/ocm_oidc_idp/__init__.py +0 -0
- reconcile/gql_definitions/ocm_subscription_labels/__init__.py +0 -0
- reconcile/jenkins/__init__.py +0 -0
- reconcile/jenkins/types.py +0 -77
- {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/entry_points.txt +0 -0
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
import
|
|
2
|
+
from collections import defaultdict
|
|
3
3
|
from collections.abc import (
|
|
4
4
|
Callable,
|
|
5
5
|
Iterable,
|
|
6
|
-
Mapping,
|
|
7
6
|
Sequence,
|
|
8
7
|
)
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from enum import StrEnum
|
|
9
10
|
from typing import Any
|
|
10
11
|
|
|
11
12
|
from sretoolbox.utils import threaded
|
|
12
13
|
|
|
13
14
|
import reconcile.openshift_base as ob
|
|
14
15
|
from reconcile.gql_definitions.common.namespaces_minimal import NamespaceV1
|
|
15
|
-
from reconcile.status import ExitCodes
|
|
16
16
|
from reconcile.typed_queries.app_interface_vault_settings import (
|
|
17
17
|
get_app_interface_vault_settings,
|
|
18
18
|
)
|
|
19
19
|
from reconcile.typed_queries.namespaces_minimal import get_namespaces_minimal
|
|
20
20
|
from reconcile.utils.constants import DEFAULT_THREAD_POOL_SIZE
|
|
21
21
|
from reconcile.utils.defer import defer
|
|
22
|
-
from reconcile.utils.oc_filters import
|
|
22
|
+
from reconcile.utils.oc_filters import (
|
|
23
|
+
filter_namespaces_by_cluster_and_namespace,
|
|
24
|
+
)
|
|
23
25
|
from reconcile.utils.oc_map import (
|
|
24
26
|
OCLogMsg,
|
|
25
27
|
OCMap,
|
|
@@ -30,113 +32,112 @@ from reconcile.utils.sharding import is_in_shard
|
|
|
30
32
|
|
|
31
33
|
QONTRACT_INTEGRATION = "openshift-namespaces"
|
|
32
34
|
|
|
33
|
-
NS_STATE_PRESENT = "present"
|
|
34
|
-
NS_STATE_ABSENT = "absent"
|
|
35
|
-
|
|
36
|
-
NS_ACTION_CREATE = "create"
|
|
37
|
-
NS_ACTION_DELETE = "delete"
|
|
38
35
|
|
|
36
|
+
class Action(StrEnum):
|
|
37
|
+
CREATE = "create"
|
|
38
|
+
DELETE = "delete"
|
|
39
39
|
|
|
40
|
-
DUPLICATES_LOG_MSG = "Found multiple definitions for the namespace {key}"
|
|
41
40
|
|
|
41
|
+
@dataclass(frozen=True)
|
|
42
|
+
class DesiredState:
|
|
43
|
+
cluster: str
|
|
44
|
+
namespace: str
|
|
45
|
+
delete: bool
|
|
42
46
|
|
|
43
|
-
def get_desired_state(namespaces: Iterable[NamespaceV1]) -> list[dict[str, str]]:
|
|
44
|
-
desired_state: list[dict[str, str]] = []
|
|
45
|
-
for ns in namespaces:
|
|
46
|
-
state = NS_STATE_PRESENT
|
|
47
|
-
if ns.delete:
|
|
48
|
-
state = NS_STATE_ABSENT
|
|
49
47
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"namespace": ns.name,
|
|
53
|
-
"desired_state": state,
|
|
54
|
-
})
|
|
48
|
+
class NamespaceDuplicateError(Exception):
|
|
49
|
+
pass
|
|
55
50
|
|
|
56
|
-
return desired_state
|
|
57
51
|
|
|
52
|
+
def get_namespaces(
|
|
53
|
+
cluster_name: Sequence[str] | None,
|
|
54
|
+
namespace_name: Sequence[str] | None,
|
|
55
|
+
) -> tuple[list[NamespaceV1], list[NamespaceDuplicateError]]:
|
|
56
|
+
all_namespaces = get_namespaces_minimal()
|
|
58
57
|
|
|
59
|
-
|
|
60
|
-
namespaces: Iterable[NamespaceV1],
|
|
61
|
-
) -> tuple[list[NamespaceV1], bool]:
|
|
62
|
-
# Structure holding duplicates by namespace key
|
|
63
|
-
duplicates: dict[str, list[NamespaceV1]] = {}
|
|
64
|
-
# namespace filtered list without duplicates
|
|
65
|
-
filtered_ns: dict[str, NamespaceV1] = {}
|
|
66
|
-
|
|
67
|
-
err = False
|
|
68
|
-
for ns in namespaces:
|
|
69
|
-
key = f"{ns.cluster.name}/{ns.name}"
|
|
58
|
+
namespaces_by_shard_key = defaultdict(list)
|
|
70
59
|
|
|
60
|
+
for namespace in all_namespaces:
|
|
61
|
+
key = f"{namespace.cluster.name}/{namespace.name}"
|
|
71
62
|
if is_in_shard(key):
|
|
72
|
-
|
|
73
|
-
filtered_ns[key] = ns
|
|
74
|
-
else:
|
|
75
|
-
# Duplicated NS
|
|
76
|
-
dupe_list_by_key = duplicates.setdefault(key, [])
|
|
77
|
-
dupe_list_by_key.append(ns)
|
|
78
|
-
|
|
79
|
-
for key, dupe_list in duplicates.items():
|
|
80
|
-
dupe_list.append(filtered_ns[key])
|
|
81
|
-
delete_flags = (
|
|
82
|
-
[ns.delete for ns in dupe_list_by_key] if dupe_list_by_key else []
|
|
83
|
-
)
|
|
63
|
+
namespaces_by_shard_key[key].append(namespace)
|
|
84
64
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
65
|
+
managed_namespaces = []
|
|
66
|
+
duplicate_errors = []
|
|
67
|
+
|
|
68
|
+
for key, namespaces in namespaces_by_shard_key.items():
|
|
69
|
+
if len(namespaces) == 1:
|
|
70
|
+
namespace = namespaces[0]
|
|
71
|
+
if not namespace.managed_by_external:
|
|
72
|
+
managed_namespaces.append(namespace)
|
|
92
73
|
else:
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
logging.
|
|
74
|
+
msg = f"Found multiple definitions for the namespace {key}"
|
|
75
|
+
duplicate_errors.append(NamespaceDuplicateError(msg))
|
|
76
|
+
logging.error(msg)
|
|
77
|
+
|
|
78
|
+
namespaces = filter_namespaces_by_cluster_and_namespace(
|
|
79
|
+
namespaces=managed_namespaces,
|
|
80
|
+
cluster_names=cluster_name,
|
|
81
|
+
namespace_names=namespace_name,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return namespaces, duplicate_errors
|
|
85
|
+
|
|
96
86
|
|
|
97
|
-
|
|
87
|
+
def build_desired_state(
|
|
88
|
+
namespaces: Iterable[NamespaceV1],
|
|
89
|
+
) -> list[DesiredState]:
|
|
90
|
+
return [
|
|
91
|
+
DesiredState(
|
|
92
|
+
cluster=namespace.cluster.name,
|
|
93
|
+
namespace=namespace.name,
|
|
94
|
+
delete=namespace.delete or False,
|
|
95
|
+
)
|
|
96
|
+
for namespace in namespaces
|
|
97
|
+
]
|
|
98
98
|
|
|
99
99
|
|
|
100
|
-
def
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
def manage_namespace(
|
|
101
|
+
desired_state: DesiredState,
|
|
102
|
+
oc_map: OCMap,
|
|
103
|
+
dry_run: bool,
|
|
104
|
+
) -> None:
|
|
105
|
+
namespace = desired_state.namespace
|
|
104
106
|
|
|
105
|
-
oc = oc_map.get(cluster)
|
|
107
|
+
oc = oc_map.get(desired_state.cluster)
|
|
106
108
|
if isinstance(oc, OCLogMsg):
|
|
107
109
|
logging.log(level=oc.log_level, msg=oc.message)
|
|
108
|
-
return
|
|
110
|
+
return
|
|
109
111
|
|
|
110
|
-
|
|
112
|
+
current_delete = not oc.project_exists(namespace)
|
|
111
113
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if not exists and desired_state == NS_STATE_PRESENT:
|
|
115
|
-
if namespace.startswith("openshift-"):
|
|
116
|
-
raise ValueError('cannot request a project starting with "openshift-"')
|
|
117
|
-
action = NS_ACTION_CREATE
|
|
118
|
-
elif exists and desired_state == NS_STATE_ABSENT:
|
|
119
|
-
action = NS_ACTION_DELETE
|
|
114
|
+
if desired_state.delete == current_delete:
|
|
115
|
+
return
|
|
120
116
|
|
|
121
|
-
if
|
|
122
|
-
logging.info([action, cluster, namespace])
|
|
123
|
-
if not dry_run:
|
|
124
|
-
act[action](namespace)
|
|
117
|
+
action = Action.DELETE if desired_state.delete else Action.CREATE
|
|
125
118
|
|
|
119
|
+
if namespace.startswith("openshift-"):
|
|
120
|
+
raise ValueError(f'cannot {action} a project starting with "openshift-"')
|
|
126
121
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
122
|
+
logging.info([str(action), desired_state.cluster, namespace])
|
|
123
|
+
if not dry_run:
|
|
124
|
+
match action:
|
|
125
|
+
case Action.CREATE:
|
|
126
|
+
oc.new_project(namespace)
|
|
127
|
+
case Action.DELETE:
|
|
128
|
+
oc.delete_project(namespace)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def build_runtime_errors(
|
|
132
|
+
desired_state: Iterable[DesiredState],
|
|
133
|
+
results: Iterable[Any],
|
|
134
|
+
) -> list[Exception]:
|
|
135
|
+
exceptions = []
|
|
131
136
|
for s, e in zip(desired_state, results, strict=False):
|
|
132
137
|
if isinstance(e, Exception):
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
f"exception: {e!s}"
|
|
137
|
-
)
|
|
138
|
-
logging.error(msg)
|
|
139
|
-
return err
|
|
138
|
+
e.add_note(f"cluster: {s.cluster}, namespace: {s.namespace}")
|
|
139
|
+
exceptions.append(e)
|
|
140
|
+
return exceptions
|
|
140
141
|
|
|
141
142
|
|
|
142
143
|
@defer
|
|
@@ -149,15 +150,8 @@ def run(
|
|
|
149
150
|
namespace_name: Sequence[str] | None = None,
|
|
150
151
|
defer: Callable | None = None,
|
|
151
152
|
) -> None:
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
namespaces = filter_namespaces_by_cluster_and_namespace(
|
|
155
|
-
namespaces=shard_namespaces,
|
|
156
|
-
cluster_names=cluster_name,
|
|
157
|
-
namespace_names=namespace_name,
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
desired_state = get_desired_state(namespaces)
|
|
153
|
+
namespaces, duplicate_errors = get_namespaces(cluster_name, namespace_name)
|
|
154
|
+
desired_state = build_desired_state(namespaces)
|
|
161
155
|
|
|
162
156
|
vault_settings = get_app_interface_vault_settings()
|
|
163
157
|
secret_reader = create_secret_reader(use_vault=vault_settings.vault)
|
|
@@ -171,16 +165,17 @@ def run(
|
|
|
171
165
|
thread_pool_size=thread_pool_size,
|
|
172
166
|
init_projects=True,
|
|
173
167
|
)
|
|
174
|
-
|
|
175
168
|
if defer:
|
|
176
169
|
defer(oc_map.cleanup)
|
|
177
170
|
|
|
178
171
|
ob.publish_cluster_desired_metrics_from_state(
|
|
179
|
-
desired_state,
|
|
172
|
+
state=({"cluster": s.cluster} for s in desired_state),
|
|
173
|
+
integration=QONTRACT_INTEGRATION,
|
|
174
|
+
kind="Namespace",
|
|
180
175
|
)
|
|
181
176
|
|
|
182
177
|
results = threaded.run(
|
|
183
|
-
|
|
178
|
+
manage_namespace,
|
|
184
179
|
desired_state,
|
|
185
180
|
thread_pool_size,
|
|
186
181
|
return_exceptions=True,
|
|
@@ -188,6 +183,7 @@ def run(
|
|
|
188
183
|
oc_map=oc_map,
|
|
189
184
|
)
|
|
190
185
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
186
|
+
runtime_errors = build_runtime_errors(desired_state, results)
|
|
187
|
+
errors = runtime_errors + duplicate_errors
|
|
188
|
+
if errors:
|
|
189
|
+
raise ExceptionGroup("Reconcile errors occurred", errors)
|
|
@@ -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)
|
|
@@ -1005,8 +1009,9 @@ class CheckClusterScopedResourceNames:
|
|
|
1005
1009
|
for kind in cluster_scoped_types:
|
|
1006
1010
|
declared_items = mrn.get(kind, [])
|
|
1007
1011
|
desired_items = set(
|
|
1008
|
-
|
|
1009
|
-
cluster_name, ns["name"], kind
|
|
1012
|
+
(
|
|
1013
|
+
self.ri.get_desired_by_type(cluster_name, ns["name"], kind)
|
|
1014
|
+
or {}
|
|
1010
1015
|
).keys()
|
|
1011
1016
|
)
|
|
1012
1017
|
diff = desired_items.difference(declared_items)
|
|
@@ -1212,7 +1217,7 @@ def _early_exit_fetch_resource(spec: Sequence, settings: Mapping) -> dict[str, s
|
|
|
1212
1217
|
c = resource["resource"].get("content")
|
|
1213
1218
|
del resource["resource"]
|
|
1214
1219
|
resource[IDENTIFIER_FIELD_NAME] = id
|
|
1215
|
-
content_sha = hashlib.md5(c.encode("utf-8")).hexdigest()
|
|
1220
|
+
content_sha = hashlib.md5(str(c).encode("utf-8")).hexdigest()
|
|
1216
1221
|
return {
|
|
1217
1222
|
IDENTIFIER_FIELD_NAME: id,
|
|
1218
1223
|
"cluster": cluster_name,
|
|
@@ -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,13 +153,13 @@ 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:
|
|
128
160
|
vault_cert_secret = None
|
|
129
161
|
try:
|
|
130
|
-
vault_cert_secret = vault.read_all({
|
|
162
|
+
vault_cert_secret = vault.read_all({
|
|
131
163
|
"path": f"{vault_base_path}/{ns.cluster.name}/{ns.name}/{cert_resource.secret_name}"
|
|
132
164
|
})
|
|
133
165
|
except SecretNotFoundError:
|
|
@@ -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(
|
|
@@ -169,20 +202,20 @@ def generate_vault_cert_secret(
|
|
|
169
202
|
logging.info(
|
|
170
203
|
f"Writing cert details to Vault at {vault_base_path}/{ns.cluster.name}/{ns.name}/{cert_resource.secret_name}"
|
|
171
204
|
)
|
|
172
|
-
vault.write(
|
|
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
|
|
|
@@ -227,22 +261,17 @@ def fetch_desired_state(
|
|
|
227
261
|
ri: ResourceInventory,
|
|
228
262
|
query_func: Callable,
|
|
229
263
|
) -> None:
|
|
230
|
-
vault = VaultClient()
|
|
264
|
+
vault = VaultClient.get_instance()
|
|
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)}
|