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
reconcile/utils/secret_reader.py
CHANGED
@@ -5,13 +5,11 @@ from abc import (
|
|
5
5
|
from collections.abc import Mapping
|
6
6
|
from typing import (
|
7
7
|
Any,
|
8
|
-
Optional,
|
9
8
|
Protocol,
|
10
|
-
|
9
|
+
runtime_checkable,
|
11
10
|
)
|
12
11
|
|
13
12
|
from hvac.exceptions import Forbidden
|
14
|
-
from sretoolbox.utils import retry
|
15
13
|
|
16
14
|
from reconcile.utils import (
|
17
15
|
config,
|
@@ -28,6 +26,7 @@ class SecretNotFound(Exception):
|
|
28
26
|
pass
|
29
27
|
|
30
28
|
|
29
|
+
@runtime_checkable
|
31
30
|
class HasSecret(Protocol):
|
32
31
|
"""HasSecret defines all attributes needed to fetch a secret from Vault or config.
|
33
32
|
|
@@ -36,20 +35,20 @@ class HasSecret(Protocol):
|
|
36
35
|
|
37
36
|
path: str
|
38
37
|
field: str
|
39
|
-
version:
|
40
|
-
q_format:
|
38
|
+
version: int | None
|
39
|
+
q_format: str | None
|
41
40
|
|
42
41
|
|
43
42
|
class SecretReaderBase(ABC):
|
44
43
|
@abstractmethod
|
45
44
|
def _read(
|
46
|
-
self, path: str, field: str, format:
|
45
|
+
self, path: str, field: str, format: str | None, version: int | None
|
47
46
|
) -> str:
|
48
47
|
raise NotImplementedError()
|
49
48
|
|
50
49
|
@abstractmethod
|
51
50
|
def _read_all(
|
52
|
-
self, path: str, field: str, format:
|
51
|
+
self, path: str, field: str, format: str | None, version: int | None
|
53
52
|
) -> dict[str, str]:
|
54
53
|
raise NotImplementedError()
|
55
54
|
|
@@ -96,7 +95,7 @@ class SecretReaderBase(ABC):
|
|
96
95
|
)
|
97
96
|
|
98
97
|
def read_with_parameters(
|
99
|
-
self, path: str, field: str, format:
|
98
|
+
self, path: str, field: str, format: str | None, version: int | None
|
100
99
|
) -> str:
|
101
100
|
return self._read(
|
102
101
|
path=path,
|
@@ -106,7 +105,7 @@ class SecretReaderBase(ABC):
|
|
106
105
|
)
|
107
106
|
|
108
107
|
def read_all_with_parameters(
|
109
|
-
self, path: str, field: str, format:
|
108
|
+
self, path: str, field: str, format: str | None, version: int | None
|
110
109
|
) -> dict[str, str]:
|
111
110
|
return self._read_all(
|
112
111
|
path=path,
|
@@ -116,7 +115,7 @@ class SecretReaderBase(ABC):
|
|
116
115
|
)
|
117
116
|
|
118
117
|
def _parameters_to_dict(
|
119
|
-
self, path: str, field: str, format:
|
118
|
+
self, path: str, field: str, format: str | None, version: int | None
|
120
119
|
) -> dict[str, Any]:
|
121
120
|
return {
|
122
121
|
"path": path,
|
@@ -126,7 +125,7 @@ class SecretReaderBase(ABC):
|
|
126
125
|
}
|
127
126
|
|
128
127
|
@staticmethod
|
129
|
-
def to_dict(secret: HasSecret) -> dict[str,
|
128
|
+
def to_dict(secret: HasSecret) -> dict[str, str | int | None]:
|
130
129
|
"""Convenient method to convert Secret class to dictionary."""
|
131
130
|
return {
|
132
131
|
"path": secret.path,
|
@@ -141,7 +140,7 @@ class VaultSecretReader(SecretReaderBase):
|
|
141
140
|
Read secrets from vault via a vault_client
|
142
141
|
"""
|
143
142
|
|
144
|
-
def __init__(self, vault_client:
|
143
|
+
def __init__(self, vault_client: VaultClient | None = None):
|
145
144
|
self._vault_client = vault_client
|
146
145
|
|
147
146
|
@property
|
@@ -150,9 +149,8 @@ class VaultSecretReader(SecretReaderBase):
|
|
150
149
|
self._vault_client = VaultClient()
|
151
150
|
return self._vault_client
|
152
151
|
|
153
|
-
@retry()
|
154
152
|
def _read_all(
|
155
|
-
self, path: str, field: str, format:
|
153
|
+
self, path: str, field: str, format: str | None, version: int | None
|
156
154
|
) -> dict[str, str]:
|
157
155
|
try:
|
158
156
|
data = self.vault_client.read_all( # type: ignore[attr-defined] # mypy doesn't recognize the VaultClient.__new__ method
|
@@ -166,15 +164,14 @@ class VaultSecretReader(SecretReaderBase):
|
|
166
164
|
except Forbidden:
|
167
165
|
raise VaultForbidden(
|
168
166
|
f"permission denied reading vault secret " f"at {path}"
|
169
|
-
)
|
167
|
+
) from None
|
170
168
|
except vault.SecretNotFound as e:
|
171
169
|
raise SecretNotFound(*e.args) from e
|
172
170
|
return data
|
173
171
|
|
174
|
-
@retry()
|
175
172
|
def _read(
|
176
|
-
self, path: str, field: str, format:
|
177
|
-
) ->
|
173
|
+
self, path: str, field: str, format: str | None, version: int | None
|
174
|
+
) -> str:
|
178
175
|
try:
|
179
176
|
data = self.vault_client.read( # type: ignore[attr-defined] # mypy doesn't recognize the VaultClient.__new__ method
|
180
177
|
self._parameters_to_dict(
|
@@ -195,7 +192,7 @@ class ConfigSecretReader(SecretReaderBase):
|
|
195
192
|
"""
|
196
193
|
|
197
194
|
def _read(
|
198
|
-
self, path: str, field: str, format:
|
195
|
+
self, path: str, field: str, format: str | None, version: int | None
|
199
196
|
) -> str:
|
200
197
|
try:
|
201
198
|
data = config.read(
|
@@ -211,7 +208,7 @@ class ConfigSecretReader(SecretReaderBase):
|
|
211
208
|
return data
|
212
209
|
|
213
210
|
def _read_all(
|
214
|
-
self, path: str, field: str, format:
|
211
|
+
self, path: str, field: str, format: str | None, version: int | None
|
215
212
|
) -> dict[str, str]:
|
216
213
|
try:
|
217
214
|
data = config.read_all(
|
@@ -243,13 +240,13 @@ class SecretReader(SecretReaderBase):
|
|
243
240
|
Consider using create_secret_reader() instead.
|
244
241
|
"""
|
245
242
|
|
246
|
-
def __init__(self, settings:
|
243
|
+
def __init__(self, settings: Mapping | None = None) -> None:
|
247
244
|
"""
|
248
245
|
:param settings: app-interface-settings object. It is a dictionary
|
249
246
|
containing `value: true` if Vault is to be used as the secret backend.
|
250
247
|
"""
|
251
248
|
self.settings = settings
|
252
|
-
self._vault_client:
|
249
|
+
self._vault_client: VaultClient | None = None
|
253
250
|
|
254
251
|
@property
|
255
252
|
def vault_client(self) -> VaultClient:
|
@@ -257,9 +254,8 @@ class SecretReader(SecretReaderBase):
|
|
257
254
|
self._vault_client = VaultClient()
|
258
255
|
return self._vault_client
|
259
256
|
|
260
|
-
@retry()
|
261
257
|
def _read(
|
262
|
-
self, path: str, field: str, format:
|
258
|
+
self, path: str, field: str, format: str | None, version: int | None
|
263
259
|
) -> str:
|
264
260
|
"""Returns a value of a key from Vault secret or configuration file.
|
265
261
|
The input secret is a dictionary which contains the following fields:
|
@@ -293,9 +289,8 @@ class SecretReader(SecretReaderBase):
|
|
293
289
|
|
294
290
|
return data
|
295
291
|
|
296
|
-
@retry()
|
297
292
|
def _read_all(
|
298
|
-
self, path: str, field: str, format:
|
293
|
+
self, path: str, field: str, format: str | None, version: int | None
|
299
294
|
) -> dict[str, str]:
|
300
295
|
"""Returns a dictionary of keys and values
|
301
296
|
from Vault secret or configuration file.
|
@@ -321,7 +316,7 @@ class SecretReader(SecretReaderBase):
|
|
321
316
|
except Forbidden:
|
322
317
|
raise VaultForbidden(
|
323
318
|
f"permission denied reading vault secret " f"at {path}"
|
324
|
-
)
|
319
|
+
) from None
|
325
320
|
except vault.SecretNotFound as e:
|
326
321
|
raise SecretNotFound(*e.args) from e
|
327
322
|
else:
|
reconcile/utils/semver_helper.py
CHANGED
@@ -7,7 +7,16 @@ def make_semver(major: int, minor: int, patch: int) -> str:
|
|
7
7
|
return str(semver.VersionInfo(major=major, minor=minor, patch=patch))
|
8
8
|
|
9
9
|
|
10
|
-
def parse_semver(
|
10
|
+
def parse_semver(
|
11
|
+
version: str, optional_minor_and_patch: bool = False
|
12
|
+
) -> semver.VersionInfo:
|
13
|
+
if optional_minor_and_patch:
|
14
|
+
# semver3 supports optional minor and patch.
|
15
|
+
# until we upgrade to semver3, we support this by adding a default minor and/or patch
|
16
|
+
if "." not in version:
|
17
|
+
version = f"{version}.0.0"
|
18
|
+
elif version.count(".") == 1:
|
19
|
+
version = f"{version}.0"
|
11
20
|
return semver.VersionInfo.parse(version)
|
12
21
|
|
13
22
|
|
@@ -26,3 +35,8 @@ def sort_versions(versions: Iterable[str]) -> list[str]:
|
|
26
35
|
|
27
36
|
def is_version_bumped(current_version: str, previous_version: str) -> bool:
|
28
37
|
return parse_semver(current_version) > parse_semver(previous_version)
|
38
|
+
|
39
|
+
|
40
|
+
def get_version_prefix(version: str) -> str:
|
41
|
+
semver = parse_semver(version)
|
42
|
+
return f"{semver.major}.{semver.minor}"
|
reconcile/utils/slack_api.py
CHANGED
@@ -9,9 +9,7 @@ from collections.abc import (
|
|
9
9
|
)
|
10
10
|
from typing import (
|
11
11
|
Any,
|
12
|
-
Optional,
|
13
12
|
Protocol,
|
14
|
-
Union,
|
15
13
|
)
|
16
14
|
|
17
15
|
from slack_sdk import WebClient
|
@@ -24,6 +22,8 @@ from slack_sdk.http_retry import (
|
|
24
22
|
RetryState,
|
25
23
|
)
|
26
24
|
|
25
|
+
from reconcile.utils.metrics import slack_request
|
26
|
+
|
27
27
|
MAX_RETRIES = 5
|
28
28
|
TIMEOUT = 30
|
29
29
|
|
@@ -44,36 +44,32 @@ class ServerErrorRetryHandler(RetryHandler):
|
|
44
44
|
*,
|
45
45
|
state: RetryState,
|
46
46
|
request: HttpRequest,
|
47
|
-
response:
|
48
|
-
error:
|
47
|
+
response: HttpResponse | None = None,
|
48
|
+
error: Exception | None = None,
|
49
49
|
) -> bool:
|
50
50
|
return response is not None and response.status_code >= 500
|
51
51
|
|
52
52
|
|
53
53
|
class HasClientGlobalConfig(Protocol):
|
54
|
-
max_retries:
|
55
|
-
timeout:
|
54
|
+
max_retries: int | None
|
55
|
+
timeout: int | None
|
56
56
|
|
57
|
-
def dict(self) -> dict[str,
|
58
|
-
...
|
57
|
+
def dict(self) -> dict[str, int | None]: ...
|
59
58
|
|
60
59
|
|
61
60
|
class HasClientMethodConfig(Protocol):
|
62
61
|
name: str
|
63
62
|
args: Any
|
64
63
|
|
65
|
-
def dict(self) -> dict[str, str]:
|
66
|
-
...
|
64
|
+
def dict(self) -> dict[str, str]: ...
|
67
65
|
|
68
66
|
|
69
67
|
class HasClientConfig(Protocol):
|
70
68
|
@property
|
71
|
-
def q_global(self) ->
|
72
|
-
...
|
69
|
+
def q_global(self) -> HasClientGlobalConfig | None: ...
|
73
70
|
|
74
71
|
@property
|
75
|
-
def methods(self) ->
|
76
|
-
...
|
72
|
+
def methods(self) -> Sequence[HasClientMethodConfig] | None: ...
|
77
73
|
|
78
74
|
|
79
75
|
class SlackApiConfig:
|
@@ -83,7 +79,6 @@ class SlackApiConfig:
|
|
83
79
|
"""
|
84
80
|
|
85
81
|
def __init__(self, timeout: int = TIMEOUT, max_retries: int = MAX_RETRIES) -> None:
|
86
|
-
|
87
82
|
self.timeout = timeout
|
88
83
|
self.max_retries = max_retries
|
89
84
|
self._methods: dict[str, Any] = {}
|
@@ -98,7 +93,7 @@ class SlackApiConfig:
|
|
98
93
|
"""
|
99
94
|
self._methods[method_name] = method_config
|
100
95
|
|
101
|
-
def get_method_config(self, method_name: str) ->
|
96
|
+
def get_method_config(self, method_name: str) -> dict[str, Any] | None:
|
102
97
|
"""
|
103
98
|
Get Slack method configuration.
|
104
99
|
:param method_name: the name of a method (ex. users.list)
|
@@ -168,9 +163,10 @@ class SlackApi:
|
|
168
163
|
self,
|
169
164
|
workspace_name: str,
|
170
165
|
token: str,
|
171
|
-
api_config:
|
166
|
+
api_config: SlackApiConfig | None = None,
|
172
167
|
init_usergroups: bool = True,
|
173
|
-
channel:
|
168
|
+
channel: str | None = None,
|
169
|
+
slack_url: str | None = None,
|
174
170
|
**chat_kwargs: Any,
|
175
171
|
) -> None:
|
176
172
|
"""
|
@@ -181,7 +177,7 @@ class SlackApi:
|
|
181
177
|
:param init_usergroups: whether or not to get a list of all Slack
|
182
178
|
usergroups when instantiated
|
183
179
|
:param channel: the Slack channel to post messages to, only used
|
184
|
-
when posting messages to a channel
|
180
|
+
when posting messages to a channel or getting conversation history
|
185
181
|
:param chat_kwargs: any other kwargs that can be used to post Slack
|
186
182
|
channel messages
|
187
183
|
"""
|
@@ -192,14 +188,22 @@ class SlackApi:
|
|
192
188
|
else:
|
193
189
|
self.config = SlackApiConfig()
|
194
190
|
|
195
|
-
self._sc = WebClient(
|
191
|
+
self._sc = WebClient(
|
192
|
+
token=token,
|
193
|
+
timeout=self.config.timeout,
|
194
|
+
base_url=slack_url or WebClient.BASE_URL,
|
195
|
+
)
|
196
196
|
self._configure_client_retry()
|
197
197
|
|
198
198
|
self._results: dict[str, Any] = {}
|
199
|
+
self._enterprise_user_id_to_user_ids: dict[str, str] = {}
|
199
200
|
|
200
201
|
self.channel = channel
|
201
202
|
self.chat_kwargs = chat_kwargs
|
202
203
|
|
204
|
+
self._user_groups_initialized = False
|
205
|
+
self.usergroups: list[dict] = []
|
206
|
+
|
203
207
|
if init_usergroups:
|
204
208
|
self._initiate_usergroups()
|
205
209
|
|
@@ -234,16 +238,25 @@ class SlackApi:
|
|
234
238
|
)
|
235
239
|
|
236
240
|
def do_send(c: str, t: str) -> None:
|
241
|
+
slack_request.labels("chat.postMessage", "POST").inc()
|
237
242
|
self._sc.chat_postMessage(channel=c, text=t, **self.chat_kwargs)
|
238
243
|
|
239
244
|
try:
|
240
245
|
do_send(self.channel, text)
|
241
246
|
except SlackApiError as e:
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
+
match e.response["error"]:
|
248
|
+
case "not_in_channel":
|
249
|
+
self.join_channel()
|
250
|
+
do_send(self.channel, text)
|
251
|
+
# When a message is sent to #someChannel and the Slack API can't find
|
252
|
+
# it, the message it provides in the exception doesn't include the
|
253
|
+
# channel name. We handle that here in case the consumer has many such
|
254
|
+
# independent calls to Slack's API.
|
255
|
+
case "channel_not_found":
|
256
|
+
logging.error(f"Slack API says can't find channel {self.channel}")
|
257
|
+
raise
|
258
|
+
case _:
|
259
|
+
raise
|
247
260
|
|
248
261
|
def describe_usergroup(
|
249
262
|
self, handle: str
|
@@ -274,11 +287,13 @@ class SlackApi:
|
|
274
287
|
|
275
288
|
channels_found = self.get_channels_by_names(self.channel)
|
276
289
|
[channel_id] = [k for k in channels_found if channels_found[k] == self.channel]
|
290
|
+
slack_request.labels("conversations.info", "GET").inc()
|
291
|
+
|
277
292
|
info = self._sc.conversations_info(channel=channel_id)
|
278
293
|
if not info.data["channel"]["is_member"]: # type: ignore[call-overload]
|
279
294
|
self._sc.conversations_join(channel=channel_id)
|
280
295
|
|
281
|
-
def get_usergroup_id(self, handle: str) ->
|
296
|
+
def get_usergroup_id(self, handle: str) -> str | None:
|
282
297
|
try:
|
283
298
|
return self.get_usergroup(handle)["id"]
|
284
299
|
except UsergroupNotFoundException:
|
@@ -291,17 +306,26 @@ class SlackApi:
|
|
291
306
|
:raises slack_sdk.errors.SlackApiError: if unsuccessful response from
|
292
307
|
Slack API
|
293
308
|
"""
|
309
|
+
slack_request.labels("usergroups.list", "GET").inc()
|
310
|
+
|
294
311
|
result = self._sc.usergroups_list(include_users=True)
|
295
312
|
self.usergroups = result["usergroups"]
|
313
|
+
self._user_groups_initialized = True
|
296
314
|
|
297
315
|
def get_usergroup(self, handle: str) -> dict[str, Any]:
|
316
|
+
if not self._user_groups_initialized:
|
317
|
+
self._initiate_usergroups()
|
298
318
|
usergroup = [g for g in self.usergroups if g["handle"] == handle]
|
299
319
|
if len(usergroup) != 1:
|
300
320
|
raise UsergroupNotFoundException(handle)
|
301
321
|
return usergroup[0]
|
302
322
|
|
303
323
|
def create_usergroup(self, handle: str) -> str:
|
324
|
+
slack_request.labels("usergroups.create", "POST").inc()
|
325
|
+
|
304
326
|
response = self._sc.usergroups_create(name=handle, handle=handle)
|
327
|
+
# Invalidate the usergroups list cache
|
328
|
+
self._user_groups_initialized = False
|
305
329
|
return response["usergroup"]["id"]
|
306
330
|
|
307
331
|
def update_usergroup(
|
@@ -317,6 +341,8 @@ class SlackApi:
|
|
317
341
|
:raises slack_sdk.errors.SlackApiError: if unsuccessful response from
|
318
342
|
Slack API
|
319
343
|
"""
|
344
|
+
slack_request.labels("usergroups.update", "POST").inc()
|
345
|
+
|
320
346
|
self._sc.usergroups_update(
|
321
347
|
usergroup=id, channels=channels_list, description=description
|
322
348
|
)
|
@@ -337,6 +363,8 @@ class SlackApi:
|
|
337
363
|
users_list = [self.get_random_deleted_user()]
|
338
364
|
|
339
365
|
try:
|
366
|
+
slack_request.labels("usergroups.users.update", "POST").inc()
|
367
|
+
|
340
368
|
self._sc.usergroups_users_update(usergroup=id, users=users_list)
|
341
369
|
except SlackApiError as e:
|
342
370
|
# Slack can throw an invalid_users error when emptying groups, but
|
@@ -365,10 +393,12 @@ class SlackApi:
|
|
365
393
|
:raises UserNotFoundException: if the Slack user is not found
|
366
394
|
"""
|
367
395
|
try:
|
396
|
+
slack_request.labels("users.lookupByEmail", "GET").inc()
|
397
|
+
|
368
398
|
result = self._sc.users_lookupByEmail(email=f"{user_name}@{mail_address}")
|
369
399
|
except SlackApiError as e:
|
370
400
|
if e.response["error"] == "users_not_found":
|
371
|
-
raise UserNotFoundException(e.response["error"])
|
401
|
+
raise UserNotFoundException(e.response["error"]) from None
|
372
402
|
raise
|
373
403
|
|
374
404
|
return result["user"]["id"]
|
@@ -385,15 +415,23 @@ class SlackApi:
|
|
385
415
|
k: v["name"] for k, v in self._get("channels").items() if k in channels_ids
|
386
416
|
}
|
387
417
|
|
388
|
-
def
|
418
|
+
def get_active_users_by_names(self, user_names: Iterable[str]) -> dict[str, str]:
|
389
419
|
return {
|
390
420
|
k: v["name"]
|
391
421
|
for k, v in self._get("users").items()
|
392
|
-
if v["name"] in user_names
|
422
|
+
if v["name"] in user_names and not v["deleted"]
|
393
423
|
}
|
394
424
|
|
395
425
|
def get_users_by_ids(self, users_ids: Iterable[str]) -> dict[str, str]:
|
396
|
-
|
426
|
+
users = self._get("users")
|
427
|
+
translated_user_ids = (
|
428
|
+
self._translate_user_id(user_id) for user_id in users_ids
|
429
|
+
)
|
430
|
+
return {
|
431
|
+
user_id: user["name"]
|
432
|
+
for user_id in translated_user_ids
|
433
|
+
if (user := users.get(user_id))
|
434
|
+
}
|
397
435
|
|
398
436
|
def _get(self, resource: str) -> dict[str, Any]:
|
399
437
|
"""
|
@@ -403,21 +441,23 @@ class SlackApi:
|
|
403
441
|
:param resource: resource type
|
404
442
|
:return: data from API call
|
405
443
|
"""
|
444
|
+
if resource in self._results:
|
445
|
+
return self._results[resource]
|
446
|
+
|
406
447
|
result_key = "members" if resource == "users" else resource
|
407
448
|
api_key = "conversations" if resource == "channels" else resource
|
408
449
|
results = {}
|
409
|
-
additional_kwargs: dict[str,
|
410
|
-
|
411
|
-
if resource in self._results:
|
412
|
-
return self._results[resource]
|
450
|
+
additional_kwargs: dict[str, str | int] = {"cursor": ""}
|
413
451
|
|
414
452
|
method_config = self.config.get_method_config(f"{api_key}.list")
|
415
453
|
if method_config:
|
416
454
|
additional_kwargs.update(method_config)
|
417
455
|
|
418
456
|
while True:
|
457
|
+
slack_request.labels(f"{api_key}.list", "GET").inc()
|
458
|
+
|
419
459
|
result = self._sc.api_call(
|
420
|
-
"{}.list"
|
460
|
+
f"{api_key}.list", http_verb="GET", params=additional_kwargs
|
421
461
|
)
|
422
462
|
|
423
463
|
for r in result[result_key]:
|
@@ -425,10 +465,58 @@ class SlackApi:
|
|
425
465
|
|
426
466
|
cursor = result["response_metadata"]["next_cursor"]
|
427
467
|
|
428
|
-
if cursor
|
468
|
+
if not cursor:
|
429
469
|
break
|
430
470
|
|
431
471
|
additional_kwargs["cursor"] = cursor
|
432
472
|
|
433
473
|
self._results[resource] = results
|
474
|
+
|
475
|
+
if resource == "users":
|
476
|
+
self._enterprise_user_id_to_user_ids = {
|
477
|
+
enterprise_user_id: user["id"]
|
478
|
+
for user in results.values()
|
479
|
+
if (enterprise_user_id := user.get("enterprise_user", {}).get("id"))
|
480
|
+
}
|
434
481
|
return results
|
482
|
+
|
483
|
+
def _translate_user_id(self, user_id: str) -> str:
|
484
|
+
"""Translate enterprise user id to user id"""
|
485
|
+
return self._enterprise_user_id_to_user_ids.get(user_id, user_id)
|
486
|
+
|
487
|
+
def get_flat_conversation_history(
|
488
|
+
self, from_timestamp: int, to_timestamp: int | None
|
489
|
+
) -> list[dict[str, Any]]:
|
490
|
+
"""Calls conversation_history method to get all messages in a channel between
|
491
|
+
from_timestamp to to_timestamp ignoring threads"""
|
492
|
+
if not self.channel:
|
493
|
+
raise ValueError("Expecting self.channel to be set")
|
494
|
+
|
495
|
+
cursor = ""
|
496
|
+
responses = []
|
497
|
+
keep_fetching = True
|
498
|
+
while True:
|
499
|
+
slack_request.labels("conversations.history", "GET").inc()
|
500
|
+
|
501
|
+
response = self._sc.conversations_history(
|
502
|
+
cursor=cursor, channel=self.channel, **self.chat_kwargs
|
503
|
+
)
|
504
|
+
|
505
|
+
for r in response["messages"]:
|
506
|
+
if to_timestamp and float(r["ts"]) > to_timestamp:
|
507
|
+
continue
|
508
|
+
|
509
|
+
if float(r["ts"]) < from_timestamp:
|
510
|
+
keep_fetching = False
|
511
|
+
break
|
512
|
+
|
513
|
+
responses.append(r)
|
514
|
+
|
515
|
+
if not keep_fetching:
|
516
|
+
break
|
517
|
+
|
518
|
+
cursor = response["response_metadata"]["next_cursor"]
|
519
|
+
if not cursor:
|
520
|
+
break
|
521
|
+
|
522
|
+
return responses
|
reconcile/utils/smtp_client.py
CHANGED
@@ -4,7 +4,6 @@ from email.header import Header
|
|
4
4
|
from email.mime.multipart import MIMEMultipart
|
5
5
|
from email.mime.text import MIMEText
|
6
6
|
from email.utils import formataddr
|
7
|
-
from typing import Optional
|
8
7
|
|
9
8
|
from pydantic import (
|
10
9
|
BaseModel,
|
@@ -54,7 +53,7 @@ class SmtpClient:
|
|
54
53
|
self.passwd = server.password
|
55
54
|
self.mail_address = mail_address
|
56
55
|
self.timeout = timeout
|
57
|
-
self._client:
|
56
|
+
self._client: smtplib.SMTP | None = None
|
58
57
|
|
59
58
|
@property
|
60
59
|
def client(self) -> smtplib.SMTP:
|
reconcile/utils/sqs_gateway.py
CHANGED
@@ -13,7 +13,7 @@ class SQSGateway:
|
|
13
13
|
"""Wrapper around SQS AWS SDK"""
|
14
14
|
|
15
15
|
def __init__(self, accounts, secret_reader: SecretReader):
|
16
|
-
queue_url = os.environ.get("gitlab_pr_submitter_queue_url")
|
16
|
+
queue_url = os.environ.get("gitlab_pr_submitter_queue_url") # noqa: SIM112
|
17
17
|
if not queue_url:
|
18
18
|
raise SQSGatewayInitError(
|
19
19
|
"when /app-interface/app-interface-settings-1.yml#mergeRequestGateway "
|
@@ -46,17 +46,21 @@ class SQSGateway:
|
|
46
46
|
a["name"] for a in accounts if a["uid"] == queue_account_uid
|
47
47
|
]
|
48
48
|
if len(queue_account_name) != 1:
|
49
|
-
raise SQSGatewayInitError(
|
50
|
-
"account uid not found: {}".format(queue_account_uid)
|
51
|
-
)
|
49
|
+
raise SQSGatewayInitError(f"account uid not found: {queue_account_uid}")
|
52
50
|
return queue_account_name[0]
|
53
51
|
|
54
52
|
def send_message(self, body):
|
55
53
|
self.sqs.send_message(QueueUrl=self.queue_url, MessageBody=json.dumps(body))
|
56
54
|
|
57
|
-
def receive_messages(
|
55
|
+
def receive_messages(
|
56
|
+
self,
|
57
|
+
visibility_timeout=30,
|
58
|
+
wait_time_seconds=20,
|
59
|
+
):
|
58
60
|
messages = self.sqs.receive_message(
|
59
|
-
QueueUrl=self.queue_url,
|
61
|
+
QueueUrl=self.queue_url,
|
62
|
+
VisibilityTimeout=visibility_timeout,
|
63
|
+
WaitTimeSeconds=wait_time_seconds,
|
60
64
|
).get("Messages", [])
|
61
65
|
return [(m["ReceiptHandle"], json.loads(m["Body"])) for m in messages]
|
62
66
|
|