qontract-reconcile 0.10.2.dev361__py3-none-any.whl → 0.10.2.dev474__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/METADATA +14 -13
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/RECORD +371 -364
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/WHEEL +1 -1
- reconcile/acs_rbac.py +2 -2
- reconcile/aus/advanced_upgrade_service.py +18 -12
- reconcile/aus/aus_sts_gate_handler.py +59 -0
- reconcile/aus/base.py +137 -34
- reconcile/aus/cluster_version_data.py +15 -5
- reconcile/aus/models.py +3 -1
- reconcile/aus/ocm_addons_upgrade_scheduler_org.py +1 -0
- reconcile/aus/ocm_upgrade_scheduler.py +8 -1
- reconcile/aus/ocm_upgrade_scheduler_org.py +20 -5
- reconcile/aus/version_gate_approver.py +1 -16
- reconcile/aus/version_gates/sts_version_gate_handler.py +5 -72
- reconcile/automated_actions/config/integration.py +16 -4
- reconcile/aws_account_manager/integration.py +21 -9
- reconcile/aws_account_manager/reconciler.py +3 -3
- reconcile/aws_account_manager/utils.py +1 -1
- reconcile/aws_ami_cleanup/integration.py +8 -12
- reconcile/aws_ami_share.py +69 -62
- reconcile/aws_cloudwatch_log_retention/integration.py +155 -126
- reconcile/aws_ecr_image_pull_secrets.py +1 -1
- reconcile/aws_iam_keys.py +1 -0
- reconcile/aws_saml_idp/integration.py +12 -4
- reconcile/aws_saml_roles/integration.py +30 -23
- reconcile/aws_version_sync/integration.py +6 -12
- reconcile/change_owners/README.md +1 -1
- reconcile/change_owners/bundle.py +3 -3
- reconcile/change_owners/change_log_tracking.py +3 -2
- reconcile/change_owners/change_owners.py +108 -42
- reconcile/change_owners/decision.py +1 -1
- reconcile/change_owners/diff.py +0 -2
- reconcile/checkpoint.py +11 -3
- reconcile/cli.py +94 -11
- reconcile/dashdotdb_dora.py +5 -12
- reconcile/dashdotdb_slo.py +1 -1
- reconcile/database_access_manager.py +123 -117
- reconcile/dynatrace_token_provider/integration.py +1 -1
- reconcile/endpoints_discovery/integration.py +4 -1
- reconcile/endpoints_discovery/merge_request.py +1 -1
- reconcile/endpoints_discovery/merge_request_manager.py +8 -8
- reconcile/external_resources/factories.py +4 -6
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +8 -6
- reconcile/external_resources/meta.py +0 -1
- reconcile/external_resources/metrics.py +1 -1
- reconcile/external_resources/model.py +19 -15
- reconcile/external_resources/reconciler.py +7 -4
- reconcile/external_resources/secrets_sync.py +6 -10
- reconcile/external_resources/state.py +26 -16
- reconcile/fleet_labeler/integration.py +1 -1
- reconcile/gabi_authorized_users.py +5 -2
- reconcile/gcp_image_mirror.py +2 -2
- reconcile/github_org.py +1 -1
- reconcile/github_owners.py +4 -0
- reconcile/gitlab_housekeeping.py +13 -15
- reconcile/gitlab_members.py +6 -12
- reconcile/gitlab_owners.py +15 -11
- reconcile/gitlab_permissions.py +8 -12
- reconcile/glitchtip_project_alerts/integration.py +3 -1
- reconcile/gql_definitions/acs/acs_instances.py +5 -5
- reconcile/gql_definitions/acs/acs_policies.py +5 -5
- reconcile/gql_definitions/acs/acs_rbac.py +5 -5
- reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +5 -5
- reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +5 -5
- reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +5 -5
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
- reconcile/gql_definitions/automated_actions/instance.py +46 -7
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +14 -5
- reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +15 -5
- reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +27 -66
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +15 -5
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +15 -5
- reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
- reconcile/gql_definitions/aws_version_sync/clusters.py +5 -5
- reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
- reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
- reconcile/gql_definitions/change_owners/queries/self_service_roles.py +5 -5
- reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +5 -5
- reconcile/gql_definitions/common/alerting_services_settings.py +5 -5
- reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
- reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
- reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_roles.py +5 -5
- reconcile/gql_definitions/common/app_interface_state_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
- reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
- reconcile/gql_definitions/common/apps.py +5 -5
- reconcile/gql_definitions/common/aws_vpc_requests.py +18 -5
- reconcile/gql_definitions/common/aws_vpcs.py +5 -5
- reconcile/gql_definitions/common/clusters.py +7 -5
- reconcile/gql_definitions/common/clusters_minimal.py +5 -5
- reconcile/gql_definitions/common/clusters_with_dms.py +5 -5
- reconcile/gql_definitions/common/clusters_with_peering.py +5 -5
- reconcile/gql_definitions/common/github_orgs.py +5 -5
- reconcile/gql_definitions/common/jira_settings.py +5 -5
- reconcile/gql_definitions/common/jiralert_settings.py +5 -5
- reconcile/gql_definitions/common/ldap_settings.py +5 -5
- reconcile/gql_definitions/common/namespaces.py +5 -5
- reconcile/gql_definitions/common/namespaces_minimal.py +7 -5
- reconcile/gql_definitions/common/ocm_env_telemeter.py +5 -5
- reconcile/gql_definitions/common/ocm_environments.py +5 -5
- reconcile/gql_definitions/common/pagerduty_instances.py +5 -5
- reconcile/gql_definitions/common/pgp_reencryption_settings.py +5 -5
- reconcile/gql_definitions/common/pipeline_providers.py +5 -5
- reconcile/gql_definitions/common/quay_instances.py +5 -5
- reconcile/gql_definitions/common/quay_orgs.py +5 -5
- reconcile/gql_definitions/common/reserved_networks.py +5 -5
- reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
- reconcile/gql_definitions/common/saas_files.py +5 -5
- reconcile/gql_definitions/common/saas_target_namespaces.py +5 -5
- reconcile/gql_definitions/common/saasherder_settings.py +5 -5
- reconcile/gql_definitions/common/slack_workspaces.py +5 -5
- reconcile/gql_definitions/common/smtp_client_settings.py +5 -5
- reconcile/gql_definitions/common/state_aws_account.py +5 -5
- reconcile/gql_definitions/common/users.py +5 -5
- reconcile/gql_definitions/common/users_with_paths.py +5 -5
- reconcile/gql_definitions/cost_report/app_names.py +5 -5
- reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
- reconcile/gql_definitions/cost_report/settings.py +5 -5
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +5 -5
- reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +5 -5
- reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
- reconcile/gql_definitions/email_sender/apps.py +5 -5
- reconcile/gql_definitions/email_sender/emails.py +5 -5
- reconcile/gql_definitions/email_sender/users.py +5 -5
- reconcile/gql_definitions/endpoints_discovery/apps.py +5 -5
- reconcile/gql_definitions/external_resources/aws_accounts.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_modules.py +5 -5
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py +38 -7
- reconcile/gql_definitions/external_resources/external_resources_settings.py +5 -5
- reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
- reconcile/gql_definitions/fleet_labeler/fleet_labels.py +5 -5
- reconcile/gql_definitions/fragments/aus_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_common.py +7 -5
- reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
- reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
- reconcile/gql_definitions/fragments/aws_organization.py +33 -0
- reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc_request.py +12 -5
- reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
- reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
- reconcile/gql_definitions/fragments/disable.py +5 -5
- reconcile/gql_definitions/fragments/email_service.py +5 -5
- reconcile/gql_definitions/fragments/email_user.py +5 -5
- reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
- reconcile/gql_definitions/fragments/membership_source.py +5 -5
- reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
- reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
- reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
- reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
- reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
- reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_values.py +5 -5
- reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
- reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
- reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
- reconcile/gql_definitions/fragments/terraform_state.py +5 -5
- reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
- reconcile/gql_definitions/fragments/user.py +5 -5
- reconcile/gql_definitions/fragments/vault_secret.py +5 -5
- reconcile/gql_definitions/gcp/gcp_docker_repos.py +5 -5
- reconcile/gql_definitions/gcp/gcp_projects.py +5 -5
- reconcile/gql_definitions/gitlab_members/gitlab_instances.py +5 -5
- reconcile/gql_definitions/gitlab_members/permissions.py +5 -5
- reconcile/gql_definitions/glitchtip/glitchtip_instance.py +5 -5
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +5 -5
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +5 -5
- reconcile/gql_definitions/integrations/integrations.py +5 -5
- reconcile/gql_definitions/introspection.json +775 -136
- reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +5 -5
- reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +5 -5
- reconcile/gql_definitions/jira/jira_servers.py +5 -5
- reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +9 -5
- reconcile/gql_definitions/jumphosts/jumphosts.py +5 -5
- reconcile/gql_definitions/ldap_groups/roles.py +5 -5
- reconcile/gql_definitions/ldap_groups/settings.py +5 -5
- reconcile/gql_definitions/maintenance/maintenances.py +5 -5
- reconcile/gql_definitions/membershipsources/roles.py +5 -5
- reconcile/gql_definitions/ocm_labels/clusters.py +5 -5
- reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
- reconcile/gql_definitions/openshift_cluster_bots/clusters.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_roles.py +5 -5
- reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +5 -5
- reconcile/gql_definitions/quay_membership/quay_membership.py +5 -5
- reconcile/gql_definitions/rhcs/certs.py +25 -79
- reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +43 -0
- reconcile/gql_definitions/rhidp/organizations.py +5 -5
- reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
- reconcile/gql_definitions/service_dependencies/service_dependencies.py +5 -5
- reconcile/gql_definitions/sharding/aws_accounts.py +5 -5
- reconcile/gql_definitions/sharding/ocm_organization.py +5 -5
- reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
- reconcile/gql_definitions/skupper_network/skupper_networks.py +5 -5
- reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
- reconcile/gql_definitions/slack_usergroups/permissions.py +5 -5
- reconcile/gql_definitions/slack_usergroups/users.py +5 -5
- reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
- reconcile/gql_definitions/status_board/status_board.py +5 -5
- reconcile/gql_definitions/statuspage/statuspages.py +5 -5
- reconcile/gql_definitions/templating/template_collection.py +5 -5
- reconcile/gql_definitions/templating/templates.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +5 -5
- reconcile/gql_definitions/terraform_init/aws_accounts.py +19 -5
- reconcile/gql_definitions/terraform_repo/terraform_repo.py +5 -5
- reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +37 -7
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +15 -5
- reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +5 -5
- reconcile/gql_definitions/vault_instances/vault_instances.py +5 -5
- reconcile/gql_definitions/vault_policies/vault_policies.py +5 -5
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +8 -5
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +6 -5
- reconcile/integrations_manager.py +3 -3
- reconcile/jenkins_worker_fleets.py +10 -8
- reconcile/jira_permissions_validator.py +237 -122
- reconcile/ldap_groups/integration.py +1 -1
- reconcile/ocm/types.py +35 -57
- reconcile/ocm_aws_infrastructure_access.py +1 -1
- reconcile/ocm_clusters.py +4 -4
- reconcile/ocm_labels/integration.py +3 -2
- reconcile/ocm_machine_pools.py +33 -27
- reconcile/openshift_base.py +113 -4
- reconcile/openshift_cluster_bots.py +1 -1
- reconcile/openshift_namespace_labels.py +1 -1
- reconcile/openshift_namespaces.py +96 -101
- reconcile/openshift_resources_base.py +6 -2
- reconcile/openshift_rhcs_certs.py +74 -37
- reconcile/openshift_rolebindings.py +7 -11
- reconcile/openshift_saas_deploy.py +4 -5
- reconcile/openshift_saas_deploy_change_tester.py +9 -7
- reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
- reconcile/openshift_serviceaccount_tokens.py +2 -2
- reconcile/openshift_upgrade_watcher.py +4 -4
- reconcile/oum/labelset.py +5 -3
- reconcile/oum/models.py +1 -4
- reconcile/prometheus_rules_tester/integration.py +3 -3
- reconcile/quay_base.py +25 -6
- reconcile/quay_membership.py +55 -29
- reconcile/quay_mirror.py +1 -1
- reconcile/quay_mirror_org.py +6 -4
- reconcile/quay_permissions.py +81 -75
- reconcile/quay_repos.py +35 -37
- reconcile/queries.py +132 -1
- reconcile/rhidp/common.py +3 -5
- reconcile/rhidp/sso_client/base.py +16 -5
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
- reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
- reconcile/skupper_network/integration.py +2 -2
- reconcile/slack_usergroups.py +35 -14
- reconcile/sql_query.py +1 -0
- reconcile/status_board.py +6 -6
- reconcile/statuspage/atlassian.py +7 -7
- reconcile/statuspage/integrations/maintenances.py +4 -3
- reconcile/statuspage/page.py +4 -9
- reconcile/statuspage/status.py +5 -8
- reconcile/templates/rosa-classic-cluster-creation.sh.j2 +1 -1
- reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +1 -1
- reconcile/templating/lib/rendering.py +3 -3
- reconcile/templating/renderer.py +2 -2
- reconcile/templating/validator.py +4 -4
- reconcile/terraform_aws_route53.py +7 -1
- reconcile/terraform_cloudflare_dns.py +3 -3
- reconcile/terraform_cloudflare_resources.py +5 -5
- reconcile/terraform_cloudflare_users.py +3 -2
- reconcile/terraform_init/integration.py +187 -23
- reconcile/terraform_repo.py +16 -12
- reconcile/terraform_resources.py +6 -6
- reconcile/terraform_tgw_attachments.py +27 -19
- reconcile/terraform_users.py +7 -0
- reconcile/terraform_vpc_peerings.py +14 -3
- reconcile/terraform_vpc_resources/integration.py +20 -8
- reconcile/terraform_vpc_resources/merge_request.py +12 -2
- reconcile/terraform_vpc_resources/merge_request_manager.py +43 -19
- reconcile/typed_queries/aws_account_tags.py +41 -0
- reconcile/typed_queries/cost_report/app_names.py +1 -1
- reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
- reconcile/typed_queries/saas_files.py +20 -15
- reconcile/typed_queries/status_board.py +2 -2
- reconcile/unleash_feature_toggles/integration.py +4 -2
- reconcile/utils/acs/base.py +6 -3
- reconcile/utils/acs/policies.py +2 -2
- reconcile/utils/aws_api.py +51 -20
- reconcile/utils/aws_api_typed/api.py +38 -9
- reconcile/utils/aws_api_typed/cloudformation.py +149 -0
- reconcile/utils/aws_api_typed/logs.py +73 -0
- reconcile/utils/aws_api_typed/organization.py +4 -2
- reconcile/utils/binary.py +7 -12
- reconcile/utils/datetime_util.py +67 -0
- reconcile/utils/deadmanssnitch_api.py +1 -1
- reconcile/utils/differ.py +2 -3
- reconcile/utils/early_exit_cache.py +11 -12
- reconcile/utils/environ.py +5 -0
- reconcile/utils/expiration.py +7 -3
- reconcile/utils/external_resource_spec.py +2 -0
- reconcile/utils/filtering.py +1 -1
- reconcile/utils/gitlab_api.py +19 -5
- reconcile/utils/glitchtip/client.py +6 -2
- reconcile/utils/glitchtip/models.py +25 -28
- reconcile/utils/gql.py +4 -7
- reconcile/utils/helpers.py +1 -1
- reconcile/utils/instrumented_wrappers.py +1 -1
- reconcile/utils/internal_groups/client.py +2 -2
- reconcile/utils/internal_groups/models.py +8 -17
- reconcile/utils/jinja2/utils.py +6 -101
- reconcile/utils/jira_client.py +82 -63
- reconcile/utils/jjb_client.py +26 -13
- reconcile/utils/jobcontroller/controller.py +2 -2
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/json.py +43 -1
- reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
- reconcile/utils/membershipsources/models.py +16 -23
- reconcile/utils/membershipsources/resolver.py +4 -2
- reconcile/utils/merge_request_manager/merge_request_manager.py +4 -4
- reconcile/utils/merge_request_manager/parser.py +6 -6
- reconcile/utils/metrics.py +5 -5
- reconcile/utils/models.py +304 -82
- reconcile/utils/mr/app_interface_reporter.py +2 -2
- reconcile/utils/mr/notificator.py +3 -3
- reconcile/utils/mr/update_access_report_base.py +3 -4
- reconcile/utils/mr/user_maintenance.py +3 -2
- reconcile/utils/oc.py +252 -201
- reconcile/utils/oc_filters.py +3 -3
- reconcile/utils/ocm/addons.py +0 -1
- reconcile/utils/ocm/base.py +17 -20
- reconcile/utils/ocm/cluster_groups.py +1 -1
- reconcile/utils/ocm/identity_providers.py +2 -2
- reconcile/utils/ocm/labels.py +1 -1
- reconcile/utils/ocm/products.py +8 -8
- reconcile/utils/ocm/search_filters.py +3 -6
- reconcile/utils/ocm/service_log.py +4 -6
- reconcile/utils/ocm/sre_capability_labels.py +20 -13
- reconcile/utils/openshift_resource.py +8 -3
- reconcile/utils/pagerduty_api.py +10 -7
- reconcile/utils/promotion_state.py +6 -11
- reconcile/utils/quay_api.py +74 -87
- reconcile/utils/raw_github_api.py +1 -1
- reconcile/utils/rhcsv2_certs.py +86 -23
- reconcile/utils/rosa/session.py +16 -0
- reconcile/utils/runtime/integration.py +2 -3
- reconcile/utils/runtime/runner.py +2 -2
- reconcile/utils/saasherder/interfaces.py +13 -20
- reconcile/utils/saasherder/models.py +23 -20
- reconcile/utils/saasherder/saasherder.py +50 -27
- reconcile/utils/slack_api.py +2 -2
- reconcile/utils/sloth.py +171 -2
- reconcile/utils/structs.py +1 -1
- reconcile/utils/terraform_client.py +5 -4
- reconcile/utils/terrascript_aws_client.py +274 -124
- reconcile/utils/unleash/server.py +2 -8
- reconcile/utils/vault.py +5 -12
- reconcile/utils/vcs.py +8 -8
- reconcile/vault_replication.py +107 -42
- reconcile/vpc_peerings_validator.py +13 -0
- tools/app_interface_reporter.py +4 -4
- tools/cli_commands/cost_report/cost_management_api.py +3 -3
- tools/cli_commands/cost_report/view.py +7 -6
- tools/cli_commands/erv2.py +1 -1
- tools/qontract_cli.py +28 -17
- tools/template_validation.py +3 -1
- {qontract_reconcile-0.10.2.dev361.dist-info → qontract_reconcile-0.10.2.dev474.dist-info}/entry_points.txt +0 -0
reconcile/quay_membership.py
CHANGED
|
@@ -10,7 +10,7 @@ from reconcile.gql_definitions.quay_membership.quay_membership import (
|
|
|
10
10
|
PermissionQuayOrgTeamV1,
|
|
11
11
|
UserV1,
|
|
12
12
|
)
|
|
13
|
-
from reconcile.quay_base import
|
|
13
|
+
from reconcile.quay_base import OrgKey, QuayApiStore
|
|
14
14
|
from reconcile.status import ExitCodes
|
|
15
15
|
from reconcile.utils import (
|
|
16
16
|
expiration,
|
|
@@ -58,10 +58,11 @@ def fetch_current_state(quay_api_store: QuayApiStore) -> AggregatedList:
|
|
|
58
58
|
state = AggregatedList()
|
|
59
59
|
|
|
60
60
|
for org_key, org_data in quay_api_store.items():
|
|
61
|
-
quay_api = org_data["api"]
|
|
62
61
|
teams = org_data["teams"]
|
|
63
62
|
if not teams:
|
|
64
63
|
continue
|
|
64
|
+
|
|
65
|
+
quay_api = org_data["api"]
|
|
65
66
|
for team in teams:
|
|
66
67
|
try:
|
|
67
68
|
members = quay_api.list_team_members(team)
|
|
@@ -76,8 +77,13 @@ def fetch_current_state(quay_api_store: QuayApiStore) -> AggregatedList:
|
|
|
76
77
|
else:
|
|
77
78
|
# Teams are only added to the state if they exist so that
|
|
78
79
|
# there is a proper diff between the desired and current state.
|
|
80
|
+
# Use tuple format (instance, org_name) to match desired state format
|
|
79
81
|
state.add(
|
|
80
|
-
{
|
|
82
|
+
{
|
|
83
|
+
"service": "quay-membership",
|
|
84
|
+
"org": (org_key.instance, org_key.org_name),
|
|
85
|
+
"team": team,
|
|
86
|
+
},
|
|
81
87
|
members,
|
|
82
88
|
)
|
|
83
89
|
return state
|
|
@@ -117,9 +123,16 @@ class RunnerAction:
|
|
|
117
123
|
def action(params: dict, items: list) -> bool:
|
|
118
124
|
org = params["org"]
|
|
119
125
|
team = params["team"]
|
|
126
|
+
# Convert org tuple (instance, org_name) to OrgKey for lookup
|
|
127
|
+
org_key = (
|
|
128
|
+
OrgKey(org[0], org[1])
|
|
129
|
+
if isinstance(org, tuple)
|
|
130
|
+
else OrgKey("quay.io", org)
|
|
131
|
+
)
|
|
132
|
+
org_data = self.quay_api_store[org_key]
|
|
133
|
+
quay_api = org_data["api"]
|
|
120
134
|
|
|
121
135
|
missing_users = False
|
|
122
|
-
quay_api = self.quay_api_store[org]["api"]
|
|
123
136
|
for member in items:
|
|
124
137
|
logging.info([label, member, org, team])
|
|
125
138
|
user_exists = quay_api.user_exists(member)
|
|
@@ -147,19 +160,26 @@ class RunnerAction:
|
|
|
147
160
|
def action(params: dict, items: list) -> bool:
|
|
148
161
|
org = params["org"]
|
|
149
162
|
team = params["team"]
|
|
163
|
+
# Convert org tuple (instance, org_name) to OrgKey for lookup
|
|
164
|
+
org_key = (
|
|
165
|
+
OrgKey(org[0], org[1])
|
|
166
|
+
if isinstance(org, tuple)
|
|
167
|
+
else OrgKey("quay.io", org)
|
|
168
|
+
)
|
|
169
|
+
org_data = self.quay_api_store[org_key]
|
|
150
170
|
|
|
151
171
|
# Ensure all quay org/teams are declared as dependencies in a
|
|
152
172
|
# `/dependencies/quay-org-1.yml` datafile.
|
|
153
|
-
if team not in
|
|
173
|
+
if team not in org_data["teams"]:
|
|
154
174
|
raise RunnerError(
|
|
155
175
|
f"Quay team {team} is not defined as a "
|
|
156
|
-
f"managedTeam in the {
|
|
176
|
+
f"managedTeam in the {org_key.org_name} org."
|
|
157
177
|
)
|
|
158
178
|
|
|
159
179
|
logging.info([label, org, team])
|
|
160
180
|
|
|
161
181
|
if not self.dry_run:
|
|
162
|
-
quay_api =
|
|
182
|
+
quay_api = org_data["api"]
|
|
163
183
|
quay_api.create_or_update_team(team)
|
|
164
184
|
|
|
165
185
|
return True
|
|
@@ -172,12 +192,19 @@ class RunnerAction:
|
|
|
172
192
|
def action(params: dict, items: list) -> bool:
|
|
173
193
|
org = params["org"]
|
|
174
194
|
team = params["team"]
|
|
195
|
+
# Convert org tuple (instance, org_name) to OrgKey for lookup
|
|
196
|
+
org_key = (
|
|
197
|
+
OrgKey(org[0], org[1])
|
|
198
|
+
if isinstance(org, tuple)
|
|
199
|
+
else OrgKey("quay.io", org)
|
|
200
|
+
)
|
|
201
|
+
org_data = self.quay_api_store[org_key]
|
|
175
202
|
|
|
203
|
+
quay_api = org_data["api"]
|
|
176
204
|
if self.dry_run:
|
|
177
205
|
for member in items:
|
|
178
206
|
logging.info([label, member, org, team])
|
|
179
207
|
else:
|
|
180
|
-
quay_api = self.quay_api_store[org]["api"]
|
|
181
208
|
for member in items:
|
|
182
209
|
logging.info([label, member, org, team])
|
|
183
210
|
quay_api.remove_user_from_team(member, team)
|
|
@@ -188,24 +215,23 @@ class RunnerAction:
|
|
|
188
215
|
|
|
189
216
|
|
|
190
217
|
def run(dry_run: bool) -> None:
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
sys.exit(ExitCodes.ERROR)
|
|
218
|
+
with QuayApiStore() as quay_api_store:
|
|
219
|
+
current_state = fetch_current_state(quay_api_store)
|
|
220
|
+
desired_state = fetch_desired_state()
|
|
221
|
+
|
|
222
|
+
# calculate diff
|
|
223
|
+
diff = current_state.diff(desired_state)
|
|
224
|
+
logging.debug("State diff: %s", diff)
|
|
225
|
+
|
|
226
|
+
# Run actions
|
|
227
|
+
runner_action = RunnerAction(dry_run, quay_api_store)
|
|
228
|
+
runner = AggregatedDiffRunner(diff)
|
|
229
|
+
|
|
230
|
+
runner.register("insert", runner_action.create_team())
|
|
231
|
+
runner.register("update-insert", runner_action.add_to_team())
|
|
232
|
+
runner.register("update-delete", runner_action.del_from_team())
|
|
233
|
+
runner.register("delete", runner_action.del_from_team())
|
|
234
|
+
|
|
235
|
+
status = runner.run()
|
|
236
|
+
if not status:
|
|
237
|
+
sys.exit(ExitCodes.ERROR)
|
reconcile/quay_mirror.py
CHANGED
reconcile/quay_mirror_org.py
CHANGED
|
@@ -17,7 +17,7 @@ from sretoolbox.container.image import (
|
|
|
17
17
|
)
|
|
18
18
|
from sretoolbox.container.skopeo import SkopeoCmdError
|
|
19
19
|
|
|
20
|
-
from reconcile.quay_base import
|
|
20
|
+
from reconcile.quay_base import QuayApiStore
|
|
21
21
|
from reconcile.quay_mirror import QuayMirror
|
|
22
22
|
from reconcile.utils.quay_mirror import record_timestamp, sync_tag
|
|
23
23
|
|
|
@@ -45,7 +45,7 @@ class QuayMirrorOrg:
|
|
|
45
45
|
) -> None:
|
|
46
46
|
self.dry_run = dry_run
|
|
47
47
|
self.skopeo_cli = Skopeo(dry_run)
|
|
48
|
-
self.quay_api_store =
|
|
48
|
+
self.quay_api_store = QuayApiStore()
|
|
49
49
|
self.compare_tags = compare_tags
|
|
50
50
|
self.compare_tags_interval = compare_tags_interval
|
|
51
51
|
self.orgs = orgs
|
|
@@ -71,6 +71,7 @@ class QuayMirrorOrg:
|
|
|
71
71
|
|
|
72
72
|
def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
|
73
73
|
self.session.close()
|
|
74
|
+
self.quay_api_store.cleanup()
|
|
74
75
|
|
|
75
76
|
def run(self) -> None:
|
|
76
77
|
sync_tasks = self.process_sync_tasks()
|
|
@@ -101,11 +102,9 @@ class QuayMirrorOrg:
|
|
|
101
102
|
if self.orgs and org_key.org_name not in self.orgs:
|
|
102
103
|
continue
|
|
103
104
|
|
|
104
|
-
quay_api = org_info["api"]
|
|
105
105
|
upstream_org_key = org_info["mirror"]
|
|
106
106
|
assert upstream_org_key is not None
|
|
107
107
|
upstream_org = self.quay_api_store[upstream_org_key]
|
|
108
|
-
upstream_quay_api = upstream_org["api"]
|
|
109
108
|
|
|
110
109
|
push_token = upstream_org["push_token"]
|
|
111
110
|
|
|
@@ -114,7 +113,10 @@ class QuayMirrorOrg:
|
|
|
114
113
|
username = push_token["user"]
|
|
115
114
|
token = push_token["token"]
|
|
116
115
|
|
|
116
|
+
quay_api = org_info["api"]
|
|
117
117
|
org_repos = [item["name"] for item in quay_api.list_images()]
|
|
118
|
+
|
|
119
|
+
upstream_quay_api = upstream_org["api"]
|
|
118
120
|
for repo in upstream_quay_api.list_images():
|
|
119
121
|
if repo["name"] not in org_repos:
|
|
120
122
|
continue
|
reconcile/quay_permissions.py
CHANGED
|
@@ -2,7 +2,10 @@ import logging
|
|
|
2
2
|
import sys
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
|
-
from reconcile.quay_base import
|
|
5
|
+
from reconcile.quay_base import (
|
|
6
|
+
OrgKey,
|
|
7
|
+
QuayApiStore,
|
|
8
|
+
)
|
|
6
9
|
from reconcile.status import ExitCodes
|
|
7
10
|
from reconcile.utils import gql
|
|
8
11
|
|
|
@@ -57,85 +60,88 @@ def run(dry_run: bool) -> None:
|
|
|
57
60
|
return
|
|
58
61
|
|
|
59
62
|
apps: list[dict[str, Any]] = result.get("apps") or []
|
|
60
|
-
quay_api_store = get_quay_api_store()
|
|
61
63
|
error = False
|
|
62
|
-
for app in apps:
|
|
63
|
-
quay_repo_configs = app.get("quayRepos")
|
|
64
|
-
if not quay_repo_configs:
|
|
65
|
-
continue
|
|
66
|
-
for quay_repo_config in quay_repo_configs:
|
|
67
|
-
instance_name = quay_repo_config["org"]["instance"]["name"]
|
|
68
|
-
org_name = quay_repo_config["org"]["name"]
|
|
69
|
-
org_key = OrgKey(instance_name, org_name)
|
|
70
|
-
|
|
71
|
-
if not quay_repo_config["org"]["managedRepos"]:
|
|
72
|
-
logging.error(
|
|
73
|
-
f"[{app['name']}] Can not manage repo permissions in {org_name} "
|
|
74
|
-
"since managedRepos is set to false."
|
|
75
|
-
)
|
|
76
|
-
error = True
|
|
77
|
-
continue
|
|
78
|
-
|
|
79
|
-
# processing quayRepos section
|
|
80
|
-
logging.debug(["app", app["name"], instance_name, org_name])
|
|
81
64
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
65
|
+
with QuayApiStore() as quay_api_store:
|
|
66
|
+
for app in apps:
|
|
67
|
+
quay_repo_configs = app.get("quayRepos")
|
|
68
|
+
if not quay_repo_configs:
|
|
85
69
|
continue
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
70
|
+
for quay_repo_config in quay_repo_configs:
|
|
71
|
+
instance_name = quay_repo_config["org"]["instance"]["name"]
|
|
72
|
+
org_name = quay_repo_config["org"]["name"]
|
|
73
|
+
org_key = OrgKey(instance_name, org_name)
|
|
74
|
+
|
|
75
|
+
if not quay_repo_config["org"]["managedRepos"]:
|
|
76
|
+
logging.error(
|
|
77
|
+
f"[{app['name']}] Can not manage repo permissions in {org_name} "
|
|
78
|
+
"since managedRepos is set to false."
|
|
79
|
+
)
|
|
80
|
+
error = True
|
|
81
|
+
continue
|
|
82
|
+
|
|
83
|
+
# processing quayRepos section
|
|
84
|
+
logging.debug(["app", app["name"], instance_name, org_name])
|
|
85
|
+
|
|
86
|
+
org_data = quay_api_store[org_key]
|
|
87
|
+
teams = quay_repo_config.get("teams")
|
|
88
|
+
if not teams:
|
|
89
|
+
continue
|
|
90
|
+
repos = quay_repo_config["items"]
|
|
91
|
+
quay_api = org_data["api"]
|
|
92
|
+
|
|
93
|
+
for repo in repos:
|
|
94
|
+
repo_name = repo["name"]
|
|
95
|
+
|
|
96
|
+
# processing repo section
|
|
97
|
+
logging.debug(["repo", repo_name])
|
|
98
|
+
|
|
99
|
+
for team in teams:
|
|
100
|
+
permissions = team["permissions"]
|
|
101
|
+
role = team["role"]
|
|
102
|
+
for permission in permissions:
|
|
103
|
+
if permission["service"] != "quay-membership":
|
|
104
|
+
logging.warning(
|
|
105
|
+
"wrong service kind, should be quay-membership"
|
|
106
|
+
)
|
|
107
|
+
continue
|
|
108
|
+
|
|
109
|
+
perm_org_key = OrgKey(
|
|
110
|
+
permission["quayOrg"]["instance"]["name"],
|
|
111
|
+
permission["quayOrg"]["name"],
|
|
100
112
|
)
|
|
101
|
-
continue
|
|
102
|
-
|
|
103
|
-
perm_org_key = OrgKey(
|
|
104
|
-
permission["quayOrg"]["instance"]["name"],
|
|
105
|
-
permission["quayOrg"]["name"],
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
if perm_org_key != org_key:
|
|
109
|
-
logging.warning(f"wrong org, should be {org_key}")
|
|
110
|
-
continue
|
|
111
113
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
114
|
+
if perm_org_key != org_key:
|
|
115
|
+
logging.warning(f"wrong org, should be {org_key}")
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
team_name = permission["team"]
|
|
119
|
+
|
|
120
|
+
# processing team section
|
|
121
|
+
logging.debug(["team", team_name])
|
|
122
|
+
try:
|
|
123
|
+
current_role = quay_api.get_repo_team_permissions(
|
|
124
|
+
repo_name, team_name
|
|
125
|
+
)
|
|
126
|
+
if current_role != role:
|
|
127
|
+
logging.info([
|
|
128
|
+
"update_role",
|
|
129
|
+
org_key,
|
|
130
|
+
repo_name,
|
|
131
|
+
team_name,
|
|
132
|
+
role,
|
|
133
|
+
])
|
|
134
|
+
if not dry_run:
|
|
135
|
+
quay_api.set_repo_team_permissions(
|
|
136
|
+
repo_name, team_name, role
|
|
137
|
+
)
|
|
138
|
+
except Exception:
|
|
139
|
+
error = True
|
|
140
|
+
logging.exception(
|
|
141
|
+
"could not manage repo permissions: "
|
|
142
|
+
f"repo name: {repo_name}, "
|
|
143
|
+
f"team name: {team_name}"
|
|
144
|
+
)
|
|
139
145
|
|
|
140
146
|
if error:
|
|
141
147
|
sys.exit(ExitCodes.ERROR)
|
reconcile/quay_repos.py
CHANGED
|
@@ -3,18 +3,14 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
import sys
|
|
5
5
|
from collections import namedtuple
|
|
6
|
-
from typing import TYPE_CHECKING
|
|
7
6
|
|
|
8
7
|
from reconcile.quay_base import (
|
|
9
8
|
OrgKey,
|
|
10
|
-
|
|
9
|
+
QuayApiStore,
|
|
11
10
|
)
|
|
12
11
|
from reconcile.status import ExitCodes
|
|
13
12
|
from reconcile.utils import gql
|
|
14
13
|
|
|
15
|
-
if TYPE_CHECKING:
|
|
16
|
-
from reconcile.quay_base import QuayApiStore
|
|
17
|
-
|
|
18
14
|
QUAY_REPOS_QUERY = """
|
|
19
15
|
{
|
|
20
16
|
apps: apps_v1 {
|
|
@@ -51,7 +47,6 @@ def fetch_current_state(quay_api_store: QuayApiStore) -> list[RepoInfo]:
|
|
|
51
47
|
continue
|
|
52
48
|
|
|
53
49
|
quay_api = org_info["api"]
|
|
54
|
-
|
|
55
50
|
for repo in quay_api.list_images():
|
|
56
51
|
name = repo["name"]
|
|
57
52
|
public = repo["is_public"]
|
|
@@ -150,7 +145,8 @@ def act_delete(
|
|
|
150
145
|
current_repo.name,
|
|
151
146
|
])
|
|
152
147
|
if not dry_run:
|
|
153
|
-
|
|
148
|
+
org_data = quay_api_store[current_repo.org_key]
|
|
149
|
+
api = org_data["api"]
|
|
154
150
|
api.repo_delete(current_repo.name)
|
|
155
151
|
|
|
156
152
|
|
|
@@ -164,7 +160,8 @@ def act_create(
|
|
|
164
160
|
desired_repo.name,
|
|
165
161
|
])
|
|
166
162
|
if not dry_run:
|
|
167
|
-
|
|
163
|
+
org_data = quay_api_store[desired_repo.org_key]
|
|
164
|
+
api = org_data["api"]
|
|
168
165
|
api.repo_create(
|
|
169
166
|
desired_repo.name, desired_repo.description, desired_repo.public
|
|
170
167
|
)
|
|
@@ -180,7 +177,8 @@ def act_description(
|
|
|
180
177
|
desired_repo.description,
|
|
181
178
|
])
|
|
182
179
|
if not dry_run:
|
|
183
|
-
|
|
180
|
+
org_data = quay_api_store[desired_repo.org_key]
|
|
181
|
+
api = org_data["api"]
|
|
184
182
|
api.repo_update_description(desired_repo.name, desired_repo.description)
|
|
185
183
|
|
|
186
184
|
|
|
@@ -194,7 +192,8 @@ def act_public(
|
|
|
194
192
|
desired_repo.name,
|
|
195
193
|
])
|
|
196
194
|
if not dry_run:
|
|
197
|
-
|
|
195
|
+
org_data = quay_api_store[desired_repo.org_key]
|
|
196
|
+
api = org_data["api"]
|
|
198
197
|
if desired_repo.public:
|
|
199
198
|
api.repo_make_public(desired_repo.name)
|
|
200
199
|
else:
|
|
@@ -223,32 +222,31 @@ def act(
|
|
|
223
222
|
|
|
224
223
|
|
|
225
224
|
def run(dry_run: bool) -> None:
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
sys.exit(ExitCodes.ERROR)
|
|
225
|
+
with QuayApiStore() as quay_api_store:
|
|
226
|
+
# consistency checks
|
|
227
|
+
for org_key, org_info in quay_api_store.items():
|
|
228
|
+
if org_info.get("mirror"):
|
|
229
|
+
# ensure there are no circular mirror dependencies
|
|
230
|
+
mirror_org_key = org_info["mirror"]
|
|
231
|
+
assert mirror_org_key is not None
|
|
232
|
+
mirror_org = quay_api_store[mirror_org_key]
|
|
233
|
+
if mirror_org.get("mirror"):
|
|
234
|
+
logging.error(
|
|
235
|
+
f"{mirror_org_key.instance}/"
|
|
236
|
+
+ f"{mirror_org_key.org_name} "
|
|
237
|
+
+ "can't have mirrors and be a mirror"
|
|
238
|
+
)
|
|
239
|
+
sys.exit(ExitCodes.ERROR)
|
|
242
240
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
241
|
+
# ensure no org defines `managedRepos` and `mirror` at the same
|
|
242
|
+
if org_info.get("managedRepos"):
|
|
243
|
+
logging.error(
|
|
244
|
+
f"{org_key.instance}/{org_key.org_name} "
|
|
245
|
+
+ "has defined mirror and managedRepos"
|
|
246
|
+
)
|
|
247
|
+
sys.exit(ExitCodes.ERROR)
|
|
250
248
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
249
|
+
# run integration
|
|
250
|
+
current_state = fetch_current_state(quay_api_store)
|
|
251
|
+
desired_state = fetch_desired_state(quay_api_store)
|
|
252
|
+
act(dry_run, quay_api_store, current_state, desired_state)
|