qontract-reconcile 0.9.1rc298__py3-none-any.whl → 0.10.1.dev1203__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.1.dev1203.dist-info/METADATA +500 -0
- qontract_reconcile-0.10.1.dev1203.dist-info/RECORD +771 -0
- {qontract_reconcile-0.9.1rc298.dist-info → qontract_reconcile-0.10.1.dev1203.dist-info}/WHEEL +1 -2
- {qontract_reconcile-0.9.1rc298.dist-info → qontract_reconcile-0.10.1.dev1203.dist-info}/entry_points.txt +4 -2
- reconcile/acs_notifiers.py +126 -0
- reconcile/acs_policies.py +243 -0
- reconcile/acs_rbac.py +596 -0
- reconcile/aus/advanced_upgrade_service.py +621 -8
- reconcile/aus/aus_label_source.py +115 -0
- reconcile/aus/base.py +1053 -353
- reconcile/{utils → aus}/cluster_version_data.py +27 -12
- reconcile/aus/healthchecks.py +77 -0
- reconcile/aus/metrics.py +158 -0
- reconcile/aus/models.py +245 -5
- reconcile/aus/node_pool_spec.py +35 -0
- reconcile/aus/ocm_addons_upgrade_scheduler_org.py +225 -110
- reconcile/aus/ocm_upgrade_scheduler.py +76 -71
- reconcile/aus/ocm_upgrade_scheduler_org.py +81 -23
- reconcile/aus/version_gate_approver.py +204 -0
- reconcile/aus/version_gates/__init__.py +12 -0
- reconcile/aus/version_gates/handler.py +33 -0
- reconcile/aus/version_gates/ingress_gate_handler.py +32 -0
- reconcile/aus/version_gates/ocp_gate_handler.py +26 -0
- reconcile/aus/version_gates/sts_version_gate_handler.py +100 -0
- reconcile/aws_account_manager/README.md +5 -0
- reconcile/aws_account_manager/integration.py +373 -0
- reconcile/aws_account_manager/merge_request_manager.py +114 -0
- reconcile/aws_account_manager/metrics.py +39 -0
- reconcile/aws_account_manager/reconciler.py +403 -0
- reconcile/aws_account_manager/utils.py +41 -0
- reconcile/aws_ami_cleanup/integration.py +273 -0
- reconcile/aws_ami_share.py +18 -14
- reconcile/aws_cloudwatch_log_retention/integration.py +253 -0
- reconcile/aws_iam_keys.py +1 -1
- reconcile/aws_iam_password_reset.py +56 -20
- reconcile/aws_saml_idp/integration.py +204 -0
- reconcile/aws_saml_roles/integration.py +322 -0
- reconcile/aws_support_cases_sos.py +2 -2
- reconcile/aws_version_sync/integration.py +430 -0
- reconcile/aws_version_sync/merge_request_manager/merge_request.py +156 -0
- reconcile/aws_version_sync/merge_request_manager/merge_request_manager.py +160 -0
- reconcile/aws_version_sync/utils.py +64 -0
- reconcile/blackbox_exporter_endpoint_monitoring.py +2 -5
- reconcile/change_owners/README.md +34 -0
- reconcile/change_owners/approver.py +7 -9
- reconcile/change_owners/bundle.py +134 -9
- reconcile/change_owners/change_log_tracking.py +236 -0
- reconcile/change_owners/change_owners.py +204 -194
- reconcile/change_owners/change_types.py +183 -265
- reconcile/change_owners/changes.py +488 -0
- reconcile/change_owners/decision.py +120 -41
- reconcile/change_owners/diff.py +63 -92
- reconcile/change_owners/implicit_ownership.py +19 -16
- reconcile/change_owners/self_service_roles.py +158 -35
- reconcile/change_owners/tester.py +20 -18
- reconcile/checkpoint.py +4 -6
- reconcile/cli.py +1523 -242
- reconcile/closedbox_endpoint_monitoring_base.py +10 -17
- reconcile/cluster_auth_rhidp/integration.py +257 -0
- reconcile/cluster_deployment_mapper.py +2 -5
- reconcile/cna/assets/asset.py +4 -7
- reconcile/cna/assets/null.py +2 -5
- reconcile/cna/integration.py +2 -3
- reconcile/cna/state.py +6 -9
- reconcile/dashdotdb_base.py +31 -10
- reconcile/dashdotdb_cso.py +3 -6
- reconcile/dashdotdb_dora.py +530 -0
- reconcile/dashdotdb_dvo.py +10 -13
- reconcile/dashdotdb_slo.py +75 -19
- reconcile/database_access_manager.py +753 -0
- reconcile/deadmanssnitch.py +207 -0
- reconcile/dynatrace_token_provider/dependencies.py +69 -0
- reconcile/dynatrace_token_provider/integration.py +656 -0
- reconcile/dynatrace_token_provider/metrics.py +62 -0
- reconcile/dynatrace_token_provider/model.py +14 -0
- reconcile/dynatrace_token_provider/ocm.py +140 -0
- reconcile/dynatrace_token_provider/validate.py +48 -0
- reconcile/endpoints_discovery/integration.py +348 -0
- reconcile/endpoints_discovery/merge_request.py +96 -0
- reconcile/endpoints_discovery/merge_request_manager.py +178 -0
- reconcile/external_resources/aws.py +204 -0
- reconcile/external_resources/factories.py +163 -0
- reconcile/external_resources/integration.py +194 -0
- reconcile/external_resources/integration_secrets_sync.py +47 -0
- reconcile/external_resources/manager.py +405 -0
- reconcile/external_resources/meta.py +17 -0
- reconcile/external_resources/metrics.py +95 -0
- reconcile/external_resources/model.py +350 -0
- reconcile/external_resources/reconciler.py +265 -0
- reconcile/external_resources/secrets_sync.py +465 -0
- reconcile/external_resources/state.py +258 -0
- reconcile/gabi_authorized_users.py +19 -11
- reconcile/gcr_mirror.py +43 -34
- reconcile/github_org.py +4 -6
- reconcile/github_owners.py +1 -1
- reconcile/github_repo_invites.py +2 -5
- reconcile/gitlab_fork_compliance.py +14 -13
- reconcile/gitlab_housekeeping.py +185 -91
- reconcile/gitlab_labeler.py +15 -14
- reconcile/gitlab_members.py +126 -120
- reconcile/gitlab_owners.py +53 -66
- reconcile/gitlab_permissions.py +167 -6
- reconcile/glitchtip/README.md +150 -0
- reconcile/glitchtip/integration.py +99 -51
- reconcile/glitchtip/reconciler.py +99 -70
- reconcile/glitchtip_project_alerts/__init__.py +0 -0
- reconcile/glitchtip_project_alerts/integration.py +333 -0
- reconcile/glitchtip_project_dsn/integration.py +43 -43
- reconcile/gql_definitions/acs/__init__.py +0 -0
- reconcile/gql_definitions/acs/acs_instances.py +83 -0
- reconcile/gql_definitions/acs/acs_policies.py +239 -0
- reconcile/gql_definitions/acs/acs_rbac.py +111 -0
- reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +46 -8
- reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +38 -8
- reconcile/gql_definitions/app_interface_metrics_exporter/__init__.py +0 -0
- reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +61 -0
- reconcile/gql_definitions/aws_account_manager/__init__.py +0 -0
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +177 -0
- reconcile/gql_definitions/aws_ami_cleanup/__init__.py +0 -0
- reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +161 -0
- reconcile/gql_definitions/aws_saml_idp/__init__.py +0 -0
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +117 -0
- reconcile/gql_definitions/aws_saml_roles/__init__.py +0 -0
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +117 -0
- reconcile/gql_definitions/aws_saml_roles/roles.py +97 -0
- reconcile/gql_definitions/aws_version_sync/__init__.py +0 -0
- reconcile/gql_definitions/aws_version_sync/clusters.py +83 -0
- reconcile/gql_definitions/aws_version_sync/namespaces.py +143 -0
- reconcile/gql_definitions/change_owners/queries/change_types.py +16 -29
- reconcile/gql_definitions/change_owners/queries/self_service_roles.py +45 -11
- reconcile/gql_definitions/cluster_auth_rhidp/__init__.py +0 -0
- reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +128 -0
- reconcile/gql_definitions/cna/queries/cna_provisioners.py +6 -8
- reconcile/gql_definitions/cna/queries/cna_resources.py +3 -5
- reconcile/gql_definitions/common/alerting_services_settings.py +2 -2
- reconcile/gql_definitions/common/app_code_component_repos.py +9 -5
- reconcile/gql_definitions/{glitchtip/glitchtip_settings.py → common/app_interface_custom_messages.py} +14 -16
- reconcile/gql_definitions/common/app_interface_dms_settings.py +86 -0
- reconcile/gql_definitions/common/app_interface_repo_settings.py +2 -2
- reconcile/gql_definitions/common/app_interface_state_settings.py +3 -5
- reconcile/gql_definitions/common/app_interface_vault_settings.py +3 -5
- reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +120 -0
- reconcile/gql_definitions/common/apps.py +72 -0
- reconcile/gql_definitions/common/aws_vpc_requests.py +109 -0
- reconcile/gql_definitions/common/aws_vpcs.py +84 -0
- reconcile/gql_definitions/common/clusters.py +120 -254
- reconcile/gql_definitions/common/clusters_minimal.py +11 -35
- reconcile/gql_definitions/common/clusters_with_dms.py +72 -0
- reconcile/gql_definitions/common/clusters_with_peering.py +70 -98
- reconcile/gql_definitions/common/github_orgs.py +2 -2
- reconcile/gql_definitions/common/jira_settings.py +68 -0
- reconcile/gql_definitions/common/jiralert_settings.py +68 -0
- reconcile/gql_definitions/common/namespaces.py +74 -32
- reconcile/gql_definitions/common/namespaces_minimal.py +4 -10
- reconcile/gql_definitions/common/ocm_env_telemeter.py +95 -0
- reconcile/gql_definitions/common/ocm_environments.py +4 -2
- reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
- reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -11
- reconcile/gql_definitions/common/pipeline_providers.py +45 -90
- reconcile/gql_definitions/common/quay_instances.py +64 -0
- reconcile/gql_definitions/common/quay_orgs.py +68 -0
- reconcile/gql_definitions/common/reserved_networks.py +94 -0
- reconcile/gql_definitions/common/saas_files.py +133 -95
- reconcile/gql_definitions/common/saas_target_namespaces.py +41 -26
- reconcile/gql_definitions/common/saasherder_settings.py +2 -2
- reconcile/gql_definitions/common/slack_workspaces.py +62 -0
- reconcile/gql_definitions/common/smtp_client_settings.py +2 -2
- reconcile/gql_definitions/common/state_aws_account.py +77 -0
- reconcile/gql_definitions/common/users.py +3 -2
- reconcile/gql_definitions/cost_report/__init__.py +0 -0
- reconcile/gql_definitions/cost_report/app_names.py +68 -0
- reconcile/gql_definitions/cost_report/cost_namespaces.py +86 -0
- reconcile/gql_definitions/cost_report/settings.py +77 -0
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +42 -12
- reconcile/gql_definitions/dynatrace_token_provider/__init__.py +0 -0
- reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +79 -0
- reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +84 -0
- reconcile/gql_definitions/endpoints_discovery/__init__.py +0 -0
- reconcile/gql_definitions/endpoints_discovery/namespaces.py +127 -0
- reconcile/gql_definitions/external_resources/__init__.py +0 -0
- reconcile/gql_definitions/external_resources/aws_accounts.py +73 -0
- reconcile/gql_definitions/external_resources/external_resources_modules.py +78 -0
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py +1111 -0
- reconcile/gql_definitions/external_resources/external_resources_settings.py +98 -0
- reconcile/gql_definitions/fragments/aus_organization.py +34 -39
- reconcile/gql_definitions/fragments/aws_account_common.py +62 -0
- reconcile/gql_definitions/fragments/aws_account_managed.py +57 -0
- reconcile/gql_definitions/fragments/aws_account_sso.py +35 -0
- reconcile/gql_definitions/fragments/aws_infra_management_account.py +2 -2
- reconcile/gql_definitions/fragments/aws_vpc.py +47 -0
- reconcile/gql_definitions/fragments/aws_vpc_request.py +65 -0
- reconcile/gql_definitions/fragments/aws_vpc_request_subnet.py +29 -0
- reconcile/gql_definitions/fragments/deplopy_resources.py +7 -7
- reconcile/gql_definitions/fragments/disable.py +28 -0
- reconcile/gql_definitions/fragments/jumphost_common_fields.py +2 -2
- reconcile/gql_definitions/fragments/membership_source.py +47 -0
- reconcile/gql_definitions/fragments/minimal_ocm_organization.py +29 -0
- reconcile/gql_definitions/fragments/oc_connection_cluster.py +4 -9
- reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
- reconcile/gql_definitions/fragments/pipeline_provider_retention.py +30 -0
- reconcile/gql_definitions/fragments/prometheus_instance.py +48 -0
- reconcile/gql_definitions/fragments/resource_limits_requirements.py +29 -0
- reconcile/gql_definitions/fragments/{resource_requirements.py → resource_requests_requirements.py} +3 -3
- reconcile/gql_definitions/fragments/resource_values.py +2 -2
- reconcile/gql_definitions/fragments/saas_target_namespace.py +55 -12
- reconcile/gql_definitions/fragments/serviceaccount_token.py +38 -0
- reconcile/gql_definitions/fragments/terraform_state.py +36 -0
- reconcile/gql_definitions/fragments/upgrade_policy.py +5 -3
- reconcile/gql_definitions/fragments/user.py +3 -2
- reconcile/gql_definitions/fragments/vault_secret.py +2 -2
- reconcile/gql_definitions/gitlab_members/gitlab_instances.py +6 -2
- reconcile/gql_definitions/gitlab_members/permissions.py +3 -5
- reconcile/gql_definitions/glitchtip/glitchtip_instance.py +16 -2
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +22 -23
- reconcile/gql_definitions/glitchtip_project_alerts/__init__.py +0 -0
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +173 -0
- reconcile/gql_definitions/integrations/integrations.py +62 -45
- reconcile/gql_definitions/introspection.json +51176 -0
- reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +13 -5
- reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +79 -0
- reconcile/gql_definitions/jira/__init__.py +0 -0
- reconcile/gql_definitions/jira/jira_servers.py +80 -0
- reconcile/gql_definitions/jira_permissions_validator/__init__.py +0 -0
- reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +131 -0
- reconcile/gql_definitions/jumphosts/jumphosts.py +3 -5
- reconcile/gql_definitions/ldap_groups/__init__.py +0 -0
- reconcile/gql_definitions/ldap_groups/roles.py +111 -0
- reconcile/gql_definitions/ldap_groups/settings.py +79 -0
- reconcile/gql_definitions/maintenance/__init__.py +0 -0
- reconcile/gql_definitions/maintenance/maintenances.py +101 -0
- reconcile/gql_definitions/membershipsources/__init__.py +0 -0
- reconcile/gql_definitions/membershipsources/roles.py +112 -0
- reconcile/gql_definitions/ocm_labels/__init__.py +0 -0
- reconcile/gql_definitions/ocm_labels/clusters.py +112 -0
- reconcile/gql_definitions/ocm_labels/organizations.py +78 -0
- reconcile/gql_definitions/ocm_subscription_labels/__init__.py +0 -0
- reconcile/gql_definitions/openshift_cluster_bots/__init__.py +0 -0
- reconcile/gql_definitions/openshift_cluster_bots/clusters.py +126 -0
- reconcile/gql_definitions/openshift_groups/managed_groups.py +2 -2
- reconcile/gql_definitions/openshift_groups/managed_roles.py +3 -2
- reconcile/gql_definitions/openshift_serviceaccount_tokens/__init__.py +0 -0
- reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +132 -0
- reconcile/gql_definitions/quay_membership/quay_membership.py +3 -5
- reconcile/gql_definitions/rhidp/__init__.py +0 -0
- reconcile/gql_definitions/rhidp/organizations.py +96 -0
- reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +2 -2
- reconcile/gql_definitions/service_dependencies/service_dependencies.py +9 -31
- reconcile/gql_definitions/sharding/aws_accounts.py +2 -2
- reconcile/gql_definitions/sharding/ocm_organization.py +63 -0
- reconcile/gql_definitions/skupper_network/site_controller_template.py +2 -2
- reconcile/gql_definitions/skupper_network/skupper_networks.py +12 -38
- reconcile/gql_definitions/slack_usergroups/clusters.py +2 -2
- reconcile/gql_definitions/slack_usergroups/permissions.py +8 -15
- reconcile/gql_definitions/slack_usergroups/users.py +3 -2
- reconcile/gql_definitions/slo_documents/__init__.py +0 -0
- reconcile/gql_definitions/slo_documents/slo_documents.py +142 -0
- reconcile/gql_definitions/status_board/__init__.py +0 -0
- reconcile/gql_definitions/status_board/status_board.py +163 -0
- reconcile/gql_definitions/statuspage/statuspages.py +56 -7
- reconcile/gql_definitions/templating/__init__.py +0 -0
- reconcile/gql_definitions/templating/template_collection.py +130 -0
- reconcile/gql_definitions/templating/templates.py +108 -0
- reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +4 -8
- reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +8 -8
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +6 -8
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +45 -56
- reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +4 -8
- reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +4 -8
- reconcile/gql_definitions/terraform_init/__init__.py +0 -0
- reconcile/gql_definitions/terraform_init/aws_accounts.py +93 -0
- reconcile/gql_definitions/terraform_repo/__init__.py +0 -0
- reconcile/gql_definitions/terraform_repo/terraform_repo.py +141 -0
- reconcile/gql_definitions/terraform_resources/database_access_manager.py +158 -0
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +153 -162
- reconcile/gql_definitions/terraform_tgw_attachments/__init__.py +0 -0
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +119 -0
- reconcile/gql_definitions/unleash_feature_toggles/__init__.py +0 -0
- reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +113 -0
- reconcile/gql_definitions/vault_instances/vault_instances.py +17 -50
- reconcile/gql_definitions/vault_policies/vault_policies.py +2 -2
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +49 -12
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +7 -2
- reconcile/integrations_manager.py +25 -13
- reconcile/jenkins/types.py +5 -1
- reconcile/jenkins_base.py +36 -0
- reconcile/jenkins_job_builder.py +10 -48
- reconcile/jenkins_job_builds_cleaner.py +40 -25
- reconcile/jenkins_job_cleaner.py +1 -3
- reconcile/jenkins_roles.py +22 -26
- reconcile/jenkins_webhooks.py +9 -6
- reconcile/jenkins_worker_fleets.py +11 -6
- reconcile/jira_permissions_validator.py +340 -0
- reconcile/jira_watcher.py +3 -5
- reconcile/ldap_groups/__init__.py +0 -0
- reconcile/ldap_groups/integration.py +279 -0
- reconcile/ldap_users.py +3 -0
- reconcile/ocm/types.py +39 -59
- reconcile/ocm_additional_routers.py +0 -1
- reconcile/ocm_addons_upgrade_tests_trigger.py +10 -15
- reconcile/ocm_aws_infrastructure_access.py +30 -32
- reconcile/ocm_clusters.py +217 -130
- reconcile/ocm_external_configuration_labels.py +15 -0
- reconcile/ocm_github_idp.py +1 -1
- reconcile/ocm_groups.py +25 -5
- reconcile/ocm_internal_notifications/__init__.py +0 -0
- reconcile/ocm_internal_notifications/integration.py +119 -0
- reconcile/ocm_labels/__init__.py +0 -0
- reconcile/ocm_labels/integration.py +409 -0
- reconcile/ocm_machine_pools.py +517 -108
- reconcile/ocm_upgrade_scheduler_org_updater.py +15 -11
- reconcile/openshift_base.py +609 -207
- reconcile/openshift_cluster_bots.py +344 -0
- reconcile/openshift_clusterrolebindings.py +15 -15
- reconcile/openshift_groups.py +42 -45
- reconcile/openshift_limitranges.py +1 -0
- reconcile/openshift_namespace_labels.py +22 -28
- reconcile/openshift_namespaces.py +22 -22
- reconcile/openshift_network_policies.py +4 -8
- reconcile/openshift_prometheus_rules.py +43 -0
- reconcile/openshift_resourcequotas.py +2 -16
- reconcile/openshift_resources.py +12 -10
- reconcile/openshift_resources_base.py +304 -328
- reconcile/openshift_rolebindings.py +18 -20
- reconcile/openshift_saas_deploy.py +105 -21
- reconcile/openshift_saas_deploy_change_tester.py +30 -35
- reconcile/openshift_saas_deploy_trigger_base.py +39 -36
- reconcile/openshift_saas_deploy_trigger_cleaner.py +41 -27
- reconcile/openshift_saas_deploy_trigger_configs.py +1 -2
- reconcile/openshift_saas_deploy_trigger_images.py +1 -2
- reconcile/openshift_saas_deploy_trigger_moving_commits.py +1 -2
- reconcile/openshift_saas_deploy_trigger_upstream_jobs.py +1 -2
- reconcile/openshift_serviceaccount_tokens.py +138 -74
- reconcile/openshift_tekton_resources.py +89 -24
- reconcile/openshift_upgrade_watcher.py +110 -62
- reconcile/openshift_users.py +16 -15
- reconcile/openshift_vault_secrets.py +11 -6
- reconcile/oum/__init__.py +0 -0
- reconcile/oum/base.py +387 -0
- reconcile/oum/labelset.py +55 -0
- reconcile/oum/metrics.py +71 -0
- reconcile/oum/models.py +69 -0
- reconcile/oum/providers.py +59 -0
- reconcile/oum/standalone.py +196 -0
- reconcile/prometheus_rules_tester/integration.py +31 -23
- reconcile/quay_base.py +4 -1
- reconcile/quay_membership.py +1 -2
- reconcile/quay_mirror.py +111 -61
- reconcile/quay_mirror_org.py +34 -21
- reconcile/quay_permissions.py +7 -3
- reconcile/quay_repos.py +24 -32
- reconcile/queries.py +263 -198
- reconcile/query_validator.py +3 -5
- reconcile/resource_scraper.py +3 -4
- reconcile/{template_tester.py → resource_template_tester.py} +3 -3
- reconcile/rhidp/__init__.py +0 -0
- reconcile/rhidp/common.py +214 -0
- reconcile/rhidp/metrics.py +20 -0
- reconcile/rhidp/ocm_oidc_idp/__init__.py +0 -0
- reconcile/rhidp/ocm_oidc_idp/base.py +221 -0
- reconcile/rhidp/ocm_oidc_idp/integration.py +56 -0
- reconcile/rhidp/ocm_oidc_idp/metrics.py +22 -0
- reconcile/rhidp/sso_client/__init__.py +0 -0
- reconcile/rhidp/sso_client/base.py +266 -0
- reconcile/rhidp/sso_client/integration.py +60 -0
- reconcile/rhidp/sso_client/metrics.py +39 -0
- reconcile/run_integration.py +293 -0
- reconcile/saas_auto_promotions_manager/integration.py +69 -24
- reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py +208 -0
- reconcile/saas_auto_promotions_manager/merge_request_manager/desired_state.py +28 -0
- reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request.py +3 -4
- reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager_v2.py +172 -0
- reconcile/saas_auto_promotions_manager/merge_request_manager/metrics.py +42 -0
- reconcile/saas_auto_promotions_manager/merge_request_manager/mr_parser.py +226 -0
- reconcile/saas_auto_promotions_manager/merge_request_manager/open_merge_requests.py +23 -0
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +108 -32
- reconcile/saas_auto_promotions_manager/meta.py +4 -0
- reconcile/saas_auto_promotions_manager/publisher.py +32 -4
- reconcile/saas_auto_promotions_manager/s3_exporter.py +77 -0
- reconcile/saas_auto_promotions_manager/subscriber.py +110 -23
- reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py +48 -41
- reconcile/saas_file_validator.py +16 -6
- reconcile/sendgrid_teammates.py +27 -12
- reconcile/service_dependencies.py +0 -3
- reconcile/signalfx_endpoint_monitoring.py +2 -5
- reconcile/skupper_network/integration.py +10 -11
- reconcile/skupper_network/models.py +3 -5
- reconcile/skupper_network/reconciler.py +28 -35
- reconcile/skupper_network/site_controller.py +8 -8
- reconcile/slack_base.py +4 -7
- reconcile/slack_usergroups.py +249 -171
- reconcile/sql_query.py +324 -171
- reconcile/status.py +0 -1
- reconcile/status_board.py +275 -0
- reconcile/statuspage/__init__.py +0 -5
- reconcile/statuspage/atlassian.py +219 -80
- reconcile/statuspage/integration.py +9 -97
- reconcile/statuspage/integrations/__init__.py +0 -0
- reconcile/statuspage/integrations/components.py +77 -0
- reconcile/statuspage/integrations/maintenances.py +111 -0
- reconcile/statuspage/page.py +107 -72
- reconcile/statuspage/state.py +6 -11
- reconcile/statuspage/status.py +8 -12
- reconcile/templates/rosa-classic-cluster-creation.sh.j2 +60 -0
- reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +61 -0
- reconcile/templating/__init__.py +0 -0
- reconcile/templating/lib/__init__.py +0 -0
- reconcile/templating/lib/merge_request_manager.py +180 -0
- reconcile/templating/lib/model.py +20 -0
- reconcile/templating/lib/rendering.py +191 -0
- reconcile/templating/renderer.py +410 -0
- reconcile/templating/validator.py +153 -0
- reconcile/terraform_aws_route53.py +13 -10
- reconcile/terraform_cloudflare_dns.py +92 -122
- reconcile/terraform_cloudflare_resources.py +15 -13
- reconcile/terraform_cloudflare_users.py +27 -27
- reconcile/terraform_init/__init__.py +0 -0
- reconcile/terraform_init/integration.py +165 -0
- reconcile/terraform_init/merge_request.py +57 -0
- reconcile/terraform_init/merge_request_manager.py +102 -0
- reconcile/terraform_repo.py +403 -0
- reconcile/terraform_resources.py +266 -168
- reconcile/terraform_tgw_attachments.py +417 -167
- reconcile/terraform_users.py +40 -17
- reconcile/terraform_vpc_peerings.py +310 -142
- reconcile/terraform_vpc_resources/__init__.py +0 -0
- reconcile/terraform_vpc_resources/integration.py +220 -0
- reconcile/terraform_vpc_resources/merge_request.py +57 -0
- reconcile/terraform_vpc_resources/merge_request_manager.py +107 -0
- reconcile/typed_queries/alerting_services_settings.py +1 -2
- reconcile/typed_queries/app_interface_custom_messages.py +24 -0
- reconcile/typed_queries/app_interface_deadmanssnitch_settings.py +17 -0
- reconcile/typed_queries/app_interface_metrics_exporter/__init__.py +0 -0
- reconcile/typed_queries/app_interface_metrics_exporter/onboarding_status.py +13 -0
- reconcile/typed_queries/app_interface_repo_url.py +1 -2
- reconcile/typed_queries/app_interface_state_settings.py +1 -3
- reconcile/typed_queries/app_interface_vault_settings.py +1 -2
- reconcile/typed_queries/app_quay_repos_escalation_policies.py +14 -0
- reconcile/typed_queries/apps.py +11 -0
- reconcile/typed_queries/aws_vpc_requests.py +9 -0
- reconcile/typed_queries/aws_vpcs.py +12 -0
- reconcile/typed_queries/cloudflare.py +10 -0
- reconcile/typed_queries/clusters.py +7 -5
- reconcile/typed_queries/clusters_minimal.py +6 -5
- reconcile/typed_queries/clusters_with_dms.py +16 -0
- reconcile/typed_queries/cost_report/__init__.py +0 -0
- reconcile/typed_queries/cost_report/app_names.py +22 -0
- reconcile/typed_queries/cost_report/cost_namespaces.py +43 -0
- reconcile/typed_queries/cost_report/settings.py +15 -0
- reconcile/typed_queries/dynatrace.py +10 -0
- reconcile/typed_queries/dynatrace_environments.py +14 -0
- reconcile/typed_queries/dynatrace_token_provider_token_specs.py +14 -0
- reconcile/typed_queries/external_resources.py +46 -0
- reconcile/typed_queries/get_state_aws_account.py +20 -0
- reconcile/typed_queries/glitchtip.py +10 -0
- reconcile/typed_queries/jenkins.py +25 -0
- reconcile/typed_queries/jira.py +7 -0
- reconcile/typed_queries/jira_settings.py +16 -0
- reconcile/typed_queries/jiralert_settings.py +22 -0
- reconcile/typed_queries/ocm.py +8 -0
- reconcile/typed_queries/pagerduty_instances.py +2 -7
- reconcile/typed_queries/quay.py +23 -0
- reconcile/typed_queries/repos.py +20 -8
- reconcile/typed_queries/reserved_networks.py +12 -0
- reconcile/typed_queries/saas_files.py +221 -167
- reconcile/typed_queries/slack.py +7 -0
- reconcile/typed_queries/slo_documents.py +12 -0
- reconcile/typed_queries/status_board.py +58 -0
- reconcile/typed_queries/tekton_pipeline_providers.py +1 -2
- reconcile/typed_queries/terraform_namespaces.py +1 -2
- reconcile/typed_queries/terraform_tgw_attachments/__init__.py +0 -0
- reconcile/typed_queries/terraform_tgw_attachments/aws_accounts.py +16 -0
- reconcile/typed_queries/unleash.py +10 -0
- reconcile/typed_queries/users.py +11 -0
- reconcile/typed_queries/vault.py +10 -0
- reconcile/unleash_feature_toggles/__init__.py +0 -0
- reconcile/unleash_feature_toggles/integration.py +287 -0
- reconcile/utils/acs/__init__.py +0 -0
- reconcile/utils/acs/base.py +81 -0
- reconcile/utils/acs/notifiers.py +143 -0
- reconcile/utils/acs/policies.py +163 -0
- reconcile/utils/acs/rbac.py +277 -0
- reconcile/utils/aggregated_list.py +11 -9
- reconcile/utils/amtool.py +6 -4
- reconcile/utils/aws_api.py +279 -66
- reconcile/utils/aws_api_typed/__init__.py +0 -0
- reconcile/utils/aws_api_typed/account.py +23 -0
- reconcile/utils/aws_api_typed/api.py +273 -0
- reconcile/utils/aws_api_typed/dynamodb.py +16 -0
- reconcile/utils/aws_api_typed/iam.py +67 -0
- reconcile/utils/aws_api_typed/organization.py +152 -0
- reconcile/utils/aws_api_typed/s3.py +26 -0
- reconcile/utils/aws_api_typed/service_quotas.py +79 -0
- reconcile/utils/aws_api_typed/sts.py +36 -0
- reconcile/utils/aws_api_typed/support.py +79 -0
- reconcile/utils/aws_helper.py +42 -3
- reconcile/utils/batches.py +11 -0
- reconcile/utils/binary.py +7 -9
- reconcile/utils/cloud_resource_best_practice/__init__.py +0 -0
- reconcile/utils/cloud_resource_best_practice/aws_rds.py +66 -0
- reconcile/utils/clusterhealth/__init__.py +0 -0
- reconcile/utils/clusterhealth/providerbase.py +39 -0
- reconcile/utils/clusterhealth/telemeter.py +39 -0
- reconcile/utils/config.py +3 -4
- reconcile/utils/deadmanssnitch_api.py +86 -0
- reconcile/utils/differ.py +205 -0
- reconcile/utils/disabled_integrations.py +4 -6
- reconcile/utils/dynatrace/__init__.py +0 -0
- reconcile/utils/dynatrace/client.py +93 -0
- reconcile/utils/early_exit_cache.py +289 -0
- reconcile/utils/elasticsearch_exceptions.py +5 -0
- reconcile/utils/environ.py +2 -2
- reconcile/utils/exceptions.py +4 -0
- reconcile/utils/expiration.py +4 -8
- reconcile/utils/extended_early_exit.py +210 -0
- reconcile/utils/external_resource_spec.py +34 -12
- reconcile/utils/external_resources.py +48 -20
- reconcile/utils/filtering.py +16 -0
- reconcile/utils/git.py +49 -16
- reconcile/utils/github_api.py +10 -9
- reconcile/utils/gitlab_api.py +333 -190
- reconcile/utils/glitchtip/client.py +97 -100
- reconcile/utils/glitchtip/models.py +89 -11
- reconcile/utils/gql.py +157 -58
- reconcile/utils/grouping.py +17 -0
- reconcile/utils/helm.py +89 -18
- reconcile/utils/helpers.py +51 -0
- reconcile/utils/imap_client.py +5 -6
- reconcile/utils/internal_groups/__init__.py +0 -0
- reconcile/utils/internal_groups/client.py +160 -0
- reconcile/utils/internal_groups/models.py +71 -0
- reconcile/utils/jenkins_api.py +10 -34
- reconcile/utils/jinja2/__init__.py +0 -0
- reconcile/utils/{jinja2_ext.py → jinja2/extensions.py} +6 -4
- reconcile/utils/jinja2/filters.py +142 -0
- reconcile/utils/jinja2/utils.py +278 -0
- reconcile/utils/jira_client.py +165 -8
- reconcile/utils/jjb_client.py +47 -35
- reconcile/utils/jobcontroller/__init__.py +0 -0
- reconcile/utils/jobcontroller/controller.py +413 -0
- reconcile/utils/jobcontroller/models.py +195 -0
- reconcile/utils/jsonpath.py +4 -5
- reconcile/utils/jump_host.py +13 -12
- reconcile/utils/keycloak.py +106 -0
- reconcile/utils/ldap_client.py +35 -6
- reconcile/utils/lean_terraform_client.py +115 -6
- reconcile/utils/membershipsources/__init__.py +0 -0
- reconcile/utils/membershipsources/app_interface_resolver.py +60 -0
- reconcile/utils/membershipsources/models.py +91 -0
- reconcile/utils/membershipsources/resolver.py +110 -0
- reconcile/utils/merge_request_manager/__init__.py +0 -0
- reconcile/utils/merge_request_manager/merge_request_manager.py +99 -0
- reconcile/utils/merge_request_manager/parser.py +67 -0
- reconcile/utils/metrics.py +511 -1
- reconcile/utils/models.py +123 -0
- reconcile/utils/mr/README.md +198 -0
- reconcile/utils/mr/__init__.py +14 -10
- reconcile/utils/mr/app_interface_reporter.py +2 -2
- reconcile/utils/mr/aws_access.py +4 -4
- reconcile/utils/mr/base.py +51 -31
- reconcile/utils/mr/clusters_updates.py +10 -7
- reconcile/utils/mr/glitchtip_access_reporter.py +2 -4
- reconcile/utils/mr/labels.py +14 -1
- reconcile/utils/mr/notificator.py +1 -3
- reconcile/utils/mr/ocm_update_recommended_version.py +1 -2
- reconcile/utils/mr/ocm_upgrade_scheduler_org_updates.py +7 -3
- reconcile/utils/mr/promote_qontract.py +203 -0
- reconcile/utils/mr/user_maintenance.py +24 -4
- reconcile/utils/oauth2_backend_application_session.py +132 -0
- reconcile/utils/oc.py +194 -170
- reconcile/utils/oc_connection_parameters.py +40 -51
- reconcile/utils/oc_filters.py +11 -13
- reconcile/utils/oc_map.py +14 -35
- reconcile/utils/ocm/__init__.py +30 -1
- reconcile/utils/ocm/addons.py +228 -0
- reconcile/utils/ocm/base.py +618 -5
- reconcile/utils/ocm/cluster_groups.py +5 -56
- reconcile/utils/ocm/clusters.py +111 -99
- reconcile/utils/ocm/identity_providers.py +66 -0
- reconcile/utils/ocm/label_sources.py +75 -0
- reconcile/utils/ocm/labels.py +139 -54
- reconcile/utils/ocm/manifests.py +39 -0
- reconcile/utils/ocm/ocm.py +182 -928
- reconcile/utils/ocm/products.py +758 -0
- reconcile/utils/ocm/search_filters.py +20 -28
- reconcile/utils/ocm/service_log.py +32 -79
- reconcile/utils/ocm/sre_capability_labels.py +51 -0
- reconcile/utils/ocm/status_board.py +66 -0
- reconcile/utils/ocm/subscriptions.py +49 -59
- reconcile/utils/ocm/syncsets.py +39 -0
- reconcile/utils/ocm/upgrades.py +181 -0
- reconcile/utils/ocm_base_client.py +71 -36
- reconcile/utils/openshift_resource.py +113 -67
- reconcile/utils/output.py +18 -11
- reconcile/utils/pagerduty_api.py +16 -10
- reconcile/utils/parse_dhms_duration.py +13 -1
- reconcile/utils/prometheus.py +123 -0
- reconcile/utils/promotion_state.py +56 -19
- reconcile/utils/promtool.py +5 -8
- reconcile/utils/quay_api.py +13 -25
- reconcile/utils/raw_github_api.py +3 -5
- reconcile/utils/repo_owners.py +2 -8
- reconcile/utils/rest_api_base.py +126 -0
- reconcile/utils/rosa/__init__.py +0 -0
- reconcile/utils/rosa/rosa_cli.py +310 -0
- reconcile/utils/rosa/session.py +201 -0
- reconcile/utils/ruamel.py +16 -0
- reconcile/utils/runtime/__init__.py +0 -1
- reconcile/utils/runtime/desired_state_diff.py +9 -20
- reconcile/utils/runtime/environment.py +33 -8
- reconcile/utils/runtime/integration.py +28 -12
- reconcile/utils/runtime/meta.py +1 -3
- reconcile/utils/runtime/runner.py +8 -11
- reconcile/utils/runtime/sharding.py +93 -36
- reconcile/utils/saasherder/__init__.py +1 -1
- reconcile/utils/saasherder/interfaces.py +143 -138
- reconcile/utils/saasherder/models.py +201 -43
- reconcile/utils/saasherder/saasherder.py +508 -378
- reconcile/utils/secret_reader.py +22 -27
- reconcile/utils/semver_helper.py +15 -1
- reconcile/utils/slack_api.py +124 -36
- reconcile/utils/smtp_client.py +1 -2
- reconcile/utils/sqs_gateway.py +10 -6
- reconcile/utils/state.py +276 -127
- reconcile/utils/terraform/config_client.py +6 -7
- reconcile/utils/terraform_client.py +284 -125
- reconcile/utils/terrascript/cloudflare_client.py +38 -17
- reconcile/utils/terrascript/cloudflare_resources.py +67 -18
- reconcile/utils/terrascript/models.py +2 -3
- reconcile/utils/terrascript/resources.py +1 -2
- reconcile/utils/terrascript_aws_client.py +1292 -540
- reconcile/utils/three_way_diff_strategy.py +157 -0
- reconcile/utils/unleash/__init__.py +11 -0
- reconcile/utils/{unleash.py → unleash/client.py} +35 -29
- reconcile/utils/unleash/server.py +145 -0
- reconcile/utils/vault.py +42 -32
- reconcile/utils/vaultsecretref.py +2 -4
- reconcile/utils/vcs.py +250 -0
- reconcile/vault_replication.py +38 -31
- reconcile/vpc_peerings_validator.py +82 -13
- tools/app_interface_metrics_exporter.py +70 -0
- tools/app_interface_reporter.py +44 -157
- tools/cli_commands/container_images_report.py +154 -0
- tools/cli_commands/cost_report/__init__.py +0 -0
- tools/cli_commands/cost_report/aws.py +137 -0
- tools/cli_commands/cost_report/cost_management_api.py +155 -0
- tools/cli_commands/cost_report/model.py +49 -0
- tools/cli_commands/cost_report/openshift.py +166 -0
- tools/cli_commands/cost_report/openshift_cost_optimization.py +187 -0
- tools/cli_commands/cost_report/response.py +124 -0
- tools/cli_commands/cost_report/util.py +72 -0
- tools/cli_commands/cost_report/view.py +524 -0
- tools/cli_commands/erv2.py +620 -0
- tools/cli_commands/gpg_encrypt.py +5 -8
- tools/cli_commands/systems_and_tools.py +489 -0
- tools/glitchtip_access_revalidation.py +1 -1
- tools/qontract_cli.py +2301 -673
- tools/saas_metrics_exporter/__init__.py +0 -0
- tools/saas_metrics_exporter/commit_distance/__init__.py +0 -0
- tools/saas_metrics_exporter/commit_distance/channel.py +63 -0
- tools/saas_metrics_exporter/commit_distance/commit_distance.py +103 -0
- tools/saas_metrics_exporter/commit_distance/metrics.py +19 -0
- tools/saas_metrics_exporter/main.py +99 -0
- tools/saas_promotion_state/__init__.py +0 -0
- tools/saas_promotion_state/saas_promotion_state.py +105 -0
- tools/sd_app_sre_alert_report.py +145 -0
- tools/template_validation.py +107 -0
- e2e_tests/cli.py +0 -83
- e2e_tests/create_namespace.py +0 -43
- e2e_tests/dedicated_admin_rolebindings.py +0 -44
- e2e_tests/dedicated_admin_test_base.py +0 -39
- e2e_tests/default_network_policies.py +0 -47
- e2e_tests/default_project_labels.py +0 -52
- e2e_tests/network_policy_test_base.py +0 -17
- e2e_tests/test_base.py +0 -56
- qontract_reconcile-0.9.1rc298.dist-info/METADATA +0 -63
- qontract_reconcile-0.9.1rc298.dist-info/RECORD +0 -585
- qontract_reconcile-0.9.1rc298.dist-info/top_level.txt +0 -4
- reconcile/ecr_mirror.py +0 -152
- reconcile/github_scanner.py +0 -74
- reconcile/gitlab_integrations.py +0 -63
- reconcile/gql_definitions/ocm_oidc_idp/clusters.py +0 -195
- reconcile/gql_definitions/ocp_release_mirror/ocp_release_mirror.py +0 -287
- reconcile/integrations_validator.py +0 -18
- reconcile/jenkins_plugins.py +0 -129
- reconcile/kafka_clusters.py +0 -208
- reconcile/ocm_cluster_admin.py +0 -42
- reconcile/ocm_oidc_idp.py +0 -198
- reconcile/ocp_release_mirror.py +0 -373
- reconcile/prometheus_rules_tester_old.py +0 -436
- reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager.py +0 -279
- reconcile/saas_auto_promotions_manager/utils/vcs.py +0 -141
- reconcile/sentry_config.py +0 -613
- reconcile/sentry_helper.py +0 -69
- reconcile/test/conftest.py +0 -187
- reconcile/test/fixtures.py +0 -24
- reconcile/test/saas_auto_promotions_manager/conftest.py +0 -69
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py +0 -110
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/data_keys.py +0 -10
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_housekeeping.py +0 -200
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py +0 -151
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py +0 -63
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/data_keys.py +0 -4
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_multiple_namespaces.py +0 -46
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_namespace.py +0 -94
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_single_target.py +0 -44
- reconcile/test/saas_auto_promotions_manager/subscriber/conftest.py +0 -74
- reconcile/test/saas_auto_promotions_manager/subscriber/data_keys.py +0 -11
- reconcile/test/saas_auto_promotions_manager/subscriber/test_content_hash.py +0 -155
- reconcile/test/saas_auto_promotions_manager/subscriber/test_diff.py +0 -173
- reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_config_hash.py +0 -226
- reconcile/test/saas_auto_promotions_manager/subscriber/test_multiple_channels_moving_ref.py +0 -224
- reconcile/test/saas_auto_promotions_manager/subscriber/test_single_channel_with_single_publisher.py +0 -350
- reconcile/test/saas_auto_promotions_manager/test_integration_test.py +0 -129
- reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_multiple_publishers_for_single_channel.py +0 -70
- reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_use_target_config_hash.py +0 -63
- reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_with_auto_promote.py +0 -74
- reconcile/test/saas_auto_promotions_manager/utils/saas_files_inventory/test_saas_files_without_auto_promote.py +0 -65
- reconcile/test/test_aggregated_list.py +0 -237
- reconcile/test/test_amtool.py +0 -37
- reconcile/test/test_auto_promoter.py +0 -295
- reconcile/test/test_aws_ami_share.py +0 -68
- reconcile/test/test_aws_iam_keys.py +0 -70
- reconcile/test/test_aws_iam_password_reset.py +0 -35
- reconcile/test/test_aws_support_cases_sos.py +0 -23
- reconcile/test/test_checkpoint.py +0 -178
- reconcile/test/test_cli.py +0 -41
- reconcile/test/test_closedbox_endpoint_monitoring.py +0 -207
- reconcile/test/test_gabi_authorized_users.py +0 -72
- reconcile/test/test_github_org.py +0 -154
- reconcile/test/test_github_repo_invites.py +0 -123
- reconcile/test/test_gitlab_housekeeping.py +0 -88
- reconcile/test/test_gitlab_labeler.py +0 -129
- reconcile/test/test_gitlab_members.py +0 -283
- reconcile/test/test_instrumented_wrappers.py +0 -18
- reconcile/test/test_integrations_manager.py +0 -995
- reconcile/test/test_jenkins_worker_fleets.py +0 -55
- reconcile/test/test_jump_host.py +0 -117
- reconcile/test/test_ldap_users.py +0 -123
- reconcile/test/test_make.py +0 -28
- reconcile/test/test_ocm_additional_routers.py +0 -134
- reconcile/test/test_ocm_addons_upgrade_scheduler_org.py +0 -149
- reconcile/test/test_ocm_clusters.py +0 -598
- reconcile/test/test_ocm_clusters_manifest_updates.py +0 -89
- reconcile/test/test_ocm_oidc_idp.py +0 -315
- reconcile/test/test_ocm_update_recommended_version.py +0 -145
- reconcile/test/test_ocm_upgrade_scheduler.py +0 -614
- reconcile/test/test_ocm_upgrade_scheduler_org_updater.py +0 -129
- reconcile/test/test_openshift_base.py +0 -730
- reconcile/test/test_openshift_namespace_labels.py +0 -345
- reconcile/test/test_openshift_namespaces.py +0 -256
- reconcile/test/test_openshift_resource.py +0 -415
- reconcile/test/test_openshift_resources_base.py +0 -440
- reconcile/test/test_openshift_saas_deploy_change_tester.py +0 -310
- reconcile/test/test_openshift_tekton_resources.py +0 -253
- reconcile/test/test_openshift_upgrade_watcher.py +0 -146
- reconcile/test/test_prometheus_rules_tester.py +0 -151
- reconcile/test/test_prometheus_rules_tester_old.py +0 -77
- reconcile/test/test_quay_membership.py +0 -86
- reconcile/test/test_quay_mirror.py +0 -109
- reconcile/test/test_quay_mirror_org.py +0 -70
- reconcile/test/test_quay_repos.py +0 -59
- reconcile/test/test_queries.py +0 -53
- reconcile/test/test_repo_owners.py +0 -47
- reconcile/test/test_requests_sender.py +0 -139
- reconcile/test/test_saasherder.py +0 -1074
- reconcile/test/test_saasherder_allowed_secret_paths.py +0 -127
- reconcile/test/test_secret_reader.py +0 -153
- reconcile/test/test_slack_base.py +0 -185
- reconcile/test/test_slack_usergroups.py +0 -744
- reconcile/test/test_sql_query.py +0 -19
- reconcile/test/test_terraform_cloudflare_dns.py +0 -117
- reconcile/test/test_terraform_cloudflare_resources.py +0 -106
- reconcile/test/test_terraform_cloudflare_users.py +0 -749
- reconcile/test/test_terraform_resources.py +0 -257
- reconcile/test/test_terraform_tgw_attachments.py +0 -631
- reconcile/test/test_terraform_users.py +0 -57
- reconcile/test/test_terraform_vpc_peerings.py +0 -499
- reconcile/test/test_terraform_vpc_peerings_build_desired_state.py +0 -1061
- reconcile/test/test_unleash.py +0 -138
- reconcile/test/test_utils_aws_api.py +0 -240
- reconcile/test/test_utils_aws_helper.py +0 -80
- reconcile/test/test_utils_cluster_version_data.py +0 -177
- reconcile/test/test_utils_data_structures.py +0 -13
- reconcile/test/test_utils_disabled_integrations.py +0 -86
- reconcile/test/test_utils_expiration.py +0 -109
- reconcile/test/test_utils_external_resource_spec.py +0 -383
- reconcile/test/test_utils_external_resources.py +0 -247
- reconcile/test/test_utils_github_api.py +0 -73
- reconcile/test/test_utils_gitlab_api.py +0 -20
- reconcile/test/test_utils_gpg.py +0 -69
- reconcile/test/test_utils_gql.py +0 -81
- reconcile/test/test_utils_helm.py +0 -306
- reconcile/test/test_utils_helpers.py +0 -55
- reconcile/test/test_utils_imap_client.py +0 -65
- reconcile/test/test_utils_jjb_client.py +0 -52
- reconcile/test/test_utils_jsonpath.py +0 -286
- reconcile/test/test_utils_ldap_client.py +0 -51
- reconcile/test/test_utils_mr.py +0 -226
- reconcile/test/test_utils_mr_clusters_updates.py +0 -77
- reconcile/test/test_utils_oc.py +0 -984
- reconcile/test/test_utils_ocm.py +0 -110
- reconcile/test/test_utils_pagerduty_api.py +0 -251
- reconcile/test/test_utils_parse_dhms_duration.py +0 -34
- reconcile/test/test_utils_password_validator.py +0 -155
- reconcile/test/test_utils_quay_api.py +0 -86
- reconcile/test/test_utils_semver_helper.py +0 -19
- reconcile/test/test_utils_sharding.py +0 -56
- reconcile/test/test_utils_slack_api.py +0 -439
- reconcile/test/test_utils_smtp_client.py +0 -73
- reconcile/test/test_utils_state.py +0 -256
- reconcile/test/test_utils_terraform.py +0 -13
- reconcile/test/test_utils_terraform_client.py +0 -585
- reconcile/test/test_utils_terraform_config_client.py +0 -219
- reconcile/test/test_utils_terrascript_aws_client.py +0 -277
- reconcile/test/test_utils_terrascript_cloudflare_client.py +0 -597
- reconcile/test/test_utils_terrascript_cloudflare_resources.py +0 -26
- reconcile/test/test_vault_replication.py +0 -515
- reconcile/test/test_vault_utils.py +0 -47
- reconcile/test/test_version_bump.py +0 -18
- reconcile/test/test_vpc_peerings_validator.py +0 -103
- reconcile/test/test_wrong_region.py +0 -78
- reconcile/typed_queries/glitchtip_settings.py +0 -18
- reconcile/typed_queries/ocp_release_mirror.py +0 -11
- reconcile/unleash_watcher.py +0 -120
- reconcile/utils/git_secrets.py +0 -63
- reconcile/utils/mr/auto_promoter.py +0 -218
- reconcile/utils/sentry_client.py +0 -383
- release/test_version.py +0 -50
- release/version.py +0 -100
- tools/test/test_qontract_cli.py +0 -60
- tools/test/test_sre_checkpoints.py +0 -79
- /e2e_tests/__init__.py → /reconcile/aus/upgrades.py +0 -0
- /reconcile/{gql_definitions/ocp_release_mirror → aws_account_manager}/__init__.py +0 -0
- /reconcile/{test → aws_ami_cleanup}/__init__.py +0 -0
- /reconcile/{test/saas_auto_promotions_manager → aws_cloudwatch_log_retention}/__init__.py +0 -0
- /reconcile/{test/saas_auto_promotions_manager/merge_request_manager → aws_saml_idp}/__init__.py +0 -0
- /reconcile/{test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager → aws_saml_roles}/__init__.py +0 -0
- /reconcile/{test/saas_auto_promotions_manager/merge_request_manager/renderer → aws_version_sync}/__init__.py +0 -0
- /reconcile/{test/saas_auto_promotions_manager/subscriber → aws_version_sync/merge_request_manager}/__init__.py +0 -0
- /reconcile/{test/saas_auto_promotions_manager/utils → cluster_auth_rhidp}/__init__.py +0 -0
- /reconcile/{test/saas_auto_promotions_manager/utils/saas_files_inventory → dynatrace_token_provider}/__init__.py +0 -0
- {release → reconcile/endpoints_discovery}/__init__.py +0 -0
- {tools/test → reconcile/external_resources}/__init__.py +0 -0
@@ -0,0 +1,196 @@
|
|
1
|
+
import logging
|
2
|
+
from collections import defaultdict
|
3
|
+
from datetime import timedelta
|
4
|
+
|
5
|
+
from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment
|
6
|
+
from reconcile.oum.base import OCMUserManagementIntegration
|
7
|
+
from reconcile.oum.labelset import build_cluster_config_from_labels
|
8
|
+
from reconcile.oum.models import (
|
9
|
+
ClusterError,
|
10
|
+
ClusterUserManagementConfiguration,
|
11
|
+
ClusterUserManagementSpec,
|
12
|
+
OrganizationUserManagementConfiguration,
|
13
|
+
)
|
14
|
+
from reconcile.utils.ocm.base import (
|
15
|
+
OCMClusterServiceLogCreateModel,
|
16
|
+
OCMServiceLogSeverity,
|
17
|
+
)
|
18
|
+
from reconcile.utils.ocm.clusters import (
|
19
|
+
ClusterDetails,
|
20
|
+
discover_clusters_by_labels,
|
21
|
+
)
|
22
|
+
from reconcile.utils.ocm.labels import build_container_for_prefix
|
23
|
+
from reconcile.utils.ocm.search_filters import Filter
|
24
|
+
from reconcile.utils.ocm.service_log import create_service_log
|
25
|
+
from reconcile.utils.ocm.sre_capability_labels import sre_capability_label_key
|
26
|
+
from reconcile.utils.ocm_base_client import (
|
27
|
+
OCMBaseClient,
|
28
|
+
init_ocm_base_client,
|
29
|
+
)
|
30
|
+
|
31
|
+
|
32
|
+
class OCMStandaloneUserManagementIntegration(OCMUserManagementIntegration):
|
33
|
+
@property
|
34
|
+
def name(self) -> str:
|
35
|
+
return "ocm-standalone-user-management"
|
36
|
+
|
37
|
+
def get_user_mgmt_config_for_ocm_env(
|
38
|
+
self, ocm_env: OCMEnvironment, org_ids: set[str] | None
|
39
|
+
) -> dict[str, OrganizationUserManagementConfiguration]:
|
40
|
+
ocm_api = init_ocm_base_client(ocm_env, self.secret_reader)
|
41
|
+
clusters_by_org = discover_clusters(
|
42
|
+
ocm_api=ocm_api,
|
43
|
+
org_ids=org_ids,
|
44
|
+
)
|
45
|
+
configs: dict[str, OrganizationUserManagementConfiguration] = {}
|
46
|
+
for org_id, org_clusters in clusters_by_org.items():
|
47
|
+
configs[org_id] = build_user_management_configurations(
|
48
|
+
org_id=org_id,
|
49
|
+
clusters=org_clusters,
|
50
|
+
providers=self.group_member_provider_ids,
|
51
|
+
)
|
52
|
+
return configs
|
53
|
+
|
54
|
+
def signal_cluster_reconcile_success(
|
55
|
+
self,
|
56
|
+
dry_run: bool,
|
57
|
+
ocm_api: OCMBaseClient,
|
58
|
+
spec: ClusterUserManagementSpec,
|
59
|
+
message: str,
|
60
|
+
) -> None:
|
61
|
+
logging.info(message)
|
62
|
+
if dry_run:
|
63
|
+
return
|
64
|
+
create_service_log(
|
65
|
+
ocm_api=ocm_api,
|
66
|
+
service_log=OCMClusterServiceLogCreateModel(
|
67
|
+
cluster_uuid=spec.cluster.ocm_cluster.external_id,
|
68
|
+
severity=OCMServiceLogSeverity.Info,
|
69
|
+
summary="Reconciled cluster groups",
|
70
|
+
description=message,
|
71
|
+
service_name=self.name,
|
72
|
+
),
|
73
|
+
)
|
74
|
+
|
75
|
+
def signal_cluster_validation_error(
|
76
|
+
self,
|
77
|
+
dry_run: bool,
|
78
|
+
ocm_api: OCMBaseClient,
|
79
|
+
spec: ClusterUserManagementSpec,
|
80
|
+
error: Exception,
|
81
|
+
) -> None:
|
82
|
+
"""
|
83
|
+
The standalone user management capability will not fail on a configuration
|
84
|
+
validation issue. If issues should be noticed by an SRE team, alerts based on
|
85
|
+
the `oum_organization_validation_errors` metric in the `reconcile.oum.metrics`
|
86
|
+
module should be set up.
|
87
|
+
"""
|
88
|
+
logging.warning(
|
89
|
+
"Failed to reconcile cluster user group configuration in "
|
90
|
+
f"OCM organization {spec.cluster.organization_id}",
|
91
|
+
exc_info=error,
|
92
|
+
)
|
93
|
+
if dry_run:
|
94
|
+
return
|
95
|
+
create_service_log(
|
96
|
+
ocm_api=ocm_api,
|
97
|
+
service_log=OCMClusterServiceLogCreateModel(
|
98
|
+
cluster_uuid=spec.cluster.ocm_cluster.external_id,
|
99
|
+
severity=OCMServiceLogSeverity.Error,
|
100
|
+
summary="Failed to reconcile cluster user group configuration",
|
101
|
+
description=str(error),
|
102
|
+
service_name=self.name,
|
103
|
+
),
|
104
|
+
dedup_interval=timedelta(days=2),
|
105
|
+
)
|
106
|
+
|
107
|
+
def signal_cluster_reconcile_error(
|
108
|
+
self,
|
109
|
+
dry_run: bool,
|
110
|
+
ocm_api: OCMBaseClient,
|
111
|
+
spec: ClusterUserManagementSpec,
|
112
|
+
error: Exception,
|
113
|
+
) -> None:
|
114
|
+
"""
|
115
|
+
The standalone user management capability will not fail on a cluster
|
116
|
+
reconciliation issue. If issues should be noticed by an SRE team, alerts based on
|
117
|
+
the `oum_organization_reconcile_errors` metric in the `reconcile.oum.metrics`
|
118
|
+
module should be set up.
|
119
|
+
|
120
|
+
The user is not notified via service logs because such reconcile issues are not
|
121
|
+
actionable to them.
|
122
|
+
"""
|
123
|
+
logging.warning(
|
124
|
+
"Failed to reconcile cluster user group configuration on "
|
125
|
+
f"cluster {spec.cluster.ocm_cluster.name} (id={spec.cluster.ocm_cluster.id}) "
|
126
|
+
f"in the OCM organization {spec.cluster.organization_id}",
|
127
|
+
exc_info=error,
|
128
|
+
)
|
129
|
+
|
130
|
+
|
131
|
+
def user_mgmt_label_key(config_atom: str) -> str:
|
132
|
+
"""
|
133
|
+
Generates label keys for the user management authz capability, compliant with the naming
|
134
|
+
scheme defined in https://service.pages.redhat.com/dev-guidelines/docs/sre-capabilities/framework/ocm-labels/
|
135
|
+
"""
|
136
|
+
return sre_capability_label_key("user-mgmt", config_atom)
|
137
|
+
|
138
|
+
|
139
|
+
def discover_clusters(
|
140
|
+
ocm_api: OCMBaseClient,
|
141
|
+
org_ids: set[str] | None = None,
|
142
|
+
) -> dict[str, list[ClusterDetails]]:
|
143
|
+
"""
|
144
|
+
Discover all clusters with user management enabled on their subscription
|
145
|
+
or their organization. Return the discovered clusters grouped by OCM organization ID.
|
146
|
+
|
147
|
+
If `org_ids` is provided, only clusters from the specified organizations will be returned.
|
148
|
+
"""
|
149
|
+
clusters = discover_clusters_by_labels(
|
150
|
+
ocm_api=ocm_api,
|
151
|
+
label_filter=Filter().like("key", user_mgmt_label_key("%")),
|
152
|
+
)
|
153
|
+
|
154
|
+
# group by org ID
|
155
|
+
# optionally also filter on org IDs
|
156
|
+
clusters_by_org: dict[str, list[ClusterDetails]] = defaultdict(list)
|
157
|
+
for c in clusters:
|
158
|
+
passed_ocm_filters = org_ids is None or c.organization_id in org_ids
|
159
|
+
if passed_ocm_filters:
|
160
|
+
clusters_by_org[c.organization_id].append(c)
|
161
|
+
|
162
|
+
return clusters_by_org
|
163
|
+
|
164
|
+
|
165
|
+
def build_user_management_configurations(
|
166
|
+
org_id: str,
|
167
|
+
clusters: list[ClusterDetails],
|
168
|
+
providers: set[str],
|
169
|
+
) -> OrganizationUserManagementConfiguration:
|
170
|
+
"""
|
171
|
+
Extracts the user management configuration from the cluster labels.
|
172
|
+
"""
|
173
|
+
org_config = OrganizationUserManagementConfiguration(org_id=org_id)
|
174
|
+
for c in clusters:
|
175
|
+
cluster_config = ClusterUserManagementConfiguration(cluster=c)
|
176
|
+
org_config.cluster_configs.append(cluster_config)
|
177
|
+
for p in providers:
|
178
|
+
provider_org_labels = build_container_for_prefix(
|
179
|
+
c.organization_labels, user_mgmt_label_key(f"{p}."), True
|
180
|
+
)
|
181
|
+
provider_subs_labels = build_container_for_prefix(
|
182
|
+
c.subscription_labels, user_mgmt_label_key(f"{p}."), True
|
183
|
+
)
|
184
|
+
if provider_org_labels or provider_subs_labels:
|
185
|
+
try:
|
186
|
+
role_groups = build_cluster_config_from_labels(
|
187
|
+
provider=p,
|
188
|
+
org_labels=provider_org_labels,
|
189
|
+
subscription_labels=provider_subs_labels,
|
190
|
+
)
|
191
|
+
for role_id, group_refs in role_groups.items():
|
192
|
+
cluster_config.roles[role_id].extend(group_refs)
|
193
|
+
|
194
|
+
except Exception as e:
|
195
|
+
cluster_config.errors.append(ClusterError(message=str(e)))
|
196
|
+
return org_config
|
@@ -1,16 +1,15 @@
|
|
1
1
|
import json
|
2
2
|
import logging
|
3
3
|
import sys
|
4
|
+
from collections import defaultdict
|
4
5
|
from collections.abc import (
|
5
6
|
Iterable,
|
6
7
|
Mapping,
|
7
8
|
)
|
8
|
-
from typing import
|
9
|
-
Any,
|
10
|
-
Optional,
|
11
|
-
)
|
9
|
+
from typing import Any
|
12
10
|
|
13
11
|
import yaml
|
12
|
+
from deepdiff import DeepHash
|
14
13
|
from pydantic import BaseModel
|
15
14
|
from sretoolbox.utils import threaded
|
16
15
|
|
@@ -27,6 +26,7 @@ from reconcile.utils import (
|
|
27
26
|
gql,
|
28
27
|
promtool,
|
29
28
|
)
|
29
|
+
from reconcile.utils.jinja2.utils import process_extracurlyjinja2_template
|
30
30
|
from reconcile.utils.runtime.integration import DesiredStateShardConfig
|
31
31
|
from reconcile.utils.semver_helper import make_semver
|
32
32
|
from reconcile.utils.structs import CommandExecutionResult
|
@@ -55,8 +55,8 @@ class Test(BaseModel):
|
|
55
55
|
rule_path: str
|
56
56
|
rule: dict
|
57
57
|
rule_length: int
|
58
|
-
tests:
|
59
|
-
result:
|
58
|
+
tests: list[TestContent] | None
|
59
|
+
result: CommandExecutionResult | None = None
|
60
60
|
|
61
61
|
|
62
62
|
class RuleToFetch(BaseModel):
|
@@ -89,7 +89,7 @@ def fetch_rule_and_tests(
|
|
89
89
|
test_raw_yaml = gql.get_resource(test_path)["content"]
|
90
90
|
|
91
91
|
if rule.resource["type"] == "resource-template-extracurlyjinja2":
|
92
|
-
test_raw_yaml =
|
92
|
+
test_raw_yaml = process_extracurlyjinja2_template(
|
93
93
|
body=test_raw_yaml,
|
94
94
|
vars=variables,
|
95
95
|
settings=vault_settings.dict(by_alias=True),
|
@@ -119,18 +119,21 @@ def fetch_rule_and_tests(
|
|
119
119
|
def get_rules_and_tests(
|
120
120
|
vault_settings: AppInterfaceSettingsV1,
|
121
121
|
thread_pool_size: int,
|
122
|
-
|
122
|
+
cluster_names: Iterable[str] | None = None,
|
123
123
|
) -> list[Test]:
|
124
124
|
"""Iterates through all namespaces and returns a list of tests to run"""
|
125
125
|
namespace_with_prom_rules, _ = orb.get_namespaces(
|
126
126
|
PROVIDERS,
|
127
|
-
|
127
|
+
cluster_names=cluster_names if cluster_names else [],
|
128
128
|
namespace_name=NAMESPACE_NAME,
|
129
129
|
)
|
130
130
|
|
131
131
|
iterable = []
|
132
132
|
for namespace in namespace_with_prom_rules:
|
133
|
-
|
133
|
+
prom_rules = [
|
134
|
+
r for r in namespace["openshiftResources"] if r["provider"] in PROVIDERS
|
135
|
+
]
|
136
|
+
for resource in prom_rules:
|
134
137
|
iterable.append(
|
135
138
|
RuleToFetch(
|
136
139
|
namespace=namespace,
|
@@ -219,14 +222,14 @@ def check_rules_and_tests(
|
|
219
222
|
vault_settings: AppInterfaceSettingsV1,
|
220
223
|
alerting_services: Iterable[str],
|
221
224
|
thread_pool_size: int,
|
222
|
-
|
225
|
+
cluster_names: Iterable[str] | None = None,
|
223
226
|
) -> list[Test]:
|
224
227
|
"""Fetch rules and associated tests, run checks on rules and tests if they exist
|
225
228
|
and return a list of failed checks/tests"""
|
226
229
|
tests = get_rules_and_tests(
|
227
230
|
vault_settings=vault_settings,
|
228
231
|
thread_pool_size=thread_pool_size,
|
229
|
-
|
232
|
+
cluster_names=cluster_names,
|
230
233
|
)
|
231
234
|
threaded.run(
|
232
235
|
func=run_test,
|
@@ -241,14 +244,14 @@ def check_rules_and_tests(
|
|
241
244
|
|
242
245
|
|
243
246
|
def run(
|
244
|
-
dry_run: bool, thread_pool_size: int,
|
247
|
+
dry_run: bool, thread_pool_size: int, cluster_names: Iterable[str] | None = None
|
245
248
|
) -> None:
|
246
249
|
"""Check prometheus rules syntax and run the tests associated to them"""
|
247
250
|
orb.QONTRACT_INTEGRATION = QONTRACT_INTEGRATION
|
248
251
|
orb.QONTRACT_INTEGRATION_VERSION = QONTRACT_INTEGRATION_VERSION
|
249
252
|
|
250
253
|
failed_tests = check_rules_and_tests(
|
251
|
-
|
254
|
+
cluster_names=cluster_names,
|
252
255
|
vault_settings=get_app_interface_vault_settings(),
|
253
256
|
alerting_services=get_alerting_services(),
|
254
257
|
thread_pool_size=thread_pool_size,
|
@@ -266,14 +269,19 @@ def run(
|
|
266
269
|
def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
|
267
270
|
# early_exit doesn't support dataclasses or BaseModels yet, hence we have to store dicts
|
268
271
|
with orb.early_exit_monkey_patch():
|
272
|
+
state_for_clusters = defaultdict(list)
|
273
|
+
tests = get_rules_and_tests(
|
274
|
+
vault_settings=get_app_interface_vault_settings(),
|
275
|
+
thread_pool_size=10,
|
276
|
+
)
|
277
|
+
for t in tests:
|
278
|
+
state_for_clusters[t.cluster_name].append(t)
|
279
|
+
|
269
280
|
state = {
|
270
|
-
"
|
271
|
-
|
272
|
-
for
|
273
|
-
|
274
|
-
thread_pool_size=10,
|
275
|
-
)
|
276
|
-
]
|
281
|
+
"state": {
|
282
|
+
cluster: {"shard": cluster, "hash": DeepHash(state).get(state)}
|
283
|
+
for cluster, state in state_for_clusters.items()
|
284
|
+
}
|
277
285
|
}
|
278
286
|
|
279
287
|
return state
|
@@ -281,7 +289,7 @@ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
|
|
281
289
|
|
282
290
|
def desired_state_shard_config() -> DesiredStateShardConfig:
|
283
291
|
return DesiredStateShardConfig(
|
284
|
-
shard_arg_name="
|
285
|
-
shard_path_selectors={"
|
292
|
+
shard_arg_name="cluster_names",
|
293
|
+
shard_path_selectors={"state.*.shard"},
|
286
294
|
sharded_run_review=lambda proposal: len(proposal.proposed_shards) <= 4,
|
287
295
|
)
|
reconcile/quay_base.py
CHANGED
@@ -22,7 +22,10 @@ def get_quay_api_store():
|
|
22
22
|
org_name = org_data["name"]
|
23
23
|
org_key = OrgKey(instance_name, org_name)
|
24
24
|
base_url = org_data["instance"]["url"]
|
25
|
-
|
25
|
+
automation_token = org_data["automationToken"]
|
26
|
+
if not automation_token:
|
27
|
+
continue
|
28
|
+
token = secret_reader.read(automation_token)
|
26
29
|
|
27
30
|
if org_data.get("mirror"):
|
28
31
|
mirror = OrgKey(
|
reconcile/quay_membership.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
import sys
|
3
3
|
from collections.abc import Sequence
|
4
|
-
from typing import Union
|
5
4
|
|
6
5
|
from reconcile.gql_definitions.quay_membership import quay_membership
|
7
6
|
from reconcile.gql_definitions.quay_membership.quay_membership import (
|
@@ -81,7 +80,7 @@ def fetch_current_state(quay_api_store):
|
|
81
80
|
return state
|
82
81
|
|
83
82
|
|
84
|
-
def get_usernames(users: Sequence[
|
83
|
+
def get_usernames(users: Sequence[UserV1 | BotV1]) -> list[str]:
|
85
84
|
return [u.quay_username for u in users if u.quay_username]
|
86
85
|
|
87
86
|
|
reconcile/quay_mirror.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import logging
|
2
2
|
import os
|
3
|
-
import re
|
4
3
|
import sys
|
5
4
|
import tempfile
|
6
5
|
import time
|
@@ -11,9 +10,10 @@ from collections import (
|
|
11
10
|
from collections.abc import Iterable
|
12
11
|
from typing import (
|
13
12
|
Any,
|
14
|
-
|
13
|
+
Self,
|
15
14
|
)
|
16
15
|
|
16
|
+
import requests
|
17
17
|
from requests import Response
|
18
18
|
from sretoolbox.container.image import (
|
19
19
|
ImageComparisonError,
|
@@ -28,6 +28,7 @@ from reconcile.utils import (
|
|
28
28
|
metrics,
|
29
29
|
sharding,
|
30
30
|
)
|
31
|
+
from reconcile.utils.helpers import match_patterns
|
31
32
|
from reconcile.utils.instrumented_wrappers import InstrumentedImage as Image
|
32
33
|
from reconcile.utils.instrumented_wrappers import InstrumentedSkopeo as Skopeo
|
33
34
|
from reconcile.utils.secret_reader import SecretReader
|
@@ -36,12 +37,12 @@ _LOG = logging.getLogger(__name__)
|
|
36
37
|
|
37
38
|
QONTRACT_INTEGRATION = "quay-mirror"
|
38
39
|
CONTROL_FILE_NAME = "qontract-reconcile-quay-mirror.timestamp"
|
40
|
+
REQUEST_TIMEOUT = 60
|
39
41
|
|
40
42
|
OrgKey = namedtuple("OrgKey", ["instance", "org_name"])
|
41
43
|
|
42
44
|
|
43
45
|
class QuayMirror:
|
44
|
-
|
45
46
|
QUAY_ORG_CATALOG_QUERY = """
|
46
47
|
{
|
47
48
|
quay_orgs: quay_orgs_v1 {
|
@@ -65,10 +66,11 @@ class QuayMirror:
|
|
65
66
|
def __init__(
|
66
67
|
self,
|
67
68
|
dry_run: bool = False,
|
68
|
-
control_file_dir:
|
69
|
-
compare_tags:
|
69
|
+
control_file_dir: str | None = None,
|
70
|
+
compare_tags: bool | None = None,
|
70
71
|
compare_tags_interval: int = 86400,
|
71
|
-
|
72
|
+
repository_urls: Iterable[str] | None = None,
|
73
|
+
exclude_repository_urls: Iterable[str] | None = None,
|
72
74
|
) -> None:
|
73
75
|
self.dry_run = dry_run
|
74
76
|
self.gqlapi = gql.get_api()
|
@@ -78,7 +80,8 @@ class QuayMirror:
|
|
78
80
|
self.push_creds = self._get_push_creds()
|
79
81
|
self.compare_tags = compare_tags
|
80
82
|
self.compare_tags_interval = compare_tags_interval
|
81
|
-
self.
|
83
|
+
self.repository_urls = repository_urls
|
84
|
+
self.exclude_repository_urls = exclude_repository_urls
|
82
85
|
|
83
86
|
self.response_cache_hits = metrics.cache_hits.labels(
|
84
87
|
integration=QONTRACT_INTEGRATION,
|
@@ -109,7 +112,14 @@ class QuayMirror:
|
|
109
112
|
tempfile.gettempdir(), CONTROL_FILE_NAME
|
110
113
|
)
|
111
114
|
|
112
|
-
self._has_enough_time_passed_since_last_compare_tags:
|
115
|
+
self._has_enough_time_passed_since_last_compare_tags: bool | None = None
|
116
|
+
self.session = requests.Session()
|
117
|
+
|
118
|
+
def __enter__(self) -> Self:
|
119
|
+
return self
|
120
|
+
|
121
|
+
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
|
122
|
+
self.session.close()
|
113
123
|
|
114
124
|
def run(self) -> None:
|
115
125
|
sync_tasks = self.process_sync_tasks()
|
@@ -130,10 +140,20 @@ class QuayMirror:
|
|
130
140
|
|
131
141
|
@classmethod
|
132
142
|
def process_repos_query(
|
133
|
-
cls,
|
143
|
+
cls,
|
144
|
+
repository_urls: Iterable[str] | None = None,
|
145
|
+
exclude_repository_urls: Iterable[str] | None = None,
|
146
|
+
session: requests.Session | None = None,
|
147
|
+
timeout: int = REQUEST_TIMEOUT,
|
134
148
|
) -> defaultdict[OrgKey, list[dict[str, Any]]]:
|
135
149
|
apps = queries.get_quay_repos()
|
136
150
|
|
151
|
+
if repository_urls:
|
152
|
+
repository_urls = set(repository_urls)
|
153
|
+
|
154
|
+
if exclude_repository_urls:
|
155
|
+
exclude_repository_urls = set(exclude_repository_urls)
|
156
|
+
|
137
157
|
summary = defaultdict(list)
|
138
158
|
|
139
159
|
for app in apps:
|
@@ -148,14 +168,25 @@ class QuayMirror:
|
|
148
168
|
server_url = quay_repo["org"]["instance"]["url"]
|
149
169
|
|
150
170
|
for item in quay_repo["items"]:
|
151
|
-
if
|
171
|
+
if item["mirror"] is None:
|
152
172
|
continue
|
153
173
|
|
154
|
-
|
174
|
+
mirror_url = item["mirror"]["url"]
|
175
|
+
|
176
|
+
if repository_urls and mirror_url not in repository_urls:
|
177
|
+
continue
|
178
|
+
|
179
|
+
if (
|
180
|
+
exclude_repository_urls
|
181
|
+
and mirror_url in exclude_repository_urls
|
182
|
+
):
|
155
183
|
continue
|
156
184
|
|
157
185
|
mirror_image = Image(
|
158
|
-
|
186
|
+
mirror_url,
|
187
|
+
response_cache=cls.response_cache,
|
188
|
+
session=session,
|
189
|
+
timeout=timeout,
|
159
190
|
)
|
160
191
|
if mirror_image.registry == "docker.io" and item["public"]:
|
161
192
|
_LOG.error(
|
@@ -166,39 +197,53 @@ class QuayMirror:
|
|
166
197
|
sys.exit(ExitCodes.ERROR)
|
167
198
|
|
168
199
|
org_key = OrgKey(instance, org)
|
169
|
-
summary[org_key].append(
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
}
|
175
|
-
)
|
200
|
+
summary[org_key].append({
|
201
|
+
"name": item["name"],
|
202
|
+
"mirror": item["mirror"],
|
203
|
+
"server_url": server_url,
|
204
|
+
})
|
176
205
|
return summary
|
177
206
|
|
178
207
|
@staticmethod
|
179
|
-
def sync_tag(
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
208
|
+
def sync_tag(
|
209
|
+
tags: Iterable[str] | None,
|
210
|
+
tags_exclude: Iterable[str] | None,
|
211
|
+
candidate: str,
|
212
|
+
) -> bool:
|
213
|
+
"""
|
214
|
+
Determine if the candidate tag should sync, tags_exclude check take precedence.
|
215
|
+
:param tags: regex patterns to filter, match means to sync, None means no filter
|
216
|
+
:param tags_exclude: regex patterns to filter, match means not to sync, None means no filter
|
217
|
+
:param candidate: tag to check
|
218
|
+
:return: bool, True means to sync, False means not to sync
|
219
|
+
"""
|
220
|
+
if not tags and not tags_exclude:
|
192
221
|
return True
|
193
222
|
|
194
|
-
|
195
|
-
|
196
|
-
|
223
|
+
if not tags:
|
224
|
+
# only tags_exclude provided
|
225
|
+
assert tags_exclude # mypy can't infer not None
|
226
|
+
return not match_patterns(tags_exclude, candidate)
|
227
|
+
|
228
|
+
if not tags_exclude:
|
229
|
+
# only tags provided
|
230
|
+
return match_patterns(tags, candidate)
|
231
|
+
|
232
|
+
# both tags and tags_exclude provided
|
233
|
+
return not match_patterns(
|
234
|
+
tags_exclude,
|
235
|
+
candidate,
|
236
|
+
) and match_patterns(
|
237
|
+
tags,
|
238
|
+
candidate,
|
239
|
+
)
|
197
240
|
|
198
241
|
def process_sync_tasks(self):
|
199
242
|
if self.is_compare_tags:
|
200
243
|
_LOG.warning("Making a compare-tags run. This is a slow operation.")
|
201
|
-
summary = self.process_repos_query(
|
244
|
+
summary = self.process_repos_query(
|
245
|
+
self.repository_urls, self.exclude_repository_urls
|
246
|
+
)
|
202
247
|
sync_tasks = defaultdict(list)
|
203
248
|
for org_key, data in summary.items():
|
204
249
|
org = org_key.org_name
|
@@ -209,6 +254,8 @@ class QuayMirror:
|
|
209
254
|
username=push_creds[0],
|
210
255
|
password=push_creds[1],
|
211
256
|
response_cache=self.response_cache,
|
257
|
+
session=self.session,
|
258
|
+
timeout=REQUEST_TIMEOUT,
|
212
259
|
)
|
213
260
|
|
214
261
|
mirror_url = item["mirror"]["url"]
|
@@ -228,6 +275,8 @@ class QuayMirror:
|
|
228
275
|
username=username,
|
229
276
|
password=password,
|
230
277
|
response_cache=self.response_cache,
|
278
|
+
session=self.session,
|
279
|
+
timeout=REQUEST_TIMEOUT,
|
231
280
|
)
|
232
281
|
|
233
282
|
tags = item["mirror"].get("tags")
|
@@ -305,13 +354,11 @@ class QuayMirror:
|
|
305
354
|
_LOG.debug(
|
306
355
|
"Image %s and mirror %s are out of sync", downstream, upstream
|
307
356
|
)
|
308
|
-
sync_tasks[org_key].append(
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
}
|
314
|
-
)
|
357
|
+
sync_tasks[org_key].append({
|
358
|
+
"mirror_url": str(upstream),
|
359
|
+
"mirror_creds": mirror_creds,
|
360
|
+
"image_url": str(downstream),
|
361
|
+
})
|
315
362
|
|
316
363
|
return sync_tasks
|
317
364
|
|
@@ -336,20 +383,17 @@ class QuayMirror:
|
|
336
383
|
@staticmethod
|
337
384
|
def check_compare_tags_elapsed_time(path, interval) -> bool:
|
338
385
|
try:
|
339
|
-
with open(path, "
|
386
|
+
with open(path, encoding="locale") as file_obj:
|
340
387
|
last_compare_tags = float(file_obj.read())
|
341
388
|
except FileNotFoundError:
|
342
389
|
return True
|
343
390
|
|
344
391
|
next_compare_tags = last_compare_tags + interval
|
345
|
-
|
346
|
-
return True
|
347
|
-
|
348
|
-
return False
|
392
|
+
return time.time() >= next_compare_tags
|
349
393
|
|
350
394
|
@staticmethod
|
351
395
|
def record_timestamp(path) -> None:
|
352
|
-
with open(path, "w") as file_object:
|
396
|
+
with open(path, "w", encoding="locale") as file_object:
|
353
397
|
file_object.write(str(time.time()))
|
354
398
|
|
355
399
|
def _get_push_creds(self):
|
@@ -372,20 +416,26 @@ class QuayMirror:
|
|
372
416
|
|
373
417
|
def run(
|
374
418
|
dry_run,
|
375
|
-
control_file_dir:
|
376
|
-
compare_tags:
|
419
|
+
control_file_dir: str | None,
|
420
|
+
compare_tags: bool | None,
|
377
421
|
compare_tags_interval: int,
|
378
|
-
|
422
|
+
repository_urls: Iterable[str] | None,
|
423
|
+
exclude_repository_urls: Iterable[str] | None,
|
379
424
|
):
|
380
|
-
|
381
|
-
dry_run,
|
382
|
-
|
383
|
-
|
425
|
+
with QuayMirror(
|
426
|
+
dry_run,
|
427
|
+
control_file_dir,
|
428
|
+
compare_tags,
|
429
|
+
compare_tags_interval,
|
430
|
+
repository_urls,
|
431
|
+
exclude_repository_urls,
|
432
|
+
) as quay_mirror:
|
433
|
+
quay_mirror.run()
|
384
434
|
|
385
435
|
|
386
436
|
def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
437
|
+
with QuayMirror(dry_run=True) as quay_mirror:
|
438
|
+
return {
|
439
|
+
"repos": quay_mirror.process_repos_query(session=quay_mirror.session),
|
440
|
+
"orgs": quay_mirror.push_creds,
|
441
|
+
}
|