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,123 @@
|
|
1
|
+
from collections.abc import (
|
2
|
+
Callable,
|
3
|
+
Generator,
|
4
|
+
MutableMapping,
|
5
|
+
)
|
6
|
+
from typing import Any
|
7
|
+
|
8
|
+
from croniter import croniter
|
9
|
+
from pydantic import (
|
10
|
+
BaseModel,
|
11
|
+
ValidationError,
|
12
|
+
)
|
13
|
+
from pydantic import errors as pydantic_errors
|
14
|
+
from pydantic.fields import ModelField
|
15
|
+
|
16
|
+
DEFAULT_STRING = "I was too lazy to define a string here"
|
17
|
+
DEFAULT_INT = 42
|
18
|
+
|
19
|
+
|
20
|
+
def data_default_none(
|
21
|
+
klass: type[BaseModel], data: MutableMapping[str, Any], use_defaults: bool = True
|
22
|
+
) -> MutableMapping[str, Any]:
|
23
|
+
"""Set default values to None for required but optional fields."""
|
24
|
+
for field in klass.__fields__.values():
|
25
|
+
if not field.required:
|
26
|
+
continue
|
27
|
+
|
28
|
+
if field.alias not in data:
|
29
|
+
# Settings defaults
|
30
|
+
if field.allow_none:
|
31
|
+
data[field.alias] = None
|
32
|
+
elif not use_defaults:
|
33
|
+
raise ValueError(f"Field {field.alias} is required but not set.")
|
34
|
+
elif isinstance(field.type_, type) and issubclass(field.type_, str):
|
35
|
+
data[field.alias] = DEFAULT_STRING
|
36
|
+
elif isinstance(field.type_, type) and issubclass(field.type_, bool):
|
37
|
+
data[field.alias] = False
|
38
|
+
elif isinstance(field.type_, type) and issubclass(field.type_, int):
|
39
|
+
data[field.alias] = DEFAULT_INT
|
40
|
+
elif isinstance(field.type_, type) and issubclass(field.type_, BaseModel):
|
41
|
+
if isinstance(data[field.alias], dict):
|
42
|
+
data[field.alias] = data_default_none(field.type_, data[field.alias])
|
43
|
+
if isinstance(data[field.alias], list):
|
44
|
+
data[field.alias] = [
|
45
|
+
data_default_none(field.type_, item)
|
46
|
+
for item in data[field.alias]
|
47
|
+
if isinstance(item, dict)
|
48
|
+
]
|
49
|
+
elif field.sub_fields:
|
50
|
+
if all(
|
51
|
+
isinstance(sub_field.type_, type)
|
52
|
+
and issubclass(sub_field.type_, BaseModel)
|
53
|
+
for sub_field in field.sub_fields
|
54
|
+
):
|
55
|
+
# Union[ClassA, ClassB] field
|
56
|
+
for sub_field in field.sub_fields:
|
57
|
+
if isinstance(data[field.alias], dict):
|
58
|
+
try:
|
59
|
+
d = dict(data[field.alias])
|
60
|
+
d.update(data_default_none(sub_field.type_, d))
|
61
|
+
# Lets confirm we found a matching union class
|
62
|
+
sub_field.type_(**d)
|
63
|
+
data[field.alias] = d
|
64
|
+
break
|
65
|
+
except ValidationError:
|
66
|
+
continue
|
67
|
+
elif isinstance(data[field.alias], list) and len(field.sub_fields) == 1:
|
68
|
+
# list[Union[ClassA, ClassB]] field
|
69
|
+
for sub_data in data[field.alias]:
|
70
|
+
for sub_field in field.sub_fields[0].sub_fields or []:
|
71
|
+
try:
|
72
|
+
d = dict(sub_data)
|
73
|
+
d.update(data_default_none(sub_field.type_, d))
|
74
|
+
# Lets confirm we found a matching union class
|
75
|
+
sub_field.type_(**d)
|
76
|
+
sub_data.update(d)
|
77
|
+
break
|
78
|
+
except ValidationError:
|
79
|
+
continue
|
80
|
+
|
81
|
+
return data
|
82
|
+
|
83
|
+
|
84
|
+
class CSV(list[str]):
|
85
|
+
"""
|
86
|
+
A pydantic custom type that converts a CSV into a list of strings. It
|
87
|
+
also supports basic validation of length constraints.
|
88
|
+
"""
|
89
|
+
|
90
|
+
@classmethod
|
91
|
+
def __get_validators__(cls) -> Generator[Callable, None, None]: # noqa: PLW3201
|
92
|
+
yield cls.validate
|
93
|
+
yield cls.length_validator
|
94
|
+
|
95
|
+
@classmethod
|
96
|
+
def validate(cls, value: str) -> list[str]:
|
97
|
+
items = [] if not value else value.split(",")
|
98
|
+
return items
|
99
|
+
|
100
|
+
@classmethod
|
101
|
+
def length_validator(
|
102
|
+
cls, v: "list[str]", values: dict, field: ModelField
|
103
|
+
) -> "list[str]":
|
104
|
+
min_items = field.field_info.extra.get("csv_min_items")
|
105
|
+
max_items = field.field_info.extra.get("csv_max_items")
|
106
|
+
|
107
|
+
v_len = len(v)
|
108
|
+
if min_items is not None and v_len < min_items:
|
109
|
+
raise pydantic_errors.ListMinLengthError(limit_value=min_items)
|
110
|
+
if max_items is not None and v_len > max_items:
|
111
|
+
raise pydantic_errors.ListMaxLengthError(limit_value=max_items)
|
112
|
+
return v
|
113
|
+
|
114
|
+
|
115
|
+
def cron_validator(value: str) -> str:
|
116
|
+
"""
|
117
|
+
A pydantic validator for a cron expression.
|
118
|
+
"""
|
119
|
+
try:
|
120
|
+
croniter(value)
|
121
|
+
return value
|
122
|
+
except ValueError as e:
|
123
|
+
raise ValueError(f"Invalid cron expression: {e}") from None
|
@@ -0,0 +1,198 @@
|
|
1
|
+
# Merge Requests
|
2
|
+
|
3
|
+
Module responsible for abstracting a Gitlab Merge Request.
|
4
|
+
|
5
|
+
## Creating New MergeRequest Classes
|
6
|
+
|
7
|
+
Each type of merge request requires a class that inherits
|
8
|
+
from reconcile.utils.mr.base.MergeRequestBase.
|
9
|
+
|
10
|
+
That class has to comply with the specification below.
|
11
|
+
|
12
|
+
### Class Name
|
13
|
+
|
14
|
+
The class name is given by the class variable `name`. That name will be
|
15
|
+
used all around, the most important place being the SQS Message parameter
|
16
|
+
`pr_type`, used later to create an instance of the same class.
|
17
|
+
|
18
|
+
While the name can be anything it is mandatory that it is defined.
|
19
|
+
|
20
|
+
### Class Initialization
|
21
|
+
|
22
|
+
The `__init__` method has to call `super().__init__()` right after the minimum
|
23
|
+
parameters initialization. That is required to compose the SQS Message that
|
24
|
+
will later be used to create a new instance of the same class.
|
25
|
+
|
26
|
+
### Class Methods
|
27
|
+
|
28
|
+
The minimum methods that have to be defined are:
|
29
|
+
|
30
|
+
* `title`: a property that is used to give the Gitlab Merge Request a title.
|
31
|
+
It can also be used for building commit messages or as content to committed
|
32
|
+
files.
|
33
|
+
* `description`: a description for the Merge Request.
|
34
|
+
* `process`: this method is called when submitting the Merge Request to gitlab.
|
35
|
+
it's the place for the merge request changes, like creating, updating and
|
36
|
+
deleting files. The `process` method is called after the local branch is
|
37
|
+
created and right after it the `gitlab_cli.project.mergerequests.create()`
|
38
|
+
is called.
|
39
|
+
|
40
|
+
### Example
|
41
|
+
|
42
|
+
This is an example of a minimum implementation for a new MergeRequest class:
|
43
|
+
|
44
|
+
```python
|
45
|
+
from reconcile.utils.mr.base import MergeRequestBase
|
46
|
+
|
47
|
+
|
48
|
+
class CreateDeleteUser(MergeRequestBase):
|
49
|
+
|
50
|
+
name = 'create_delete_user_mr'
|
51
|
+
|
52
|
+
def __init__(self, username, paths):
|
53
|
+
self.username = username
|
54
|
+
self.paths = paths
|
55
|
+
|
56
|
+
# Called right after the minimum parameters to recreate
|
57
|
+
# an instance with the same data. This is important for
|
58
|
+
# building up the SQS message payload.
|
59
|
+
super().__init__()
|
60
|
+
|
61
|
+
@property
|
62
|
+
def title(self) -> str:
|
63
|
+
return f'[{self.name}] delete user {self.username}'
|
64
|
+
|
65
|
+
@property
|
66
|
+
def description(self) -> str:
|
67
|
+
return f'delete user {self.username}'
|
68
|
+
|
69
|
+
def process(self, gitlab_cli):
|
70
|
+
for path in self.paths:
|
71
|
+
gitlab_cli.delete_file(branch_name=self.branch,
|
72
|
+
file_path=path,
|
73
|
+
commit_message=self.title)
|
74
|
+
```
|
75
|
+
|
76
|
+
## Sending MRs to SQS
|
77
|
+
|
78
|
+
To send a Merge Request to SQS, create the corresponding MergeRequest object:
|
79
|
+
|
80
|
+
```python
|
81
|
+
from reconcile.utils.mr import CreateAppInterfaceNotificator
|
82
|
+
|
83
|
+
|
84
|
+
notification = {
|
85
|
+
'notification_type': 'Outage',
|
86
|
+
'description': 'The AppSRE team is currently investigating an outage',
|
87
|
+
'short_description': 'Short Description',
|
88
|
+
}
|
89
|
+
|
90
|
+
merge_request = CreateAppInterfaceNotificator(notification=notification)
|
91
|
+
|
92
|
+
```
|
93
|
+
|
94
|
+
then create the SQS Client instance:
|
95
|
+
|
96
|
+
```python
|
97
|
+
from reconcile import queries
|
98
|
+
|
99
|
+
from reconcile.utils.sqs_gateway import SQSGateway
|
100
|
+
from reconcile.utils.secret_reader import SecretReader
|
101
|
+
|
102
|
+
|
103
|
+
accounts = queries.get_queue_aws_accounts()
|
104
|
+
secretReader = SecretReader(queries.get_secret_reader_settings())
|
105
|
+
sqs_cli = SQSGateway(accounts, secret_reader=secret_reader)
|
106
|
+
```
|
107
|
+
|
108
|
+
and then submit the merge request to the SQS:
|
109
|
+
|
110
|
+
```python
|
111
|
+
merge_request.submit_to_sqs(sqs_cli=sqs_cli)
|
112
|
+
```
|
113
|
+
|
114
|
+
## Sending MRs to Gitlab
|
115
|
+
|
116
|
+
To get the message from SQS and use it for sending a Merge Request to gitlab,
|
117
|
+
first get the SQS messages:
|
118
|
+
|
119
|
+
|
120
|
+
```python
|
121
|
+
from reconcile import queries
|
122
|
+
|
123
|
+
from reconcile.utils.sqs_gateway import SQSGateway
|
124
|
+
from reconcile.utils.secret_reader import SecretReader
|
125
|
+
|
126
|
+
|
127
|
+
accounts = queries.get_queue_aws_accounts()
|
128
|
+
settings = queries.get_app_interface_settings()
|
129
|
+
|
130
|
+
secretReader = SecretReader(queries.get_secret_reader_settings())
|
131
|
+
sqs_cli = SQSGateway(accounts, secret_reader=secret_reader)
|
132
|
+
messages = sqs_cli.receive_messages()
|
133
|
+
```
|
134
|
+
|
135
|
+
then create the Gitlab client instance:
|
136
|
+
|
137
|
+
```python
|
138
|
+
from reconcile.utils.gitlab_api import GitLabApi
|
139
|
+
|
140
|
+
instance = queries.get_gitlab_instance()
|
141
|
+
saas_files = queries.get_saas_files_minimal()
|
142
|
+
gitlab_cli = GitLabApi(instance, project_id=gitlab_project_id,
|
143
|
+
settings=settings)
|
144
|
+
```
|
145
|
+
|
146
|
+
and then loop the messages, creating the MergeRequest objects and submitting
|
147
|
+
the merge requests:
|
148
|
+
|
149
|
+
```python
|
150
|
+
from reconcile.utils.mr import init_from_sqs_message
|
151
|
+
|
152
|
+
for message in messages:
|
153
|
+
receipt_handle, body = message[0], message[1]
|
154
|
+
merge_request = init_from_sqs_message(body)
|
155
|
+
merge_request.submit_to_gitlab(gitlab_cli=gitlab_cli)
|
156
|
+
sqs_cli.delete_message(receipt_handle)
|
157
|
+
```
|
158
|
+
|
159
|
+
## Using the MR Module for Qontract-reconcile Integrations
|
160
|
+
|
161
|
+
A given integration might be executed in different environments, like:
|
162
|
+
|
163
|
+
* Developer local machine.
|
164
|
+
* OpenShift cluster outside the VPN.
|
165
|
+
* OpenShift cluster inside the VPN.
|
166
|
+
* Jenkins periodic job.
|
167
|
+
|
168
|
+
Because we don't want the integrations to care if they are running inside or
|
169
|
+
outside the VPN, we use the `reconcile.mr_client_gateway.init()` to get the
|
170
|
+
on of SQS or GitLab client, according to the App Interface settings. Example:
|
171
|
+
|
172
|
+
```python
|
173
|
+
from reconcile import mr_client_gateway
|
174
|
+
from reconcile.utils.mr import CreateDeleteAwsAccessKey
|
175
|
+
|
176
|
+
|
177
|
+
def run(dry_run, gitlab_project_id):
|
178
|
+
...
|
179
|
+
mr = CreateDeleteAwsAccessKey(...)
|
180
|
+
with mr_client_gateway.init(gitlab_project_id=gitlab_project_id) as mr_cli:
|
181
|
+
mr.submit(cli=mr_cli)
|
182
|
+
```
|
183
|
+
|
184
|
+
If we want to override what's set in App Interface and get a specific client,
|
185
|
+
say `gitlab`, we would:
|
186
|
+
|
187
|
+
```python
|
188
|
+
from reconcile import mr_client_gateway
|
189
|
+
from reconcile.utils.mr import CreateDeleteAwsAccessKey
|
190
|
+
|
191
|
+
|
192
|
+
def run(dry_run, gitlab_project_id):
|
193
|
+
...
|
194
|
+
mr = CreateDeleteAwsAccessKey(...)
|
195
|
+
with mr_client_gateway.init(sqs_or_gitlab='gitlab',
|
196
|
+
gitlab_project_id=gitlab_project_id) as mr_cli:
|
197
|
+
mr.submit(cli=mr_cli)
|
198
|
+
```
|
reconcile/utils/mr/__init__.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
from reconcile.utils.mr.app_interface_reporter import CreateAppInterfaceReporter
|
2
|
-
from reconcile.utils.mr.auto_promoter import AutoPromoter
|
3
2
|
from reconcile.utils.mr.aws_access import CreateDeleteAwsAccessKey
|
4
3
|
from reconcile.utils.mr.base import (
|
5
4
|
MergeRequestBase,
|
@@ -13,24 +12,29 @@ from reconcile.utils.mr.ocm_update_recommended_version import (
|
|
13
12
|
from reconcile.utils.mr.ocm_upgrade_scheduler_org_updates import (
|
14
13
|
CreateOCMUpgradeSchedulerOrgUpdates,
|
15
14
|
)
|
15
|
+
from reconcile.utils.mr.promote_qontract import (
|
16
|
+
PromoteQontractReconcileCommercial,
|
17
|
+
PromoteQontractSchemas,
|
18
|
+
)
|
16
19
|
from reconcile.utils.mr.user_maintenance import (
|
17
20
|
CreateDeleteUserAppInterface,
|
18
21
|
CreateDeleteUserInfra,
|
19
22
|
)
|
20
23
|
|
21
24
|
__all__ = [
|
22
|
-
"
|
23
|
-
"UnknownMergeRequestType",
|
24
|
-
"MergeRequestProcessingError",
|
25
|
+
"CreateAppInterfaceNotificator",
|
25
26
|
"CreateAppInterfaceReporter",
|
26
|
-
"CreateDeleteAwsAccessKey",
|
27
27
|
"CreateClustersUpdates",
|
28
|
-
"
|
29
|
-
"CreateOCMUpdateRecommendedVersion",
|
30
|
-
"CreateAppInterfaceNotificator",
|
28
|
+
"CreateDeleteAwsAccessKey",
|
31
29
|
"CreateDeleteUserAppInterface",
|
32
30
|
"CreateDeleteUserInfra",
|
33
|
-
"
|
31
|
+
"CreateOCMUpdateRecommendedVersion",
|
32
|
+
"CreateOCMUpgradeSchedulerOrgUpdates",
|
33
|
+
"MergeRequestProcessingError",
|
34
|
+
"PromoteQontractReconcileCommercial",
|
35
|
+
"PromoteQontractSchemas",
|
36
|
+
"UnknownMergeRequestType",
|
37
|
+
"init_from_sqs_message",
|
34
38
|
]
|
35
39
|
|
36
40
|
|
@@ -40,7 +44,7 @@ class UnknownMergeRequestType(Exception):
|
|
40
44
|
"""
|
41
45
|
|
42
46
|
|
43
|
-
def init_from_sqs_message(message):
|
47
|
+
def init_from_sqs_message(message) -> MergeRequestBase:
|
44
48
|
# First, let's find the classes that are inheriting from
|
45
49
|
# MergeRequestBase and create a map where the class.name is
|
46
50
|
# the key and the class itself is the value.
|
@@ -3,6 +3,7 @@ from pathlib import Path
|
|
3
3
|
|
4
4
|
from ruamel.yaml.scalarstring import PreservedScalarString as pss
|
5
5
|
|
6
|
+
from reconcile.utils.gitlab_api import GitLabApi
|
6
7
|
from reconcile.utils.mr.base import (
|
7
8
|
MergeRequestBase,
|
8
9
|
app_interface_email,
|
@@ -11,7 +12,6 @@ from reconcile.utils.mr.labels import AUTO_MERGE
|
|
11
12
|
|
12
13
|
|
13
14
|
class CreateAppInterfaceReporter(MergeRequestBase):
|
14
|
-
|
15
15
|
name = "create_app_interface_reporter_mr"
|
16
16
|
|
17
17
|
def __init__(self, reports, email_body, reports_path):
|
@@ -35,7 +35,7 @@ class CreateAppInterfaceReporter(MergeRequestBase):
|
|
35
35
|
def description(self) -> str:
|
36
36
|
return f"reports for {self.isodate}"
|
37
37
|
|
38
|
-
def process(self, gitlab_cli):
|
38
|
+
def process(self, gitlab_cli: GitLabApi) -> None:
|
39
39
|
actions = [
|
40
40
|
{
|
41
41
|
"action": "create",
|
reconcile/utils/mr/aws_access.py
CHANGED
@@ -5,6 +5,7 @@ from ruamel import yaml
|
|
5
5
|
from ruamel.yaml.scalarstring import PreservedScalarString as pss
|
6
6
|
|
7
7
|
from reconcile.utils.constants import PROJ_ROOT
|
8
|
+
from reconcile.utils.gitlab_api import GitLabApi
|
8
9
|
from reconcile.utils.mr.base import (
|
9
10
|
MergeRequestBase,
|
10
11
|
app_interface_email,
|
@@ -15,7 +16,6 @@ BODY_TEMPLATE = PROJ_ROOT / "templates" / "aws_access_key_email.j2"
|
|
15
16
|
|
16
17
|
|
17
18
|
class CreateDeleteAwsAccessKey(MergeRequestBase):
|
18
|
-
|
19
19
|
name = "create_delete_aws_access_key_mr"
|
20
20
|
|
21
21
|
def __init__(self, account, path, key):
|
@@ -35,10 +35,10 @@ class CreateDeleteAwsAccessKey(MergeRequestBase):
|
|
35
35
|
def description(self) -> str:
|
36
36
|
return f"delete {self.account} access key {self.key}"
|
37
37
|
|
38
|
-
def process(self, gitlab_cli):
|
38
|
+
def process(self, gitlab_cli: GitLabApi) -> None:
|
39
39
|
# add key to deleteKeys list to be picked up by aws-iam-keys
|
40
40
|
raw_file = gitlab_cli.project.files.get(
|
41
|
-
file_path=self.path, ref=
|
41
|
+
file_path=self.path, ref=gitlab_cli.main_branch
|
42
42
|
)
|
43
43
|
content = yaml.load(raw_file.decode(), Loader=yaml.RoundTripLoader)
|
44
44
|
|
@@ -57,7 +57,7 @@ class CreateDeleteAwsAccessKey(MergeRequestBase):
|
|
57
57
|
)
|
58
58
|
|
59
59
|
# add a new email to be picked up by email-sender
|
60
|
-
with open(BODY_TEMPLATE) as file_obj:
|
60
|
+
with open(BODY_TEMPLATE, encoding="locale") as file_obj:
|
61
61
|
body_template = Template(
|
62
62
|
file_obj.read(), keep_trailing_newline=True, trim_blocks=True
|
63
63
|
)
|
reconcile/utils/mr/base.py
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
import json
|
2
2
|
import logging
|
3
3
|
from abc import (
|
4
|
-
|
4
|
+
ABC,
|
5
5
|
abstractmethod,
|
6
6
|
)
|
7
|
-
from
|
8
|
-
|
9
|
-
Union,
|
10
|
-
)
|
7
|
+
from collections.abc import Iterable
|
8
|
+
from typing import Any
|
11
9
|
from uuid import uuid4
|
12
10
|
|
13
11
|
from gitlab.exceptions import GitlabError
|
14
12
|
from jinja2 import Template
|
15
13
|
|
14
|
+
from reconcile import typed_queries
|
15
|
+
from reconcile.gql_definitions.fragments.user import User
|
16
16
|
from reconcile.utils.constants import PROJ_ROOT
|
17
17
|
from reconcile.utils.gitlab_api import GitLabApi
|
18
18
|
from reconcile.utils.mr.labels import DO_NOT_MERGE_HOLD
|
@@ -35,10 +35,10 @@ class MergeRequestProcessingError(Exception):
|
|
35
35
|
"""
|
36
36
|
|
37
37
|
|
38
|
-
MRClient =
|
38
|
+
MRClient = GitLabApi | SQSGateway
|
39
39
|
|
40
40
|
|
41
|
-
class MergeRequestBase(
|
41
|
+
class MergeRequestBase(ABC):
|
42
42
|
"""
|
43
43
|
Base abstract class for all merge request types.
|
44
44
|
"""
|
@@ -52,19 +52,17 @@ class MergeRequestBase(metaclass=ABCMeta):
|
|
52
52
|
# of the child class.
|
53
53
|
self.sqs_msg_data = {**self.__dict__}
|
54
54
|
|
55
|
-
self.gitlab_cli = None
|
56
55
|
self.labels = [DO_NOT_MERGE_HOLD]
|
57
56
|
|
58
57
|
random_id = str(uuid4())[:6]
|
59
58
|
self.branch = f"{self.name}-{random_id}"
|
60
59
|
self.branch_created = False
|
61
60
|
|
62
|
-
self.main_branch = "master"
|
63
61
|
self.remove_source_branch = True
|
64
62
|
|
65
63
|
self.cancelled = False
|
66
64
|
|
67
|
-
def cancel(self, message):
|
65
|
+
def cancel(self, message: str) -> None:
|
68
66
|
self.cancelled = True
|
69
67
|
raise CancelMergeRequest(
|
70
68
|
f"{self.name} MR canceled for "
|
@@ -93,7 +91,7 @@ class MergeRequestBase(metaclass=ABCMeta):
|
|
93
91
|
"""
|
94
92
|
|
95
93
|
@abstractmethod
|
96
|
-
def process(self, gitlab_cli):
|
94
|
+
def process(self, gitlab_cli: GitLabApi) -> None:
|
97
95
|
"""
|
98
96
|
Called by `submit_to_gitlab`, this method is the place for
|
99
97
|
user-defined steps to create the commits of a merge request.
|
@@ -103,7 +101,7 @@ class MergeRequestBase(metaclass=ABCMeta):
|
|
103
101
|
"""
|
104
102
|
|
105
103
|
@property
|
106
|
-
def sqs_data(self):
|
104
|
+
def sqs_data(self) -> dict[str, Any]:
|
107
105
|
"""
|
108
106
|
The SQS Message payload (MessageBody) generated out of
|
109
107
|
the Merge Request class instance.
|
@@ -113,7 +111,27 @@ class MergeRequestBase(metaclass=ABCMeta):
|
|
113
111
|
**self.sqs_msg_data,
|
114
112
|
}
|
115
113
|
|
116
|
-
def
|
114
|
+
def infer_author(
|
115
|
+
self, author_email: str | None, all_users: Iterable[User] | None = None
|
116
|
+
) -> str | None:
|
117
|
+
if not author_email:
|
118
|
+
return None
|
119
|
+
if not all_users:
|
120
|
+
return None
|
121
|
+
|
122
|
+
username = author_email.split("@")[0]
|
123
|
+
users = None
|
124
|
+
if author_email.endswith(typed_queries.smtp.settings().mail_address):
|
125
|
+
users = [u for u in all_users if username == u.org_username]
|
126
|
+
elif author_email.endswith("users.noreply.github.com"):
|
127
|
+
users = [u for u in all_users if username == u.github_username]
|
128
|
+
|
129
|
+
if users:
|
130
|
+
return users[0].org_username
|
131
|
+
|
132
|
+
return None
|
133
|
+
|
134
|
+
def submit_to_sqs(self, sqs_cli: SQSGateway) -> None:
|
117
135
|
"""
|
118
136
|
Sends the MR message to SQS.
|
119
137
|
|
@@ -122,21 +140,20 @@ class MergeRequestBase(metaclass=ABCMeta):
|
|
122
140
|
"""
|
123
141
|
sqs_cli.send_message(self.sqs_data)
|
124
142
|
|
125
|
-
|
126
|
-
def gitlab_data(self):
|
143
|
+
def gitlab_data(self, target_branch: str) -> dict[str, Any]:
|
127
144
|
"""
|
128
145
|
The Gitlab payload for creating the Merge Request.
|
129
146
|
"""
|
130
147
|
return {
|
131
148
|
"source_branch": self.branch,
|
132
|
-
"target_branch":
|
149
|
+
"target_branch": target_branch,
|
133
150
|
"title": self.title,
|
134
151
|
"description": self.description,
|
135
152
|
"remove_source_branch": self.remove_source_branch,
|
136
153
|
"labels": self.labels,
|
137
154
|
}
|
138
155
|
|
139
|
-
def submit_to_gitlab(self, gitlab_cli):
|
156
|
+
def submit_to_gitlab(self, gitlab_cli: GitLabApi) -> Any:
|
140
157
|
"""
|
141
158
|
Sends the MR to Gitlab.
|
142
159
|
|
@@ -163,11 +180,13 @@ class MergeRequestBase(metaclass=ABCMeta):
|
|
163
180
|
# Avoiding empty MRs
|
164
181
|
if not self.diffs(gitlab_cli):
|
165
182
|
self.cancel(
|
166
|
-
f"No changes when compared to {
|
183
|
+
f"No changes when compared to {gitlab_cli.main_branch}. "
|
167
184
|
"Aborting MR creation."
|
168
185
|
)
|
169
186
|
|
170
|
-
return gitlab_cli.project.mergerequests.create(
|
187
|
+
return gitlab_cli.project.mergerequests.create(
|
188
|
+
self.gitlab_data(target_branch=gitlab_cli.main_branch)
|
189
|
+
)
|
171
190
|
except CancelMergeRequest as mr_cancel:
|
172
191
|
# cancellation is a valid behaviour. it indicates, that the
|
173
192
|
# operation is not required, therefore we will not signal
|
@@ -187,14 +206,14 @@ class MergeRequestBase(metaclass=ABCMeta):
|
|
187
206
|
f"Reason: {err}"
|
188
207
|
) from err
|
189
208
|
|
190
|
-
def ensure_tmp_branch_exists(self, gitlab_cli):
|
209
|
+
def ensure_tmp_branch_exists(self, gitlab_cli: GitLabApi) -> None:
|
191
210
|
if not self.branch_created:
|
192
211
|
gitlab_cli.create_branch(
|
193
|
-
new_branch=self.branch, source_branch=
|
212
|
+
new_branch=self.branch, source_branch=gitlab_cli.main_branch
|
194
213
|
)
|
195
214
|
self.branch_created = True
|
196
215
|
|
197
|
-
def delete_tmp_branch(self, gitlab_cli):
|
216
|
+
def delete_tmp_branch(self, gitlab_cli: GitLabApi) -> None:
|
198
217
|
if self.branch_created:
|
199
218
|
try:
|
200
219
|
gitlab_cli.delete_branch(branch=self.branch)
|
@@ -206,17 +225,18 @@ class MergeRequestBase(metaclass=ABCMeta):
|
|
206
225
|
f"Failed to delete branch {self.branch}. " f"Reason: {gitlab_error}"
|
207
226
|
)
|
208
227
|
|
209
|
-
def diffs(self, gitlab_cli):
|
228
|
+
def diffs(self, gitlab_cli: GitLabApi) -> Any:
|
210
229
|
return gitlab_cli.project.repository_compare(
|
211
|
-
from_=
|
230
|
+
from_=gitlab_cli.main_branch, to=self.branch
|
212
231
|
)["diffs"]
|
213
232
|
|
214
|
-
def submit(self, cli: MRClient):
|
233
|
+
def submit(self, cli: MRClient) -> Any | None:
|
215
234
|
if isinstance(cli, GitLabApi):
|
216
235
|
return self.submit_to_gitlab(gitlab_cli=cli)
|
217
236
|
|
218
237
|
if isinstance(cli, SQSGateway):
|
219
|
-
|
238
|
+
self.submit_to_sqs(sqs_cli=cli)
|
239
|
+
return None
|
220
240
|
|
221
241
|
raise AttributeError(f"client {cli} not supported")
|
222
242
|
|
@@ -225,13 +245,13 @@ def app_interface_email(
|
|
225
245
|
name: str,
|
226
246
|
subject: str,
|
227
247
|
body: str,
|
228
|
-
users:
|
229
|
-
aliases:
|
230
|
-
aws_accounts:
|
231
|
-
apps:
|
248
|
+
users: list[str] | None = None,
|
249
|
+
aliases: list[str] | None = None,
|
250
|
+
aws_accounts: list[str] | None = None,
|
251
|
+
apps: list[str] | None = None,
|
232
252
|
) -> str:
|
233
253
|
"""Render app-interface-email template."""
|
234
|
-
with open(EMAIL_TEMPLATE) as file_obj:
|
254
|
+
with open(EMAIL_TEMPLATE, encoding="locale") as file_obj:
|
235
255
|
email_template = Template(
|
236
256
|
file_obj.read(), keep_trailing_newline=True, trim_blocks=True
|
237
257
|
)
|
@@ -3,14 +3,16 @@ from io import StringIO
|
|
3
3
|
from ruamel.yaml import YAML
|
4
4
|
|
5
5
|
from reconcile.change_owners.decision import DecisionCommand
|
6
|
+
from reconcile.utils.gitlab_api import GitLabApi
|
6
7
|
from reconcile.utils.mr.base import MergeRequestBase
|
7
8
|
|
8
9
|
yaml = YAML()
|
9
|
-
yaml.explicit_start = True
|
10
|
+
yaml.explicit_start = True
|
11
|
+
# Lets prevent line wraps
|
12
|
+
yaml.width = 4096
|
10
13
|
|
11
14
|
|
12
15
|
class CreateClustersUpdates(MergeRequestBase):
|
13
|
-
|
14
16
|
name = "create_clusters_updates_mr"
|
15
17
|
|
16
18
|
def __init__(self, clusters_updates):
|
@@ -28,7 +30,7 @@ class CreateClustersUpdates(MergeRequestBase):
|
|
28
30
|
def description(self) -> str:
|
29
31
|
return DecisionCommand.APPROVED.value
|
30
32
|
|
31
|
-
def process(self, gitlab_cli):
|
33
|
+
def process(self, gitlab_cli: GitLabApi):
|
32
34
|
changes = False
|
33
35
|
for cluster_name, cluster_updates in self.clusters_updates.items():
|
34
36
|
if not cluster_updates:
|
@@ -36,7 +38,7 @@ class CreateClustersUpdates(MergeRequestBase):
|
|
36
38
|
|
37
39
|
cluster_path = cluster_updates.pop("path")
|
38
40
|
raw_file = gitlab_cli.project.files.get(
|
39
|
-
file_path=cluster_path, ref=
|
41
|
+
file_path=cluster_path, ref=gitlab_cli.main_branch
|
40
42
|
)
|
41
43
|
content = yaml.load(raw_file.decode())
|
42
44
|
if "spec" not in content:
|
@@ -55,15 +57,16 @@ class CreateClustersUpdates(MergeRequestBase):
|
|
55
57
|
# content.update(cluster_updates) :(
|
56
58
|
content.update(cluster_updates["root"])
|
57
59
|
|
58
|
-
|
59
|
-
|
60
|
+
with StringIO() as stream:
|
61
|
+
yaml.dump(content, stream)
|
62
|
+
new_content = stream.getvalue()
|
60
63
|
|
61
64
|
msg = f"update cluster {cluster_name} spec fields"
|
62
65
|
gitlab_cli.update_file(
|
63
66
|
branch_name=self.branch,
|
64
67
|
file_path=cluster_path,
|
65
68
|
commit_message=msg,
|
66
|
-
content=new_content
|
69
|
+
content=new_content,
|
67
70
|
)
|
68
71
|
|
69
72
|
if not changes:
|