qontract-reconcile 0.10.2.dev310__py3-none-any.whl → 0.10.2.dev439__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of qontract-reconcile might be problematic. Click here for more details.
- {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/METADATA +13 -12
- {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/RECORD +396 -391
- reconcile/acs_rbac.py +2 -2
- reconcile/aus/advanced_upgrade_service.py +18 -12
- reconcile/aus/base.py +134 -32
- reconcile/aus/cluster_version_data.py +15 -5
- reconcile/aus/models.py +3 -1
- reconcile/aus/ocm_addons_upgrade_scheduler_org.py +1 -0
- reconcile/aus/ocm_upgrade_scheduler.py +8 -1
- reconcile/aus/ocm_upgrade_scheduler_org.py +20 -5
- reconcile/aus/version_gates/sts_version_gate_handler.py +54 -1
- reconcile/automated_actions/config/integration.py +16 -4
- reconcile/aws_account_manager/integration.py +8 -8
- reconcile/aws_account_manager/reconciler.py +3 -3
- reconcile/aws_ami_cleanup/integration.py +8 -12
- reconcile/aws_ami_share.py +69 -62
- reconcile/aws_cloudwatch_log_retention/integration.py +155 -126
- reconcile/aws_ecr_image_pull_secrets.py +5 -5
- reconcile/aws_iam_keys.py +1 -0
- reconcile/aws_saml_idp/integration.py +12 -4
- reconcile/aws_saml_roles/integration.py +32 -25
- reconcile/aws_version_sync/integration.py +125 -84
- reconcile/change_owners/bundle.py +3 -3
- reconcile/change_owners/change_log_tracking.py +3 -2
- reconcile/change_owners/change_owners.py +1 -1
- reconcile/change_owners/diff.py +2 -4
- reconcile/checkpoint.py +12 -4
- reconcile/cli.py +111 -18
- reconcile/cluster_deployment_mapper.py +2 -3
- reconcile/dashdotdb_dora.py +5 -12
- reconcile/dashdotdb_slo.py +1 -1
- reconcile/database_access_manager.py +125 -121
- reconcile/deadmanssnitch.py +1 -5
- reconcile/dynatrace_token_provider/integration.py +1 -1
- reconcile/endpoints_discovery/integration.py +4 -1
- reconcile/endpoints_discovery/merge_request.py +1 -1
- reconcile/endpoints_discovery/merge_request_manager.py +9 -11
- reconcile/external_resources/factories.py +5 -12
- reconcile/external_resources/integration.py +1 -1
- reconcile/external_resources/manager.py +8 -5
- reconcile/external_resources/meta.py +0 -1
- reconcile/external_resources/metrics.py +1 -1
- reconcile/external_resources/model.py +20 -20
- reconcile/external_resources/reconciler.py +7 -4
- reconcile/external_resources/secrets_sync.py +10 -14
- reconcile/external_resources/state.py +26 -16
- reconcile/fleet_labeler/integration.py +1 -1
- reconcile/gabi_authorized_users.py +8 -5
- reconcile/gcp_image_mirror.py +2 -2
- reconcile/github_org.py +1 -1
- reconcile/github_owners.py +4 -0
- reconcile/gitlab_housekeeping.py +13 -15
- reconcile/gitlab_members.py +6 -12
- reconcile/gitlab_mr_sqs_consumer.py +2 -2
- reconcile/gitlab_owners.py +15 -11
- reconcile/gitlab_permissions.py +8 -12
- reconcile/glitchtip_project_alerts/integration.py +3 -1
- reconcile/gql_definitions/acs/acs_instances.py +10 -10
- reconcile/gql_definitions/acs/acs_policies.py +5 -5
- reconcile/gql_definitions/acs/acs_rbac.py +6 -6
- reconcile/gql_definitions/advanced_upgrade_service/aus_clusters.py +32 -32
- reconcile/gql_definitions/advanced_upgrade_service/aus_organization.py +26 -26
- reconcile/gql_definitions/app_interface_metrics_exporter/onboarding_status.py +6 -7
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/roles.py +5 -5
- reconcile/gql_definitions/app_sre_tekton_access_revalidation/users.py +5 -5
- reconcile/gql_definitions/automated_actions/instance.py +51 -12
- reconcile/gql_definitions/aws_account_manager/aws_accounts.py +11 -11
- reconcile/gql_definitions/aws_ami_cleanup/aws_accounts.py +20 -10
- reconcile/gql_definitions/aws_cloudwatch_log_retention/aws_accounts.py +28 -68
- reconcile/gql_definitions/aws_saml_idp/aws_accounts.py +20 -10
- reconcile/gql_definitions/aws_saml_roles/aws_accounts.py +20 -10
- reconcile/gql_definitions/aws_saml_roles/roles.py +5 -5
- reconcile/gql_definitions/aws_version_sync/clusters.py +10 -10
- reconcile/gql_definitions/aws_version_sync/namespaces.py +5 -5
- reconcile/gql_definitions/change_owners/queries/change_types.py +5 -5
- reconcile/gql_definitions/change_owners/queries/self_service_roles.py +9 -9
- reconcile/gql_definitions/cluster_auth_rhidp/clusters.py +18 -18
- reconcile/gql_definitions/common/alerting_services_settings.py +9 -9
- reconcile/gql_definitions/common/app_code_component_repos.py +5 -5
- reconcile/gql_definitions/common/app_interface_custom_messages.py +5 -5
- reconcile/gql_definitions/common/app_interface_dms_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_repo_settings.py +5 -5
- reconcile/gql_definitions/common/app_interface_roles.py +120 -0
- reconcile/gql_definitions/common/app_interface_state_settings.py +10 -10
- reconcile/gql_definitions/common/app_interface_vault_settings.py +5 -5
- reconcile/gql_definitions/common/app_quay_repos_escalation_policies.py +5 -5
- reconcile/gql_definitions/common/apps.py +5 -5
- reconcile/gql_definitions/common/aws_vpc_requests.py +22 -9
- reconcile/gql_definitions/common/aws_vpcs.py +11 -11
- reconcile/gql_definitions/common/clusters.py +37 -35
- reconcile/gql_definitions/common/clusters_minimal.py +14 -14
- reconcile/gql_definitions/common/clusters_with_dms.py +6 -6
- reconcile/gql_definitions/common/clusters_with_peering.py +29 -30
- reconcile/gql_definitions/common/github_orgs.py +10 -10
- reconcile/gql_definitions/common/jira_settings.py +10 -10
- reconcile/gql_definitions/common/jiralert_settings.py +5 -5
- reconcile/gql_definitions/common/ldap_settings.py +5 -5
- reconcile/gql_definitions/common/namespaces.py +42 -44
- reconcile/gql_definitions/common/namespaces_minimal.py +15 -13
- reconcile/gql_definitions/common/ocm_env_telemeter.py +12 -12
- reconcile/gql_definitions/common/ocm_environments.py +19 -19
- reconcile/gql_definitions/common/pagerduty_instances.py +9 -9
- reconcile/gql_definitions/common/pgp_reencryption_settings.py +6 -6
- reconcile/gql_definitions/common/pipeline_providers.py +29 -29
- reconcile/gql_definitions/common/quay_instances.py +5 -5
- reconcile/gql_definitions/common/quay_orgs.py +5 -5
- reconcile/gql_definitions/common/reserved_networks.py +5 -5
- reconcile/gql_definitions/common/rhcs_provider_settings.py +5 -5
- reconcile/gql_definitions/common/saas_files.py +44 -44
- reconcile/gql_definitions/common/saas_target_namespaces.py +10 -10
- reconcile/gql_definitions/common/saasherder_settings.py +5 -5
- reconcile/gql_definitions/common/slack_workspaces.py +5 -5
- reconcile/gql_definitions/common/smtp_client_settings.py +19 -19
- reconcile/gql_definitions/common/state_aws_account.py +7 -8
- reconcile/gql_definitions/common/users.py +5 -5
- reconcile/gql_definitions/common/users_with_paths.py +5 -5
- reconcile/gql_definitions/cost_report/app_names.py +5 -5
- reconcile/gql_definitions/cost_report/cost_namespaces.py +5 -5
- reconcile/gql_definitions/cost_report/settings.py +9 -9
- reconcile/gql_definitions/dashdotdb_slo/slo_documents_query.py +43 -43
- reconcile/gql_definitions/dynatrace_token_provider/dynatrace_bootstrap_tokens.py +10 -10
- reconcile/gql_definitions/dynatrace_token_provider/token_specs.py +5 -5
- reconcile/gql_definitions/email_sender/apps.py +5 -5
- reconcile/gql_definitions/email_sender/emails.py +8 -8
- reconcile/gql_definitions/email_sender/users.py +6 -6
- reconcile/gql_definitions/endpoints_discovery/apps.py +10 -10
- reconcile/gql_definitions/external_resources/aws_accounts.py +9 -9
- reconcile/gql_definitions/external_resources/external_resources_modules.py +23 -23
- reconcile/gql_definitions/external_resources/external_resources_namespaces.py +494 -410
- reconcile/gql_definitions/external_resources/external_resources_settings.py +28 -26
- reconcile/gql_definitions/external_resources/fragments/external_resources_module_overrides.py +5 -5
- reconcile/gql_definitions/fleet_labeler/fleet_labels.py +40 -40
- reconcile/gql_definitions/fragments/aus_organization.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_common.py +7 -5
- reconcile/gql_definitions/fragments/aws_account_managed.py +5 -5
- reconcile/gql_definitions/fragments/aws_account_sso.py +5 -5
- reconcile/gql_definitions/fragments/aws_infra_management_account.py +5 -5
- reconcile/gql_definitions/fragments/{aws_vpc_request_subnet.py → aws_organization.py} +12 -8
- reconcile/gql_definitions/fragments/aws_vpc.py +5 -5
- reconcile/gql_definitions/fragments/aws_vpc_request.py +12 -5
- reconcile/gql_definitions/fragments/container_image_mirror.py +5 -5
- reconcile/gql_definitions/fragments/deploy_resources.py +5 -5
- reconcile/gql_definitions/fragments/disable.py +5 -5
- reconcile/gql_definitions/fragments/email_service.py +5 -5
- reconcile/gql_definitions/fragments/email_user.py +5 -5
- reconcile/gql_definitions/fragments/jumphost_common_fields.py +5 -5
- reconcile/gql_definitions/fragments/membership_source.py +5 -5
- reconcile/gql_definitions/fragments/minimal_ocm_organization.py +5 -5
- reconcile/gql_definitions/fragments/oc_connection_cluster.py +5 -5
- reconcile/gql_definitions/fragments/ocm_environment.py +5 -5
- reconcile/gql_definitions/fragments/pipeline_provider_retention.py +5 -5
- reconcile/gql_definitions/fragments/prometheus_instance.py +5 -5
- reconcile/gql_definitions/fragments/resource_limits_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_requests_requirements.py +5 -5
- reconcile/gql_definitions/fragments/resource_values.py +5 -5
- reconcile/gql_definitions/fragments/saas_slo_document.py +5 -5
- reconcile/gql_definitions/fragments/saas_target_namespace.py +5 -5
- reconcile/gql_definitions/fragments/serviceaccount_token.py +5 -5
- reconcile/gql_definitions/fragments/terraform_state.py +5 -5
- reconcile/gql_definitions/fragments/upgrade_policy.py +5 -5
- reconcile/gql_definitions/fragments/user.py +5 -5
- reconcile/gql_definitions/fragments/vault_secret.py +5 -5
- reconcile/gql_definitions/gcp/gcp_docker_repos.py +9 -9
- reconcile/gql_definitions/gcp/gcp_projects.py +9 -9
- reconcile/gql_definitions/gitlab_members/gitlab_instances.py +9 -9
- reconcile/gql_definitions/gitlab_members/permissions.py +9 -9
- reconcile/gql_definitions/glitchtip/glitchtip_instance.py +9 -9
- reconcile/gql_definitions/glitchtip/glitchtip_project.py +11 -11
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py +9 -9
- reconcile/gql_definitions/integrations/integrations.py +48 -51
- reconcile/gql_definitions/introspection.json +3510 -1865
- reconcile/gql_definitions/jenkins_configs/jenkins_configs.py +11 -11
- reconcile/gql_definitions/jenkins_configs/jenkins_instances.py +10 -10
- reconcile/gql_definitions/jira/jira_servers.py +5 -5
- reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py +14 -10
- reconcile/gql_definitions/jumphosts/jumphosts.py +13 -13
- reconcile/gql_definitions/ldap_groups/roles.py +5 -5
- reconcile/gql_definitions/ldap_groups/settings.py +9 -9
- reconcile/gql_definitions/maintenance/maintenances.py +5 -5
- reconcile/gql_definitions/membershipsources/roles.py +5 -5
- reconcile/gql_definitions/ocm_labels/clusters.py +18 -19
- reconcile/gql_definitions/ocm_labels/organizations.py +5 -5
- reconcile/gql_definitions/openshift_cluster_bots/clusters.py +22 -22
- reconcile/gql_definitions/openshift_groups/managed_groups.py +5 -5
- reconcile/gql_definitions/openshift_groups/managed_roles.py +6 -6
- reconcile/gql_definitions/openshift_serviceaccount_tokens/tokens.py +10 -10
- reconcile/gql_definitions/quay_membership/quay_membership.py +6 -6
- reconcile/gql_definitions/rhcs/certs.py +33 -87
- reconcile/gql_definitions/rhcs/openshift_resource_rhcs_cert.py +43 -0
- reconcile/gql_definitions/rhidp/organizations.py +18 -18
- reconcile/gql_definitions/service_dependencies/jenkins_instance_fragment.py +5 -5
- reconcile/gql_definitions/service_dependencies/service_dependencies.py +8 -8
- reconcile/gql_definitions/sharding/aws_accounts.py +10 -10
- reconcile/gql_definitions/sharding/ocm_organization.py +8 -8
- reconcile/gql_definitions/skupper_network/site_controller_template.py +5 -5
- reconcile/gql_definitions/skupper_network/skupper_networks.py +10 -10
- reconcile/gql_definitions/slack_usergroups/clusters.py +5 -5
- reconcile/gql_definitions/slack_usergroups/permissions.py +9 -9
- reconcile/gql_definitions/slack_usergroups/users.py +5 -5
- reconcile/gql_definitions/slo_documents/slo_documents.py +5 -5
- reconcile/gql_definitions/status_board/status_board.py +6 -7
- reconcile/gql_definitions/statuspage/statuspages.py +9 -9
- reconcile/gql_definitions/templating/template_collection.py +5 -5
- reconcile/gql_definitions/templating/templates.py +5 -5
- reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py +6 -6
- reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py +11 -11
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_accounts.py +11 -11
- reconcile/gql_definitions/terraform_cloudflare_resources/terraform_cloudflare_resources.py +20 -25
- reconcile/gql_definitions/terraform_cloudflare_users/app_interface_setting_cloudflare_and_vault.py +6 -6
- reconcile/gql_definitions/terraform_cloudflare_users/terraform_cloudflare_roles.py +12 -12
- reconcile/gql_definitions/terraform_init/aws_accounts.py +23 -9
- reconcile/gql_definitions/terraform_repo/terraform_repo.py +9 -9
- reconcile/gql_definitions/terraform_resources/database_access_manager.py +5 -5
- reconcile/gql_definitions/terraform_resources/terraform_resources_namespaces.py +450 -402
- reconcile/gql_definitions/terraform_tgw_attachments/aws_accounts.py +23 -17
- reconcile/gql_definitions/unleash_feature_toggles/feature_toggles.py +9 -9
- reconcile/gql_definitions/vault_instances/vault_instances.py +61 -61
- reconcile/gql_definitions/vault_policies/vault_policies.py +11 -11
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator.py +8 -8
- reconcile/gql_definitions/vpc_peerings_validator/vpc_peerings_validator_peered_cluster_fragment.py +5 -5
- reconcile/integrations_manager.py +3 -3
- reconcile/jenkins_job_builder.py +1 -1
- reconcile/jenkins_worker_fleets.py +80 -11
- reconcile/jira_permissions_validator.py +237 -122
- reconcile/ldap_groups/integration.py +1 -1
- reconcile/ocm/types.py +35 -56
- reconcile/ocm_aws_infrastructure_access.py +1 -1
- reconcile/ocm_clusters.py +4 -4
- reconcile/ocm_labels/integration.py +3 -2
- reconcile/ocm_machine_pools.py +33 -27
- reconcile/openshift_base.py +122 -10
- reconcile/openshift_cluster_bots.py +5 -5
- reconcile/openshift_groups.py +5 -0
- reconcile/openshift_limitranges.py +1 -1
- reconcile/openshift_namespace_labels.py +1 -1
- reconcile/openshift_namespaces.py +97 -101
- reconcile/openshift_resources_base.py +10 -5
- reconcile/openshift_rhcs_certs.py +77 -40
- reconcile/openshift_rolebindings.py +230 -130
- reconcile/openshift_saas_deploy.py +6 -7
- reconcile/openshift_saas_deploy_change_tester.py +9 -7
- reconcile/openshift_saas_deploy_trigger_cleaner.py +3 -5
- reconcile/openshift_serviceaccount_tokens.py +8 -7
- reconcile/openshift_tekton_resources.py +1 -1
- reconcile/openshift_upgrade_watcher.py +4 -4
- reconcile/openshift_users.py +5 -3
- reconcile/oum/labelset.py +5 -3
- reconcile/oum/models.py +1 -4
- reconcile/oum/providers.py +1 -1
- reconcile/prometheus_rules_tester/integration.py +4 -4
- reconcile/quay_mirror.py +1 -1
- reconcile/queries.py +131 -0
- reconcile/requests_sender.py +8 -3
- reconcile/resource_scraper.py +1 -5
- reconcile/rhidp/common.py +3 -5
- reconcile/rhidp/sso_client/base.py +19 -10
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -1
- reconcile/saas_auto_promotions_manager/subscriber.py +4 -3
- reconcile/sendgrid_teammates.py +20 -9
- reconcile/skupper_network/integration.py +2 -2
- reconcile/slack_usergroups.py +35 -14
- reconcile/sql_query.py +1 -0
- reconcile/status.py +2 -2
- reconcile/status_board.py +6 -6
- reconcile/statuspage/atlassian.py +7 -7
- reconcile/statuspage/integrations/maintenances.py +4 -3
- reconcile/statuspage/page.py +4 -9
- reconcile/statuspage/status.py +5 -8
- reconcile/templates/rosa-classic-cluster-creation.sh.j2 +5 -1
- reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +4 -1
- reconcile/templating/lib/merge_request_manager.py +2 -2
- reconcile/templating/lib/rendering.py +3 -3
- reconcile/templating/renderer.py +12 -13
- reconcile/terraform_aws_route53.py +18 -8
- reconcile/terraform_cloudflare_dns.py +3 -3
- reconcile/terraform_cloudflare_resources.py +12 -13
- reconcile/terraform_cloudflare_users.py +3 -2
- reconcile/terraform_init/integration.py +187 -23
- reconcile/terraform_repo.py +16 -12
- reconcile/terraform_resources.py +18 -10
- reconcile/terraform_tgw_attachments.py +28 -20
- reconcile/terraform_users.py +27 -22
- reconcile/terraform_vpc_peerings.py +15 -3
- reconcile/terraform_vpc_resources/integration.py +23 -8
- reconcile/typed_queries/app_interface_roles.py +10 -0
- reconcile/typed_queries/aws_account_tags.py +41 -0
- reconcile/typed_queries/cost_report/app_names.py +1 -1
- reconcile/typed_queries/cost_report/cost_namespaces.py +2 -2
- reconcile/typed_queries/saas_files.py +13 -13
- reconcile/typed_queries/status_board.py +2 -2
- reconcile/unleash_feature_toggles/integration.py +4 -2
- reconcile/utils/acs/base.py +6 -3
- reconcile/utils/acs/policies.py +2 -2
- reconcile/utils/aggregated_list.py +4 -3
- reconcile/utils/aws_api.py +51 -20
- reconcile/utils/aws_api_typed/api.py +38 -9
- reconcile/utils/aws_api_typed/cloudformation.py +149 -0
- reconcile/utils/aws_api_typed/logs.py +73 -0
- reconcile/utils/aws_api_typed/organization.py +4 -2
- reconcile/utils/binary.py +7 -12
- reconcile/utils/datetime_util.py +67 -0
- reconcile/utils/deadmanssnitch_api.py +1 -1
- reconcile/utils/differ.py +2 -3
- reconcile/utils/early_exit_cache.py +11 -12
- reconcile/utils/expiration.py +7 -3
- reconcile/utils/external_resource_spec.py +24 -1
- reconcile/utils/filtering.py +1 -1
- reconcile/utils/gitlab_api.py +7 -5
- reconcile/utils/glitchtip/client.py +6 -2
- reconcile/utils/glitchtip/models.py +25 -28
- reconcile/utils/gpg.py +5 -3
- reconcile/utils/gql.py +4 -7
- reconcile/utils/helm.py +2 -1
- reconcile/utils/helpers.py +1 -1
- reconcile/utils/imap_client.py +1 -1
- reconcile/utils/instrumented_wrappers.py +1 -1
- reconcile/utils/internal_groups/client.py +2 -2
- reconcile/utils/internal_groups/models.py +8 -17
- reconcile/utils/jenkins_api.py +24 -1
- reconcile/utils/jinja2/utils.py +6 -8
- reconcile/utils/jira_client.py +82 -63
- reconcile/utils/jjb_client.py +78 -46
- reconcile/utils/jobcontroller/controller.py +2 -2
- reconcile/utils/jobcontroller/models.py +17 -1
- reconcile/utils/json.py +74 -0
- reconcile/utils/ldap_client.py +4 -3
- reconcile/utils/lean_terraform_client.py +3 -1
- reconcile/utils/membershipsources/app_interface_resolver.py +4 -2
- reconcile/utils/membershipsources/models.py +16 -23
- reconcile/utils/membershipsources/resolver.py +4 -2
- reconcile/utils/merge_request_manager/merge_request_manager.py +4 -4
- reconcile/utils/merge_request_manager/parser.py +6 -6
- reconcile/utils/metrics.py +5 -5
- reconcile/utils/models.py +304 -82
- reconcile/utils/mr/__init__.py +3 -1
- reconcile/utils/mr/app_interface_reporter.py +6 -3
- reconcile/utils/mr/aws_access.py +1 -1
- reconcile/utils/mr/base.py +7 -13
- reconcile/utils/mr/clusters_updates.py +4 -2
- reconcile/utils/mr/notificator.py +3 -3
- reconcile/utils/mr/ocm_upgrade_scheduler_org_updates.py +4 -1
- reconcile/utils/mr/promote_qontract.py +28 -12
- reconcile/utils/mr/update_access_report_base.py +3 -4
- reconcile/utils/mr/user_maintenance.py +7 -6
- reconcile/utils/oc.py +445 -336
- reconcile/utils/oc_filters.py +3 -3
- reconcile/utils/ocm/addons.py +0 -1
- reconcile/utils/ocm/base.py +18 -21
- reconcile/utils/ocm/cluster_groups.py +1 -1
- reconcile/utils/ocm/identity_providers.py +2 -2
- reconcile/utils/ocm/labels.py +1 -1
- reconcile/utils/ocm/ocm.py +81 -71
- reconcile/utils/ocm/products.py +9 -3
- reconcile/utils/ocm/search_filters.py +3 -6
- reconcile/utils/ocm/service_log.py +4 -6
- reconcile/utils/ocm/sre_capability_labels.py +20 -13
- reconcile/utils/ocm_base_client.py +4 -4
- reconcile/utils/openshift_resource.py +83 -52
- reconcile/utils/openssl.py +2 -2
- reconcile/utils/output.py +3 -2
- reconcile/utils/pagerduty_api.py +10 -7
- reconcile/utils/promotion_state.py +6 -11
- reconcile/utils/raw_github_api.py +11 -8
- reconcile/utils/repo_owners.py +21 -29
- reconcile/utils/rhcsv2_certs.py +138 -35
- reconcile/utils/rosa/session.py +16 -0
- reconcile/utils/runtime/integration.py +2 -3
- reconcile/utils/runtime/meta.py +2 -1
- reconcile/utils/runtime/runner.py +2 -2
- reconcile/utils/saasherder/interfaces.py +13 -20
- reconcile/utils/saasherder/models.py +25 -21
- reconcile/utils/saasherder/saasherder.py +60 -32
- reconcile/utils/secret_reader.py +6 -6
- reconcile/utils/sharding.py +1 -1
- reconcile/utils/slack_api.py +26 -4
- reconcile/utils/sloth.py +224 -0
- reconcile/utils/sqs_gateway.py +16 -11
- reconcile/utils/state.py +2 -1
- reconcile/utils/structs.py +1 -1
- reconcile/utils/terraform_client.py +29 -26
- reconcile/utils/terrascript_aws_client.py +200 -116
- reconcile/utils/three_way_diff_strategy.py +1 -1
- reconcile/utils/unleash/server.py +2 -8
- reconcile/utils/vault.py +44 -41
- reconcile/utils/vcs.py +8 -8
- reconcile/vault_replication.py +119 -58
- tools/app_interface_reporter.py +4 -4
- tools/cli_commands/cost_report/cost_management_api.py +3 -3
- tools/cli_commands/cost_report/view.py +7 -6
- tools/cli_commands/erv2.py +1 -1
- tools/cli_commands/gpg_encrypt.py +4 -1
- tools/cli_commands/systems_and_tools.py +5 -1
- tools/qontract_cli.py +36 -21
- tools/template_validation.py +3 -1
- reconcile/gql_definitions/ocm_oidc_idp/__init__.py +0 -0
- reconcile/gql_definitions/ocm_subscription_labels/__init__.py +0 -0
- reconcile/jenkins/__init__.py +0 -0
- reconcile/jenkins/types.py +0 -77
- {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev310.dist-info → qontract_reconcile-0.10.2.dev439.dist-info}/entry_points.txt +0 -0
|
@@ -32,6 +32,7 @@ from reconcile.typed_queries.app_interface_vault_settings import (
|
|
|
32
32
|
get_app_interface_vault_settings,
|
|
33
33
|
)
|
|
34
34
|
from reconcile.typed_queries.clusters_with_peering import get_clusters_with_peering
|
|
35
|
+
from reconcile.typed_queries.external_resources import get_settings
|
|
35
36
|
from reconcile.typed_queries.terraform_tgw_attachments.aws_accounts import (
|
|
36
37
|
get_aws_accounts,
|
|
37
38
|
)
|
|
@@ -68,7 +69,7 @@ class ValidationError(Exception):
|
|
|
68
69
|
class TGWAccountProviderInfo(BaseModel):
|
|
69
70
|
name: str
|
|
70
71
|
uid: str
|
|
71
|
-
assume_role: str | None
|
|
72
|
+
assume_role: str | None = None
|
|
72
73
|
assume_region: str
|
|
73
74
|
|
|
74
75
|
|
|
@@ -80,10 +81,10 @@ class Requester(BaseModel):
|
|
|
80
81
|
tgw_id: str
|
|
81
82
|
tgw_arn: str
|
|
82
83
|
region: str
|
|
83
|
-
routes: list[dict] | None
|
|
84
|
-
rules: list[dict] | None
|
|
85
|
-
hostedzones: list[str] | None
|
|
86
|
-
cidr_block: str | None
|
|
84
|
+
routes: list[dict] | None = None
|
|
85
|
+
rules: list[dict] | None = None
|
|
86
|
+
hostedzones: list[str] | None = None
|
|
87
|
+
cidr_block: str | None = None
|
|
87
88
|
cidr_blocks: list[str]
|
|
88
89
|
account: TGWAccountProviderInfo
|
|
89
90
|
|
|
@@ -91,11 +92,11 @@ class Requester(BaseModel):
|
|
|
91
92
|
class Accepter(BaseModel):
|
|
92
93
|
cidr_block: str
|
|
93
94
|
region: str
|
|
94
|
-
vpc_id: str | None
|
|
95
|
-
route_table_ids: list[str] | None
|
|
96
|
-
subnets_id_az: list[dict[str, str]] | None
|
|
95
|
+
vpc_id: str | None = None
|
|
96
|
+
route_table_ids: list[str] | None = None
|
|
97
|
+
subnets_id_az: list[dict[str, str]] | None = None
|
|
97
98
|
account: ClusterAccountProviderInfo
|
|
98
|
-
api_security_group_id: str | None
|
|
99
|
+
api_security_group_id: str | None = None
|
|
99
100
|
|
|
100
101
|
|
|
101
102
|
class DesiredStateItem(BaseModel):
|
|
@@ -192,7 +193,7 @@ def _build_desired_state_tgw_connection(
|
|
|
192
193
|
yield None
|
|
193
194
|
|
|
194
195
|
account_tgws = awsapi.get_tgws_details(
|
|
195
|
-
peer_connection.account.
|
|
196
|
+
peer_connection.account.model_dump(by_alias=True),
|
|
196
197
|
cluster_region,
|
|
197
198
|
cluster_cidr_block,
|
|
198
199
|
tags=peer_connection.tags or {},
|
|
@@ -274,7 +275,7 @@ def _build_accepter(
|
|
|
274
275
|
)
|
|
275
276
|
(vpc_id, route_table_ids, subnets_id_az, api_security_group_id) = (
|
|
276
277
|
awsapi.get_cluster_vpc_details(
|
|
277
|
-
account.
|
|
278
|
+
account.model_dump(by_alias=True),
|
|
278
279
|
route_tables=bool(peer_connection.manage_routes),
|
|
279
280
|
subnets=True,
|
|
280
281
|
hcp_vpc_endpoint_sg=allow_hcp_private_api_access,
|
|
@@ -317,12 +318,12 @@ def _build_ocm_map(
|
|
|
317
318
|
clusters: Iterable[ClusterV1],
|
|
318
319
|
vault_settings: AppInterfaceSettingsV1,
|
|
319
320
|
) -> OCMMap | None:
|
|
320
|
-
ocm_clusters = [c.
|
|
321
|
+
ocm_clusters = [c.model_dump(by_alias=True) for c in clusters if c.ocm]
|
|
321
322
|
return (
|
|
322
323
|
OCMMap(
|
|
323
324
|
clusters=ocm_clusters,
|
|
324
325
|
integration=QONTRACT_INTEGRATION,
|
|
325
|
-
settings=vault_settings.
|
|
326
|
+
settings=vault_settings.model_dump(by_alias=True),
|
|
326
327
|
)
|
|
327
328
|
if ocm_clusters
|
|
328
329
|
# this is a case for an OCP cluster which is not provisioned
|
|
@@ -342,11 +343,11 @@ def _populate_tgw_attachments_working_dirs(
|
|
|
342
343
|
ts: Terrascript,
|
|
343
344
|
desired_state: Iterable[DesiredStateItem],
|
|
344
345
|
print_to_file: str | None,
|
|
345
|
-
) ->
|
|
346
|
+
) -> dict[str, str]:
|
|
346
347
|
accounts_by_infra_account_name: dict[str, list[dict[str, Any]]] = {}
|
|
347
348
|
for item in desired_state:
|
|
348
349
|
accounts_by_infra_account_name.setdefault(item.infra_acount_name, []).append(
|
|
349
|
-
item.accepter.account.
|
|
350
|
+
item.accepter.account.model_dump(by_alias=True)
|
|
350
351
|
)
|
|
351
352
|
for infra_account_name, accounts in accounts_by_infra_account_name.items():
|
|
352
353
|
ts.populate_additional_providers(infra_account_name, accounts)
|
|
@@ -428,7 +429,9 @@ def setup(
|
|
|
428
429
|
print_to_file: str | None = None,
|
|
429
430
|
) -> tuple[SecretReaderBase, AWSApi, Terraform, Terrascript]:
|
|
430
431
|
tgw_clusters = desired_state_data_source.clusters
|
|
431
|
-
all_accounts = [
|
|
432
|
+
all_accounts = [
|
|
433
|
+
a.model_dump(by_alias=True) for a in desired_state_data_source.accounts
|
|
434
|
+
]
|
|
432
435
|
account_by_name = {a["name"]: a for a in all_accounts}
|
|
433
436
|
vault_settings = get_app_interface_vault_settings()
|
|
434
437
|
secret_reader = create_secret_reader(vault_settings.vault)
|
|
@@ -444,13 +447,18 @@ def setup(
|
|
|
444
447
|
raise RuntimeError("Could not find VPC ID for cluster")
|
|
445
448
|
|
|
446
449
|
_validate_tgw_connection_names(desired_state)
|
|
447
|
-
|
|
450
|
+
try:
|
|
451
|
+
default_tags = get_settings().default_tags
|
|
452
|
+
except ValueError:
|
|
453
|
+
# no external resources settings found
|
|
454
|
+
default_tags = None
|
|
448
455
|
ts = Terrascript(
|
|
449
456
|
QONTRACT_INTEGRATION,
|
|
450
457
|
"",
|
|
451
458
|
thread_pool_size,
|
|
452
459
|
tgw_accounts,
|
|
453
|
-
settings=vault_settings.
|
|
460
|
+
settings=vault_settings.model_dump(by_alias=True),
|
|
461
|
+
default_tags=default_tags,
|
|
454
462
|
)
|
|
455
463
|
tgw_rosa_cluster_accounts = [
|
|
456
464
|
account_by_name[c.spec.account.name]
|
|
@@ -510,7 +518,7 @@ def run(
|
|
|
510
518
|
) -> None:
|
|
511
519
|
desired_state_data_source = _fetch_desired_state_data_source(account_name)
|
|
512
520
|
tgw_accounts = [
|
|
513
|
-
a.
|
|
521
|
+
a.model_dump(by_alias=True)
|
|
514
522
|
for a in _filter_tgw_accounts(
|
|
515
523
|
desired_state_data_source.accounts, desired_state_data_source.clusters
|
|
516
524
|
)
|
|
@@ -567,7 +575,7 @@ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
|
|
|
567
575
|
desired_state = _fetch_desired_state_data_source()
|
|
568
576
|
for a in desired_state.accounts:
|
|
569
577
|
a.deletion_approvals = []
|
|
570
|
-
return desired_state.
|
|
578
|
+
return desired_state.model_dump(by_alias=True)
|
|
571
579
|
|
|
572
580
|
|
|
573
581
|
def desired_state_shard_config() -> DesiredStateShardConfig:
|
reconcile/terraform_users.py
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import sys
|
|
2
|
-
from collections.abc import Mapping
|
|
2
|
+
from collections.abc import Iterable, Mapping
|
|
3
3
|
from textwrap import indent
|
|
4
4
|
from typing import (
|
|
5
5
|
Any,
|
|
6
|
-
cast,
|
|
7
6
|
)
|
|
8
7
|
|
|
9
8
|
from reconcile import (
|
|
@@ -12,6 +11,7 @@ from reconcile import (
|
|
|
12
11
|
)
|
|
13
12
|
from reconcile.change_owners.diff import IDENTIFIER_FIELD_NAME
|
|
14
13
|
from reconcile.gql_definitions.common.pgp_reencryption_settings import query
|
|
14
|
+
from reconcile.typed_queries.external_resources import get_settings
|
|
15
15
|
from reconcile.utils import (
|
|
16
16
|
expiration,
|
|
17
17
|
gql,
|
|
@@ -31,7 +31,6 @@ from reconcile.utils.terraform_client import TerraformClient as Terraform
|
|
|
31
31
|
from reconcile.utils.terrascript_aws_client import TerrascriptClient as Terrascript
|
|
32
32
|
from reconcile.utils.vault import (
|
|
33
33
|
VaultClient,
|
|
34
|
-
_VaultClient,
|
|
35
34
|
)
|
|
36
35
|
|
|
37
36
|
TF_POLICY = """
|
|
@@ -96,9 +95,9 @@ def get_tf_roles() -> list[Role]:
|
|
|
96
95
|
|
|
97
96
|
|
|
98
97
|
def _filter_participating_aws_accounts(
|
|
99
|
-
accounts:
|
|
100
|
-
roles:
|
|
101
|
-
) -> list:
|
|
98
|
+
accounts: Iterable[dict[str, Any]],
|
|
99
|
+
roles: Iterable[Mapping[str, Any]],
|
|
100
|
+
) -> list[dict[str, Any]]:
|
|
102
101
|
participating_aws_account_names: set[str] = set()
|
|
103
102
|
for role in roles:
|
|
104
103
|
participating_aws_account_names.update(
|
|
@@ -112,12 +111,12 @@ def _filter_participating_aws_accounts(
|
|
|
112
111
|
|
|
113
112
|
|
|
114
113
|
def setup(
|
|
115
|
-
print_to_file,
|
|
114
|
+
print_to_file: str | None,
|
|
116
115
|
thread_pool_size: int,
|
|
117
116
|
skip_reencrypt_accounts: list[str],
|
|
118
117
|
appsre_pgp_key: str | None = None,
|
|
119
118
|
account_name: str | None = None,
|
|
120
|
-
) -> tuple[list[dict[str, Any]],
|
|
119
|
+
) -> tuple[list[dict[str, Any]], dict[str, str], bool, AWSApi]:
|
|
121
120
|
accounts = [
|
|
122
121
|
a
|
|
123
122
|
for a in queries.get_aws_accounts(terraform_state=True)
|
|
@@ -128,12 +127,18 @@ def setup(
|
|
|
128
127
|
participating_aws_accounts = _filter_participating_aws_accounts(accounts, roles)
|
|
129
128
|
|
|
130
129
|
settings = queries.get_app_interface_settings()
|
|
130
|
+
try:
|
|
131
|
+
default_tags = get_settings().default_tags
|
|
132
|
+
except ValueError:
|
|
133
|
+
# no external resources settings found
|
|
134
|
+
default_tags = None
|
|
131
135
|
ts = Terrascript(
|
|
132
136
|
QONTRACT_INTEGRATION,
|
|
133
137
|
QONTRACT_TF_PREFIX,
|
|
134
138
|
thread_pool_size,
|
|
135
139
|
participating_aws_accounts,
|
|
136
140
|
settings=settings,
|
|
141
|
+
default_tags=default_tags,
|
|
137
142
|
)
|
|
138
143
|
err = ts.populate_users(
|
|
139
144
|
roles,
|
|
@@ -147,10 +152,10 @@ def setup(
|
|
|
147
152
|
|
|
148
153
|
|
|
149
154
|
def send_email_invites(
|
|
150
|
-
new_users,
|
|
155
|
+
new_users: Iterable[tuple[str, str, str, str]],
|
|
151
156
|
smtp_client: SmtpClient,
|
|
152
|
-
skip_reencrypt_accounts:
|
|
153
|
-
):
|
|
157
|
+
skip_reencrypt_accounts: Iterable[str],
|
|
158
|
+
) -> None:
|
|
154
159
|
msg_template = """
|
|
155
160
|
You have been invited to join the {} AWS account!
|
|
156
161
|
Below you will find credentials for the first sign in.
|
|
@@ -188,11 +193,11 @@ Encrypted password: {}
|
|
|
188
193
|
|
|
189
194
|
|
|
190
195
|
def write_user_to_vault(
|
|
191
|
-
vault_client:
|
|
196
|
+
vault_client: VaultClient,
|
|
192
197
|
vault_path: str,
|
|
193
|
-
new_users:
|
|
194
|
-
skip_reencrypt_accounts:
|
|
195
|
-
):
|
|
198
|
+
new_users: Iterable[tuple[str, str, str, str]],
|
|
199
|
+
skip_reencrypt_accounts: Iterable[str],
|
|
200
|
+
) -> None:
|
|
196
201
|
for account, console_url, user_name, enc_password in new_users:
|
|
197
202
|
if account in skip_reencrypt_accounts:
|
|
198
203
|
continue
|
|
@@ -209,13 +214,13 @@ def write_user_to_vault(
|
|
|
209
214
|
vault_client.write(desired_secret, decode_base64=False)
|
|
210
215
|
|
|
211
216
|
|
|
212
|
-
def cleanup_and_exit(tf=None, status=False):
|
|
217
|
+
def cleanup_and_exit(tf: Terraform | None = None, status: bool = False) -> None:
|
|
213
218
|
if tf is not None:
|
|
214
219
|
tf.cleanup()
|
|
215
220
|
sys.exit(status)
|
|
216
221
|
|
|
217
222
|
|
|
218
|
-
def get_reencrypt_settings():
|
|
223
|
+
def get_reencrypt_settings() -> tuple[list[str], str | None, Any]:
|
|
219
224
|
all_reencrypt_settings = query(
|
|
220
225
|
query_func=gql.get_api().query
|
|
221
226
|
).pgp_reencryption_settings
|
|
@@ -244,7 +249,7 @@ def run(
|
|
|
244
249
|
thread_pool_size: int = DEFAULT_THREAD_POOL_SIZE,
|
|
245
250
|
send_mails: bool = True,
|
|
246
251
|
account_name: str | None = None,
|
|
247
|
-
):
|
|
252
|
+
) -> None:
|
|
248
253
|
skip_accounts, appsre_pgp_key, reencrypt_settings = get_reencrypt_settings()
|
|
249
254
|
|
|
250
255
|
# setup errors should skip resources that will lead
|
|
@@ -298,7 +303,7 @@ def run(
|
|
|
298
303
|
new_users = tf.get_new_users()
|
|
299
304
|
|
|
300
305
|
if reencrypt_settings:
|
|
301
|
-
vc =
|
|
306
|
+
vc = VaultClient.get_instance()
|
|
302
307
|
write_user_to_vault(
|
|
303
308
|
vc, reencrypt_settings.reencrypt_vault_path, new_users, skip_accounts
|
|
304
309
|
)
|
|
@@ -320,7 +325,7 @@ def run(
|
|
|
320
325
|
cleanup_and_exit(tf, setup_err)
|
|
321
326
|
|
|
322
327
|
|
|
323
|
-
def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
|
|
328
|
+
def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
|
|
324
329
|
"""
|
|
325
330
|
Finding diffs in deeply nested structures is time/resource consuming.
|
|
326
331
|
Having a unique known property to identify objects makes it easier to match
|
|
@@ -331,11 +336,11 @@ def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
|
|
|
331
336
|
for the DeepDiff library used in qontract-reconcile.
|
|
332
337
|
"""
|
|
333
338
|
|
|
334
|
-
def add_account_identity(acc):
|
|
339
|
+
def add_account_identity(acc: dict[str, Any]) -> dict[str, Any]:
|
|
335
340
|
acc[IDENTIFIER_FIELD_NAME] = acc["path"]
|
|
336
341
|
return acc
|
|
337
342
|
|
|
338
|
-
def add_role_identity(role):
|
|
343
|
+
def add_role_identity(role: dict[str, Any]) -> dict[str, Any]:
|
|
339
344
|
role[IDENTIFIER_FIELD_NAME] = role["name"]
|
|
340
345
|
return role
|
|
341
346
|
|
|
@@ -7,6 +7,7 @@ from typing import Any, TypedDict
|
|
|
7
7
|
import reconcile.utils.terraform_client as terraform
|
|
8
8
|
import reconcile.utils.terrascript_aws_client as terrascript
|
|
9
9
|
from reconcile import queries
|
|
10
|
+
from reconcile.typed_queries import external_resources
|
|
10
11
|
from reconcile.utils import (
|
|
11
12
|
aws_api,
|
|
12
13
|
ocm,
|
|
@@ -73,6 +74,7 @@ def _build_infrastructure_assume_role(
|
|
|
73
74
|
ocm: OCM | None,
|
|
74
75
|
provided_assume_role: str | None,
|
|
75
76
|
) -> dict[str, Any] | None:
|
|
77
|
+
assume_role: str | None = None
|
|
76
78
|
if provided_assume_role:
|
|
77
79
|
assume_role = provided_assume_role
|
|
78
80
|
elif cluster["spec"].get("account"):
|
|
@@ -653,8 +655,18 @@ def run(
|
|
|
653
655
|
])
|
|
654
656
|
|
|
655
657
|
account_by_name = {a["name"]: a for a in accounts}
|
|
658
|
+
try:
|
|
659
|
+
default_tags = external_resources.get_settings().default_tags
|
|
660
|
+
except ValueError:
|
|
661
|
+
# no external resources settings found
|
|
662
|
+
default_tags = None
|
|
656
663
|
with terrascript.TerrascriptClient(
|
|
657
|
-
QONTRACT_INTEGRATION,
|
|
664
|
+
QONTRACT_INTEGRATION,
|
|
665
|
+
"",
|
|
666
|
+
thread_pool_size,
|
|
667
|
+
infra_accounts,
|
|
668
|
+
settings=settings,
|
|
669
|
+
default_tags=default_tags,
|
|
658
670
|
) as ts:
|
|
659
671
|
rosa_cluster_accounts = [
|
|
660
672
|
account_by_name[c["spec"]["account"]["name"]]
|
|
@@ -663,8 +675,8 @@ def run(
|
|
|
663
675
|
]
|
|
664
676
|
ts.populate_configs(rosa_cluster_accounts)
|
|
665
677
|
|
|
666
|
-
for infra_account_name,
|
|
667
|
-
ts.populate_additional_providers(infra_account_name,
|
|
678
|
+
for infra_account_name, accounts in participating_accounts.items():
|
|
679
|
+
ts.populate_additional_providers(infra_account_name, accounts)
|
|
668
680
|
ts.populate_vpc_peerings(desired_state)
|
|
669
681
|
working_dirs = ts.dump(print_to_file=print_to_file)
|
|
670
682
|
terraform_configurations = ts.terraform_configurations()
|
|
@@ -20,9 +20,11 @@ from reconcile.typed_queries.app_interface_vault_settings import (
|
|
|
20
20
|
get_app_interface_vault_settings,
|
|
21
21
|
)
|
|
22
22
|
from reconcile.typed_queries.aws_vpc_requests import get_aws_vpc_requests
|
|
23
|
+
from reconcile.typed_queries.external_resources import get_settings
|
|
23
24
|
from reconcile.typed_queries.github_orgs import get_github_orgs
|
|
24
25
|
from reconcile.typed_queries.gitlab_instances import get_gitlab_instances
|
|
25
26
|
from reconcile.utils import gql
|
|
27
|
+
from reconcile.utils.disabled_integrations import integration_is_enabled
|
|
26
28
|
from reconcile.utils.runtime.integration import (
|
|
27
29
|
DesiredStateShardConfig,
|
|
28
30
|
PydanticRunParams,
|
|
@@ -61,12 +63,14 @@ class TerraformVpcResources(QontractReconcileIntegration[TerraformVpcResourcesPa
|
|
|
61
63
|
) -> list[AWSAccountV1]:
|
|
62
64
|
"""Return a list of accounts extracted from the provided VPCRequests.
|
|
63
65
|
If account_name is given returns the account object with that name."""
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
return [
|
|
67
|
+
vpc.account
|
|
68
|
+
for vpc in data
|
|
69
|
+
if (
|
|
70
|
+
integration_is_enabled(self.name, vpc.account)
|
|
71
|
+
and (not account_name or vpc.account.name == account_name)
|
|
72
|
+
)
|
|
73
|
+
]
|
|
70
74
|
|
|
71
75
|
def _handle_outputs(
|
|
72
76
|
self, requests: Iterable[VPCRequest], outputs: Mapping[str, Any]
|
|
@@ -93,6 +97,7 @@ class TerraformVpcResources(QontractReconcileIntegration[TerraformVpcResourcesPa
|
|
|
93
97
|
public_subnets = outputs_per_account.get(
|
|
94
98
|
f"{request.identifier}-public_subnets", {}
|
|
95
99
|
).get("value", [])
|
|
100
|
+
availability_zones: list[str] = []
|
|
96
101
|
|
|
97
102
|
if request.subnets:
|
|
98
103
|
private_subnet_tags = VPC_REQUEST_DEFAULT_PRIVATE_SUBNET_TAGS | (
|
|
@@ -101,6 +106,7 @@ class TerraformVpcResources(QontractReconcileIntegration[TerraformVpcResourcesPa
|
|
|
101
106
|
public_subnet_tags = VPC_REQUEST_DEFAULT_PUBLIC_SUBNET_TAGS | (
|
|
102
107
|
request.subnets.public_subnet_tags or {}
|
|
103
108
|
)
|
|
109
|
+
availability_zones = request.subnets.availability_zones or []
|
|
104
110
|
else:
|
|
105
111
|
private_subnet_tags = VPC_REQUEST_DEFAULT_PRIVATE_SUBNET_TAGS
|
|
106
112
|
public_subnet_tags = VPC_REQUEST_DEFAULT_PUBLIC_SUBNET_TAGS
|
|
@@ -116,6 +122,7 @@ class TerraformVpcResources(QontractReconcileIntegration[TerraformVpcResourcesPa
|
|
|
116
122
|
"public": public_subnets,
|
|
117
123
|
"private_subnet_tags": private_subnet_tags,
|
|
118
124
|
"public_subnet_tags": public_subnet_tags,
|
|
125
|
+
"availability_zones": availability_zones,
|
|
119
126
|
},
|
|
120
127
|
"account_name": request.account.name,
|
|
121
128
|
"region": request.region,
|
|
@@ -151,20 +158,28 @@ class TerraformVpcResources(QontractReconcileIntegration[TerraformVpcResourcesPa
|
|
|
151
158
|
if data:
|
|
152
159
|
accounts = self._filter_accounts(data, account_name)
|
|
153
160
|
if account_name and not accounts:
|
|
154
|
-
msg = f"The account {account_name} doesn't have any managed
|
|
161
|
+
msg = f"The account {account_name} doesn't have any managed vpcs or the {QONTRACT_INTEGRATION} integration is disabled for this account. Verify your input"
|
|
155
162
|
logging.debug(msg)
|
|
156
163
|
sys.exit(ExitCodes.SUCCESS)
|
|
157
164
|
else:
|
|
158
165
|
logging.debug("No VPC requests found, nothing to do.")
|
|
159
166
|
sys.exit(ExitCodes.SUCCESS)
|
|
160
167
|
|
|
161
|
-
accounts_untyped: list[dict] = [
|
|
168
|
+
accounts_untyped: list[dict] = [
|
|
169
|
+
acc.model_dump(by_alias=True) for acc in accounts
|
|
170
|
+
]
|
|
171
|
+
try:
|
|
172
|
+
default_tags = get_settings().default_tags
|
|
173
|
+
except ValueError:
|
|
174
|
+
# no external resources settings found
|
|
175
|
+
default_tags = None
|
|
162
176
|
with TerrascriptClient(
|
|
163
177
|
integration=QONTRACT_INTEGRATION,
|
|
164
178
|
integration_prefix=QONTRACT_TF_PREFIX,
|
|
165
179
|
thread_pool_size=thread_pool_size,
|
|
166
180
|
accounts=accounts_untyped,
|
|
167
181
|
secret_reader=secret_reader,
|
|
182
|
+
default_tags=default_tags,
|
|
168
183
|
) as ts_client:
|
|
169
184
|
ts_client.populate_vpc_requests(data, AWS_PROVIDER_VERSION)
|
|
170
185
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from collections.abc import Mapping
|
|
3
|
+
|
|
4
|
+
from reconcile.gql_definitions.fragments.aws_organization import (
|
|
5
|
+
AWSOrganization,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_aws_account_tags(
|
|
10
|
+
organization: AWSOrganization | Mapping | None,
|
|
11
|
+
) -> dict[str, str]:
|
|
12
|
+
"""
|
|
13
|
+
Get AWS account tags by merging payer account tags
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
organization: AWSOrganization | Mapping | None - The organization object from which to extract tags.
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
dict[str, str]: A dictionary containing the merged tags from the payer account and the account itself.
|
|
20
|
+
"""
|
|
21
|
+
if organization is None:
|
|
22
|
+
return {}
|
|
23
|
+
|
|
24
|
+
match organization:
|
|
25
|
+
case AWSOrganization():
|
|
26
|
+
payer_account_tags = (
|
|
27
|
+
organization.payer_account.organization_account_tags or {}
|
|
28
|
+
)
|
|
29
|
+
account_tags = organization.tags or {}
|
|
30
|
+
case Mapping():
|
|
31
|
+
payer_account_tags = organization.get("payerAccount", {}).get(
|
|
32
|
+
"organizationAccountTags", {}
|
|
33
|
+
)
|
|
34
|
+
if isinstance(payer_account_tags, str):
|
|
35
|
+
payer_account_tags = json.loads(payer_account_tags)
|
|
36
|
+
|
|
37
|
+
account_tags = organization.get("tags", {})
|
|
38
|
+
if isinstance(account_tags, str):
|
|
39
|
+
account_tags = json.loads(account_tags)
|
|
40
|
+
|
|
41
|
+
return payer_account_tags | account_tags
|
|
@@ -13,7 +13,7 @@ class CostNamespace(BaseModel, frozen=True):
|
|
|
13
13
|
labels: CostNamespaceLabels
|
|
14
14
|
app_name: str
|
|
15
15
|
cluster_name: str
|
|
16
|
-
cluster_external_id: str | None
|
|
16
|
+
cluster_external_id: str | None = None
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def get_cost_namespaces(
|
|
@@ -32,7 +32,7 @@ def get_cost_namespaces(
|
|
|
32
32
|
return [
|
|
33
33
|
CostNamespace(
|
|
34
34
|
name=namespace.name,
|
|
35
|
-
labels=CostNamespaceLabels.
|
|
35
|
+
labels=CostNamespaceLabels.model_validate(namespace.labels or {}),
|
|
36
36
|
app_name=namespace.app.name,
|
|
37
37
|
cluster_name=namespace.cluster.name,
|
|
38
38
|
cluster_external_id=namespace.cluster.spec.external_id
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import hashlib
|
|
2
|
-
import json
|
|
3
2
|
from collections.abc import Callable
|
|
4
3
|
from threading import Lock
|
|
5
4
|
from typing import Any
|
|
@@ -7,7 +6,6 @@ from typing import Any
|
|
|
7
6
|
from jsonpath_ng.exceptions import JsonPathParserError
|
|
8
7
|
from pydantic import (
|
|
9
8
|
BaseModel,
|
|
10
|
-
Extra,
|
|
11
9
|
Field,
|
|
12
10
|
Json,
|
|
13
11
|
)
|
|
@@ -48,10 +46,16 @@ from reconcile.utils.exceptions import (
|
|
|
48
46
|
AppInterfaceSettingsError,
|
|
49
47
|
ParameterError,
|
|
50
48
|
)
|
|
49
|
+
from reconcile.utils.json import json_dumps
|
|
51
50
|
from reconcile.utils.jsonpath import parse_jsonpath
|
|
52
51
|
|
|
53
52
|
|
|
54
|
-
class SaasResourceTemplateTarget(
|
|
53
|
+
class SaasResourceTemplateTarget(
|
|
54
|
+
ConfiguredBaseModel,
|
|
55
|
+
validate_by_alias=True,
|
|
56
|
+
# ignore `namespaceSelector` and 'provider' fields from the GQL schema
|
|
57
|
+
extra="ignore",
|
|
58
|
+
):
|
|
55
59
|
path: str | None = Field(..., alias="path")
|
|
56
60
|
name: str | None = Field(..., alias="name")
|
|
57
61
|
# the namespace must be required to fulfill the saas file schema (utils.saasherder.interface.SaasFile)
|
|
@@ -79,12 +83,8 @@ class SaasResourceTemplateTarget(ConfiguredBaseModel):
|
|
|
79
83
|
digest_size=20,
|
|
80
84
|
).hexdigest()
|
|
81
85
|
|
|
82
|
-
class Config:
|
|
83
|
-
# ignore `namespaceSelector` and 'provider' fields from the GQL schema
|
|
84
|
-
extra = Extra.ignore
|
|
85
|
-
|
|
86
86
|
|
|
87
|
-
class SaasResourceTemplate(ConfiguredBaseModel):
|
|
87
|
+
class SaasResourceTemplate(ConfiguredBaseModel, validate_by_alias=True):
|
|
88
88
|
name: str = Field(..., alias="name")
|
|
89
89
|
url: str = Field(..., alias="url")
|
|
90
90
|
path: str = Field(..., alias="path")
|
|
@@ -97,7 +97,7 @@ class SaasResourceTemplate(ConfiguredBaseModel):
|
|
|
97
97
|
targets: list[SaasResourceTemplateTarget] = Field(..., alias="targets")
|
|
98
98
|
|
|
99
99
|
|
|
100
|
-
class SaasFile(ConfiguredBaseModel):
|
|
100
|
+
class SaasFile(ConfiguredBaseModel, validate_by_alias=True):
|
|
101
101
|
path: str = Field(..., alias="path")
|
|
102
102
|
name: str = Field(..., alias="name")
|
|
103
103
|
labels: Json | None = Field(..., alias="labels")
|
|
@@ -221,7 +221,7 @@ class SaasFileList:
|
|
|
221
221
|
with self._namespaces_as_dict_lock:
|
|
222
222
|
self._namespaces_as_dict_cache = {
|
|
223
223
|
"namespace": [
|
|
224
|
-
ns.
|
|
224
|
+
ns.model_dump(by_alias=True, exclude_none=True)
|
|
225
225
|
for ns in self.namespaces
|
|
226
226
|
]
|
|
227
227
|
}
|
|
@@ -283,7 +283,7 @@ class SaasFileList:
|
|
|
283
283
|
if app_name and saas_file.app.name != app_name:
|
|
284
284
|
continue
|
|
285
285
|
|
|
286
|
-
sf = saas_file.
|
|
286
|
+
sf = saas_file.model_copy(deep=True)
|
|
287
287
|
if env_name:
|
|
288
288
|
for rt in sf.resource_templates[:]:
|
|
289
289
|
for target in rt.targets[:]:
|
|
@@ -302,7 +302,7 @@ def convert_parameters_to_json_string(root: dict[str, Any]) -> dict[str, Any]:
|
|
|
302
302
|
"""Find all parameter occurrences and convert them to a json string."""
|
|
303
303
|
for key, value in root.items():
|
|
304
304
|
if key in {"parameters", "labels"}:
|
|
305
|
-
root[key] =
|
|
305
|
+
root[key] = json_dumps(value) if value is not None else None
|
|
306
306
|
elif isinstance(value, dict):
|
|
307
307
|
root[key] = convert_parameters_to_json_string(value)
|
|
308
308
|
elif isinstance(value, list):
|
|
@@ -314,7 +314,7 @@ def convert_parameters_to_json_string(root: dict[str, Any]) -> dict[str, Any]:
|
|
|
314
314
|
|
|
315
315
|
|
|
316
316
|
def export_model(model: BaseModel) -> dict[str, Any]:
|
|
317
|
-
return convert_parameters_to_json_string(model.
|
|
317
|
+
return convert_parameters_to_json_string(model.model_dump(by_alias=True))
|
|
318
318
|
|
|
319
319
|
|
|
320
320
|
def get_saas_files(
|
|
@@ -32,7 +32,7 @@ def get_selected_app_names(
|
|
|
32
32
|
prefix = f"{namespace.app.parent_app.name}-"
|
|
33
33
|
name = f"{prefix}{namespace.app.name}"
|
|
34
34
|
selected_app_names.add(name)
|
|
35
|
-
app = namespace.app.
|
|
35
|
+
app = namespace.app.model_dump(by_alias=True)
|
|
36
36
|
app["name"] = name
|
|
37
37
|
apps["apps"].append(app)
|
|
38
38
|
|
|
@@ -40,7 +40,7 @@ def get_selected_app_names(
|
|
|
40
40
|
name = f"{namespace.app.name}-{child.name}"
|
|
41
41
|
if name not in selected_app_names:
|
|
42
42
|
selected_app_names.add(f"{namespace.app.name}-{child.name}")
|
|
43
|
-
child_dict = child.
|
|
43
|
+
child_dict = child.model_dump(by_alias=True)
|
|
44
44
|
child_dict["name"] = name
|
|
45
45
|
apps["apps"].append(child_dict)
|
|
46
46
|
|
|
@@ -31,7 +31,7 @@ QONTRACT_INTEGRATION_VERSION = make_semver(1, 0, 0)
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
class UnleashTogglesIntegrationParams(PydanticRunParams):
|
|
34
|
-
instance: str | None
|
|
34
|
+
instance: str | None = None
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
def feature_toggle_equal(c: FeatureToggle, d: FeatureToggleUnleashV1) -> bool:
|
|
@@ -68,7 +68,9 @@ class UnleashTogglesIntegration(
|
|
|
68
68
|
if not query_func:
|
|
69
69
|
query_func = gql.get_api().query
|
|
70
70
|
return {
|
|
71
|
-
"toggles": [
|
|
71
|
+
"toggles": [
|
|
72
|
+
ft.model_dump() for ft in self.get_unleash_instances(query_func)
|
|
73
|
+
],
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
def get_unleash_instances(
|
reconcile/utils/acs/base.py
CHANGED
|
@@ -6,7 +6,7 @@ from typing import (
|
|
|
6
6
|
)
|
|
7
7
|
|
|
8
8
|
import requests
|
|
9
|
-
from pydantic import BaseModel
|
|
9
|
+
from pydantic import BaseModel, ConfigDict
|
|
10
10
|
|
|
11
11
|
from reconcile.gql_definitions.acs.acs_instances import AcsInstanceV1
|
|
12
12
|
from reconcile.gql_definitions.acs.acs_instances import query as acs_instances_query
|
|
@@ -19,8 +19,11 @@ class AcsBaseApi(BaseModel):
|
|
|
19
19
|
timeout: int = 30
|
|
20
20
|
session: requests.Session = requests.Session()
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
model_config = ConfigDict(
|
|
23
|
+
validate_by_name=True,
|
|
24
|
+
validate_by_alias=True,
|
|
25
|
+
arbitrary_types_allowed=True,
|
|
26
|
+
)
|
|
24
27
|
|
|
25
28
|
def __enter__(self) -> Self:
|
|
26
29
|
return self
|