qontract-reconcile 0.10.2.dev299__py3-none-any.whl → 0.10.2.dev430__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.dev299.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/METADATA +13 -12
- {qontract_reconcile-0.10.2.dev299.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/RECORD +399 -394
- 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 +4 -4
- 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 +8 -11
- 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 +23 -10
- 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 +492 -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 +10 -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 +3050 -1393
- 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 +448 -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 +5 -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 +4 -0
- reconcile/templates/rosa-hcp-cluster-creation.sh.j2 +3 -0
- 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 +27 -19
- reconcile/terraform_users.py +29 -21
- reconcile/terraform_vpc_peerings.py +16 -4
- reconcile/terraform_vpc_resources/integration.py +32 -2
- 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 +59 -43
- 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 +27 -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/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 +4 -4
- reconcile/utils/terraform_client.py +32 -29
- reconcile/utils/terrascript_aws_client.py +658 -480
- reconcile/utils/three_way_diff_strategy.py +1 -1
- reconcile/utils/throughput.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
- reconcile/vpc_peerings_validator.py +2 -2
- 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/sre_checkpoints/util.py +5 -3
- 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.dev299.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev299.dist-info → qontract_reconcile-0.10.2.dev430.dist-info}/entry_points.txt +0 -0
|
@@ -88,7 +88,7 @@ class TerraformCloudflareUsers(
|
|
|
88
88
|
if not settings.settings:
|
|
89
89
|
raise RuntimeError("App interface setting not defined")
|
|
90
90
|
|
|
91
|
-
early_exit_desired_state = cloudflare_roles.
|
|
91
|
+
early_exit_desired_state = cloudflare_roles.model_dump()
|
|
92
92
|
early_exit_desired_state.update({
|
|
93
93
|
CLOUDFLARE_EMAIL_DOMAIN_ALLOW_LIST_KEY: settings.settings
|
|
94
94
|
})
|
|
@@ -149,7 +149,8 @@ class TerraformCloudflareUsers(
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
accounts = [
|
|
152
|
-
acct.
|
|
152
|
+
acct.model_dump(by_alias=True)
|
|
153
|
+
for _, acct in account_names_to_account.items()
|
|
153
154
|
]
|
|
154
155
|
|
|
155
156
|
self._run_terraform(
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from collections.abc import Callable
|
|
3
|
-
from datetime import UTC, datetime
|
|
4
3
|
from typing import Any
|
|
5
4
|
|
|
6
5
|
import jinja2
|
|
@@ -12,12 +11,16 @@ from reconcile.gql_definitions.terraform_init.aws_accounts import (
|
|
|
12
11
|
from reconcile.terraform_init.merge_request import Renderer, create_parser
|
|
13
12
|
from reconcile.terraform_init.merge_request_manager import MergeRequestManager, MrData
|
|
14
13
|
from reconcile.typed_queries.app_interface_repo_url import get_app_interface_repo_url
|
|
14
|
+
from reconcile.typed_queries.aws_account_tags import get_aws_account_tags
|
|
15
|
+
from reconcile.typed_queries.external_resources import get_settings
|
|
15
16
|
from reconcile.typed_queries.github_orgs import get_github_orgs
|
|
16
17
|
from reconcile.typed_queries.gitlab_instances import get_gitlab_instances
|
|
17
18
|
from reconcile.utils import gql
|
|
18
19
|
from reconcile.utils.aws_api_typed.api import AWSApi, AWSStaticCredentials
|
|
20
|
+
from reconcile.utils.datetime_util import utc_now
|
|
19
21
|
from reconcile.utils.defer import defer
|
|
20
22
|
from reconcile.utils.disabled_integrations import integration_is_enabled
|
|
23
|
+
from reconcile.utils.gql import GqlApi
|
|
21
24
|
from reconcile.utils.runtime.integration import (
|
|
22
25
|
PydanticRunParams,
|
|
23
26
|
QontractReconcileIntegration,
|
|
@@ -31,10 +34,16 @@ QONTRACT_INTEGRATION_VERSION = make_semver(1, 0, 0)
|
|
|
31
34
|
|
|
32
35
|
|
|
33
36
|
class TerraformInitIntegrationParams(PydanticRunParams):
|
|
34
|
-
account_name: str | None
|
|
37
|
+
account_name: str | None = None
|
|
35
38
|
# To avoid the accidental deletion of the resource file, explicitly set the
|
|
36
39
|
# qontract.cli option in the integration extraArgs!
|
|
37
40
|
state_tmpl_resource: str = "/terraform-init/terraform-state.yml"
|
|
41
|
+
cloudformation_template_resource: str = (
|
|
42
|
+
"/terraform-init/terraform-state-s3-bucket.yaml"
|
|
43
|
+
)
|
|
44
|
+
cloudformation_import_template_resource: str = (
|
|
45
|
+
"/terraform-init/terraform-state-s3-bucket-import.yaml"
|
|
46
|
+
)
|
|
38
47
|
template_collection_root_path: str = "data/templating/collections/terraform-init"
|
|
39
48
|
|
|
40
49
|
|
|
@@ -55,25 +64,35 @@ class TerraformInitIntegration(
|
|
|
55
64
|
query_func = gql.get_api().query
|
|
56
65
|
return {
|
|
57
66
|
"accounts": [
|
|
58
|
-
account.
|
|
67
|
+
account.model_dump() for account in self.get_aws_accounts(query_func)
|
|
59
68
|
],
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
def get_aws_accounts(
|
|
63
72
|
self, query_func: Callable, account_name: str | None = None
|
|
64
73
|
) -> list[AWSAccountV1]:
|
|
65
|
-
"""Return all AWS accounts with terraform username
|
|
74
|
+
"""Return all AWS accounts with terraform username."""
|
|
66
75
|
return [
|
|
67
76
|
account
|
|
68
77
|
for account in aws_accounts_query(query_func).accounts or []
|
|
69
78
|
if integration_is_enabled(self.name, account)
|
|
70
79
|
and (not account_name or account.name == account_name)
|
|
71
80
|
and account.terraform_username
|
|
72
|
-
and not account.terraform_state
|
|
73
81
|
]
|
|
74
82
|
|
|
83
|
+
@staticmethod
|
|
84
|
+
def get_default_tags(gql_api: GqlApi) -> dict[str, str]:
|
|
85
|
+
try:
|
|
86
|
+
return get_settings(gql_api.query).default_tags
|
|
87
|
+
except ValueError:
|
|
88
|
+
# no settings found
|
|
89
|
+
return {}
|
|
90
|
+
|
|
91
|
+
@staticmethod
|
|
75
92
|
def render_state_collection(
|
|
76
|
-
|
|
93
|
+
template: str,
|
|
94
|
+
bucket_name: str,
|
|
95
|
+
account: AWSAccountV1,
|
|
77
96
|
) -> str:
|
|
78
97
|
return jinja2.Template(
|
|
79
98
|
template,
|
|
@@ -85,24 +104,114 @@ class TerraformInitIntegration(
|
|
|
85
104
|
"account_name": account.name,
|
|
86
105
|
"bucket_name": bucket_name,
|
|
87
106
|
"region": account.resources_default_region,
|
|
88
|
-
"timestamp": int(
|
|
107
|
+
"timestamp": int(utc_now().timestamp()),
|
|
89
108
|
})
|
|
90
109
|
|
|
91
110
|
def reconcile_account(
|
|
92
111
|
self,
|
|
93
|
-
|
|
112
|
+
aws_api: AWSApi,
|
|
113
|
+
merge_request_manager: MergeRequestManager,
|
|
114
|
+
dry_run: bool,
|
|
115
|
+
account: AWSAccountV1,
|
|
116
|
+
state_template: str,
|
|
117
|
+
cloudformation_template: str,
|
|
118
|
+
cloudformation_import_template: str,
|
|
119
|
+
default_tags: dict[str, str],
|
|
120
|
+
) -> None:
|
|
121
|
+
"""
|
|
122
|
+
Reconcile the terraform state for a given account.
|
|
123
|
+
|
|
124
|
+
Create S3 bucket via CloudFormation and Merge Request to update template file on init.
|
|
125
|
+
Import existing bucket if it exists but not managed by CloudFormation.
|
|
126
|
+
Update CloudFormation stack if tags or template body differ.
|
|
127
|
+
|
|
128
|
+
CloudFormation stack name and bucket name is `terraform-<account_name>`.
|
|
129
|
+
`cloudformation_import_template` should be minimal template with identifier fields only.
|
|
130
|
+
`cloudformation_template` should be the full template.
|
|
131
|
+
Use import template to import then update stack to match full template.
|
|
132
|
+
This will ensure imported resources match CloudFormation template.
|
|
133
|
+
And all desired changes in full template are applied.
|
|
134
|
+
Both templates must have BucketName in Parameters.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
aws_api: AWSApi: AWS API client for the target account.
|
|
138
|
+
merge_request_manager: MergeRequestManager: Manager to handle merge requests.
|
|
139
|
+
dry_run: bool: If True, do not make any changes.
|
|
140
|
+
account: AWSAccountV1: The AWS account to reconcile.
|
|
141
|
+
state_template: str: Jinja2 template for the Terraform state configuration.
|
|
142
|
+
cloudformation_template: str: CloudFormation template to create the S3 bucket.
|
|
143
|
+
cloudformation_import_template: str: CloudFormation template to import existing S3 bucket.
|
|
144
|
+
default_tags: dict[str, str]: Default tags to apply to the CloudFormation stack.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
None
|
|
148
|
+
"""
|
|
149
|
+
bucket_name = (
|
|
150
|
+
account.terraform_state.bucket
|
|
151
|
+
if account.terraform_state
|
|
152
|
+
else f"terraform-{account.name}"
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
tags = default_tags | get_aws_account_tags(account.organization)
|
|
156
|
+
|
|
157
|
+
if account.terraform_state is None:
|
|
158
|
+
return self._provision_terraform_state(
|
|
159
|
+
aws_api=aws_api,
|
|
160
|
+
merge_request_manager=merge_request_manager,
|
|
161
|
+
dry_run=dry_run,
|
|
162
|
+
account=account,
|
|
163
|
+
bucket_name=bucket_name,
|
|
164
|
+
cloudformation_template=cloudformation_template,
|
|
165
|
+
state_template=state_template,
|
|
166
|
+
tags=tags,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
stack = aws_api.cloudformation.get_stack(stack_name=bucket_name)
|
|
170
|
+
|
|
171
|
+
if stack is None:
|
|
172
|
+
return self._import_cloudformation_stack(
|
|
173
|
+
aws_api=aws_api,
|
|
174
|
+
dry_run=dry_run,
|
|
175
|
+
bucket_name=bucket_name,
|
|
176
|
+
cloudformation_import_template=cloudformation_import_template,
|
|
177
|
+
cloudformation_template=cloudformation_template,
|
|
178
|
+
tags=tags,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
return self._reconcile_cloudformation_stack(
|
|
182
|
+
aws_api=aws_api,
|
|
183
|
+
dry_run=dry_run,
|
|
184
|
+
bucket_name=bucket_name,
|
|
185
|
+
cloudformation_template=cloudformation_template,
|
|
186
|
+
tags=tags,
|
|
187
|
+
current_tags={tag["Key"]: tag["Value"] for tag in stack.get("Tags", [])},
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def _provision_terraform_state(
|
|
191
|
+
self,
|
|
192
|
+
aws_api: AWSApi,
|
|
94
193
|
merge_request_manager: MergeRequestManager,
|
|
95
194
|
dry_run: bool,
|
|
96
|
-
state_collection: str,
|
|
97
|
-
bucket_name: str,
|
|
98
195
|
account: AWSAccountV1,
|
|
196
|
+
bucket_name: str,
|
|
197
|
+
cloudformation_template: str,
|
|
198
|
+
state_template: str,
|
|
199
|
+
tags: dict[str, str],
|
|
99
200
|
) -> None:
|
|
100
201
|
logging.info("Creating bucket '%s' for account '%s'", bucket_name, account.name)
|
|
101
202
|
if not dry_run:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
203
|
+
aws_api.cloudformation.create_stack(
|
|
204
|
+
stack_name=bucket_name,
|
|
205
|
+
change_set_name=f"create-{bucket_name}",
|
|
206
|
+
template_body=cloudformation_template,
|
|
207
|
+
parameters={"BucketName": bucket_name},
|
|
208
|
+
tags=tags,
|
|
105
209
|
)
|
|
210
|
+
state_collection = self.render_state_collection(
|
|
211
|
+
template=state_template,
|
|
212
|
+
bucket_name=bucket_name,
|
|
213
|
+
account=account,
|
|
214
|
+
)
|
|
106
215
|
merge_request_manager.create_merge_request(
|
|
107
216
|
data=MrData(
|
|
108
217
|
account=account.name,
|
|
@@ -111,6 +220,55 @@ class TerraformInitIntegration(
|
|
|
111
220
|
)
|
|
112
221
|
)
|
|
113
222
|
|
|
223
|
+
@staticmethod
|
|
224
|
+
def _import_cloudformation_stack(
|
|
225
|
+
aws_api: AWSApi,
|
|
226
|
+
dry_run: bool,
|
|
227
|
+
bucket_name: str,
|
|
228
|
+
cloudformation_import_template: str,
|
|
229
|
+
cloudformation_template: str,
|
|
230
|
+
tags: dict[str, str],
|
|
231
|
+
) -> None:
|
|
232
|
+
logging.info("Importing existing bucket %s", bucket_name)
|
|
233
|
+
if not dry_run:
|
|
234
|
+
aws_api.cloudformation.create_stack(
|
|
235
|
+
stack_name=bucket_name,
|
|
236
|
+
change_set_name=f"import-{bucket_name}",
|
|
237
|
+
template_body=cloudformation_import_template,
|
|
238
|
+
parameters={"BucketName": bucket_name},
|
|
239
|
+
tags=tags,
|
|
240
|
+
)
|
|
241
|
+
logging.info("Syncing stack %s after import", bucket_name)
|
|
242
|
+
aws_api.cloudformation.update_stack(
|
|
243
|
+
stack_name=bucket_name,
|
|
244
|
+
template_body=cloudformation_template,
|
|
245
|
+
parameters={"BucketName": bucket_name},
|
|
246
|
+
tags=tags,
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
@staticmethod
|
|
250
|
+
def _reconcile_cloudformation_stack(
|
|
251
|
+
aws_api: AWSApi,
|
|
252
|
+
dry_run: bool,
|
|
253
|
+
bucket_name: str,
|
|
254
|
+
cloudformation_template: str,
|
|
255
|
+
tags: dict[str, str],
|
|
256
|
+
current_tags: dict[str, str],
|
|
257
|
+
) -> None:
|
|
258
|
+
if (
|
|
259
|
+
current_tags != tags
|
|
260
|
+
or aws_api.cloudformation.get_template_body(stack_name=bucket_name)
|
|
261
|
+
!= cloudformation_template
|
|
262
|
+
):
|
|
263
|
+
logging.info("Updating stack %s", bucket_name)
|
|
264
|
+
if not dry_run:
|
|
265
|
+
aws_api.cloudformation.update_stack(
|
|
266
|
+
stack_name=bucket_name,
|
|
267
|
+
template_body=cloudformation_template,
|
|
268
|
+
parameters={"BucketName": bucket_name},
|
|
269
|
+
tags=tags,
|
|
270
|
+
)
|
|
271
|
+
|
|
114
272
|
@defer
|
|
115
273
|
def run(self, dry_run: bool, defer: Callable | None = None) -> None:
|
|
116
274
|
"""Run the integration."""
|
|
@@ -144,6 +302,14 @@ class TerraformInitIntegration(
|
|
|
144
302
|
state_template = gql_api.get_resource(path=self.params.state_tmpl_resource)[
|
|
145
303
|
"content"
|
|
146
304
|
]
|
|
305
|
+
cloudformation_template = gql_api.get_resource(
|
|
306
|
+
path=self.params.cloudformation_template_resource
|
|
307
|
+
)["content"]
|
|
308
|
+
cloudformation_import_template = gql_api.get_resource(
|
|
309
|
+
path=self.params.cloudformation_import_template_resource
|
|
310
|
+
)["content"]
|
|
311
|
+
default_tags = self.get_default_tags(gql_api)
|
|
312
|
+
|
|
147
313
|
for account in accounts:
|
|
148
314
|
secret = self.secret_reader.read_all_secret(account.automation_token)
|
|
149
315
|
with AWSApi(
|
|
@@ -153,15 +319,13 @@ class TerraformInitIntegration(
|
|
|
153
319
|
region=account.resources_default_region,
|
|
154
320
|
)
|
|
155
321
|
) as account_aws_api:
|
|
156
|
-
bucket_name = f"terraform-{account.name}"
|
|
157
|
-
state_collection = self.render_state_collection(
|
|
158
|
-
state_template, bucket_name, account
|
|
159
|
-
)
|
|
160
322
|
self.reconcile_account(
|
|
161
|
-
account_aws_api,
|
|
162
|
-
merge_request_manager,
|
|
163
|
-
dry_run,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
323
|
+
aws_api=account_aws_api,
|
|
324
|
+
merge_request_manager=merge_request_manager,
|
|
325
|
+
dry_run=dry_run,
|
|
326
|
+
account=account,
|
|
327
|
+
state_template=state_template,
|
|
328
|
+
cloudformation_template=cloudformation_template,
|
|
329
|
+
cloudformation_import_template=cloudformation_import_template,
|
|
330
|
+
default_tags=default_tags,
|
|
167
331
|
)
|
reconcile/terraform_repo.py
CHANGED
|
@@ -41,10 +41,10 @@ class RepoOutput(BaseModel):
|
|
|
41
41
|
project_path: str
|
|
42
42
|
delete: bool
|
|
43
43
|
aws_creds: VaultSecret
|
|
44
|
-
variables: TerraformRepoVariablesV1 | None
|
|
45
|
-
bucket: str | None
|
|
46
|
-
region: str | None
|
|
47
|
-
bucket_path: str | None
|
|
44
|
+
variables: TerraformRepoVariablesV1 | None = None
|
|
45
|
+
bucket: str | None = None
|
|
46
|
+
region: str | None = None
|
|
47
|
+
bucket_path: str | None = None
|
|
48
48
|
require_fips: bool
|
|
49
49
|
tf_version: str
|
|
50
50
|
|
|
@@ -62,8 +62,8 @@ class OutputFile(BaseModel):
|
|
|
62
62
|
class TerraformRepoIntegrationParams(PydanticRunParams):
|
|
63
63
|
output_file: str | None
|
|
64
64
|
validate_git: bool
|
|
65
|
-
gitlab_project_id: str | None
|
|
66
|
-
gitlab_merge_request_id: int | None
|
|
65
|
+
gitlab_project_id: str | None = None
|
|
66
|
+
gitlab_merge_request_id: int | None = None
|
|
67
67
|
|
|
68
68
|
|
|
69
69
|
class TerraformRepoIntegration(
|
|
@@ -168,7 +168,7 @@ class TerraformRepoIntegration(
|
|
|
168
168
|
self.params.output_file, "w", encoding="locale"
|
|
169
169
|
) as output_file:
|
|
170
170
|
yaml.safe_dump(
|
|
171
|
-
data=output.
|
|
171
|
+
data=output.model_dump(),
|
|
172
172
|
stream=output_file,
|
|
173
173
|
explicit_start=True,
|
|
174
174
|
)
|
|
@@ -177,7 +177,7 @@ class TerraformRepoIntegration(
|
|
|
177
177
|
f"Unable to write to '{self.params.output_file}'"
|
|
178
178
|
) from None
|
|
179
179
|
else:
|
|
180
|
-
print(yaml.safe_dump(data=output.
|
|
180
|
+
print(yaml.safe_dump(data=output.model_dump(), explicit_start=True))
|
|
181
181
|
|
|
182
182
|
return output
|
|
183
183
|
|
|
@@ -206,7 +206,7 @@ class TerraformRepoIntegration(
|
|
|
206
206
|
keys = state.ls()
|
|
207
207
|
for key in keys:
|
|
208
208
|
if value := state.get(key.lstrip("/"), None):
|
|
209
|
-
repo = TerraformRepoV1.
|
|
209
|
+
repo = TerraformRepoV1.model_validate(value)
|
|
210
210
|
repo_list.append(repo)
|
|
211
211
|
|
|
212
212
|
return repo_list
|
|
@@ -283,7 +283,7 @@ class TerraformRepoIntegration(
|
|
|
283
283
|
for add_key, add_val in diff_result.add.items():
|
|
284
284
|
# state.add already performs a json.dumps(key) so we export the
|
|
285
285
|
# pydantic model as a dict to avoid a double json dump with extra quotes
|
|
286
|
-
state.add(add_key, add_val.
|
|
286
|
+
state.add(add_key, add_val.model_dump(by_alias=True), force=True)
|
|
287
287
|
for delete_key in diff_result.delete:
|
|
288
288
|
state.rm(delete_key)
|
|
289
289
|
for change_key, change_val in diff_result.change.items():
|
|
@@ -291,7 +291,9 @@ class TerraformRepoIntegration(
|
|
|
291
291
|
state.rm(change_key)
|
|
292
292
|
else:
|
|
293
293
|
state.add(
|
|
294
|
-
change_key,
|
|
294
|
+
change_key,
|
|
295
|
+
change_val.desired.model_dump(by_alias=True),
|
|
296
|
+
force=True,
|
|
295
297
|
)
|
|
296
298
|
except KeyError:
|
|
297
299
|
pass
|
|
@@ -394,5 +396,7 @@ class TerraformRepoIntegration(
|
|
|
394
396
|
def early_exit_desired_state(self, *args: Any, **kwargs: Any) -> dict[str, Any]:
|
|
395
397
|
gqlapi = gql.get_api()
|
|
396
398
|
return {
|
|
397
|
-
"repos": [
|
|
399
|
+
"repos": [
|
|
400
|
+
repo.model_dump() for repo in self.get_repos(query_func=gqlapi.query)
|
|
401
|
+
]
|
|
398
402
|
}
|
reconcile/terraform_resources.py
CHANGED
|
@@ -10,7 +10,6 @@ from dataclasses import asdict
|
|
|
10
10
|
from typing import (
|
|
11
11
|
Any,
|
|
12
12
|
TypedDict,
|
|
13
|
-
cast,
|
|
14
13
|
)
|
|
15
14
|
|
|
16
15
|
from deepdiff import DeepHash
|
|
@@ -28,6 +27,7 @@ from reconcile.gql_definitions.terraform_resources.terraform_resources_namespace
|
|
|
28
27
|
from reconcile.typed_queries.app_interface_vault_settings import (
|
|
29
28
|
get_app_interface_vault_settings,
|
|
30
29
|
)
|
|
30
|
+
from reconcile.typed_queries.external_resources import get_settings
|
|
31
31
|
from reconcile.typed_queries.terraform_namespaces import get_namespaces
|
|
32
32
|
from reconcile.utils import gql
|
|
33
33
|
from reconcile.utils.aws_api import AWSApi
|
|
@@ -63,7 +63,6 @@ from reconcile.utils.terrascript_aws_client import TerrascriptClient as Terrascr
|
|
|
63
63
|
from reconcile.utils.unleash import get_feature_toggle_state
|
|
64
64
|
from reconcile.utils.vault import (
|
|
65
65
|
VaultClient,
|
|
66
|
-
_VaultClient,
|
|
67
66
|
)
|
|
68
67
|
|
|
69
68
|
QONTRACT_INTEGRATION = "terraform_resources"
|
|
@@ -138,7 +137,7 @@ def fetch_current_state(
|
|
|
138
137
|
use_jump_host=use_jump_host,
|
|
139
138
|
thread_pool_size=thread_pool_size,
|
|
140
139
|
)
|
|
141
|
-
namespaces_dicts = [ns.
|
|
140
|
+
namespaces_dicts = [ns.model_dump(by_alias=True) for ns in namespaces]
|
|
142
141
|
state_specs = ob.init_specs_to_fetch(
|
|
143
142
|
ri, oc_map, namespaces=namespaces_dicts, override_managed_types=["Secret"]
|
|
144
143
|
)
|
|
@@ -160,6 +159,7 @@ def init_working_dirs(
|
|
|
160
159
|
accounts: list[dict[str, Any]],
|
|
161
160
|
thread_pool_size: int,
|
|
162
161
|
settings: Mapping[str, Any] | None = None,
|
|
162
|
+
default_tags: Mapping[str, str] | None = None,
|
|
163
163
|
) -> tuple[Terrascript, dict[str, str]]:
|
|
164
164
|
ts = Terrascript(
|
|
165
165
|
QONTRACT_INTEGRATION,
|
|
@@ -167,6 +167,7 @@ def init_working_dirs(
|
|
|
167
167
|
thread_pool_size,
|
|
168
168
|
accounts,
|
|
169
169
|
settings=settings,
|
|
170
|
+
default_tags=default_tags,
|
|
170
171
|
)
|
|
171
172
|
working_dirs = ts.dump()
|
|
172
173
|
return ts, working_dirs
|
|
@@ -243,8 +244,15 @@ def setup(
|
|
|
243
244
|
secret_reader = create_secret_reader(use_vault=vault_settings.vault)
|
|
244
245
|
|
|
245
246
|
settings = queries.get_app_interface_settings() or {}
|
|
247
|
+
try:
|
|
248
|
+
default_tags = get_settings().default_tags
|
|
249
|
+
except ValueError:
|
|
250
|
+
# no external resources settings found
|
|
251
|
+
default_tags = None
|
|
246
252
|
# initialize terrascript (scripting engine to generate terraform manifests)
|
|
247
|
-
ts, working_dirs = init_working_dirs(
|
|
253
|
+
ts, working_dirs = init_working_dirs(
|
|
254
|
+
accounts, thread_pool_size, settings=settings, default_tags=default_tags
|
|
255
|
+
)
|
|
248
256
|
|
|
249
257
|
# initialize terraform client
|
|
250
258
|
# it is used to plan and apply according to the output of terrascript
|
|
@@ -265,7 +273,7 @@ def setup(
|
|
|
265
273
|
)
|
|
266
274
|
else:
|
|
267
275
|
ocm_map = None
|
|
268
|
-
tf_namespaces_dicts = [ns.
|
|
276
|
+
tf_namespaces_dicts = [ns.model_dump(by_alias=True) for ns in tf_namespaces]
|
|
269
277
|
|
|
270
278
|
provider_exclusions = settings.get("terraformResourcesProviderExclusions") or []
|
|
271
279
|
ts.init_populate_specs(
|
|
@@ -287,16 +295,16 @@ def filter_tf_namespaces(
|
|
|
287
295
|
) -> list[NamespaceV1]:
|
|
288
296
|
tf_namespaces = []
|
|
289
297
|
for namespace_info in namespaces:
|
|
290
|
-
if ob.is_namespace_deleted(namespace_info.
|
|
298
|
+
if ob.is_namespace_deleted(namespace_info.model_dump(by_alias=True)):
|
|
291
299
|
continue
|
|
292
|
-
if not managed_external_resources(namespace_info.
|
|
300
|
+
if not managed_external_resources(namespace_info.model_dump(by_alias=True)):
|
|
293
301
|
continue
|
|
294
302
|
|
|
295
303
|
if not account_names:
|
|
296
304
|
tf_namespaces.append(namespace_info)
|
|
297
305
|
continue
|
|
298
306
|
|
|
299
|
-
specs = get_external_resource_specs(namespace_info.
|
|
307
|
+
specs = get_external_resource_specs(namespace_info.model_dump(by_alias=True))
|
|
300
308
|
if not specs:
|
|
301
309
|
tf_namespaces.append(namespace_info)
|
|
302
310
|
continue
|
|
@@ -314,7 +322,7 @@ def write_outputs_to_vault(
|
|
|
314
322
|
vault_path: str, resource_specs: ExternalResourceSpecInventory
|
|
315
323
|
) -> None:
|
|
316
324
|
integration_name = QONTRACT_INTEGRATION.replace("_", "-")
|
|
317
|
-
vault_client =
|
|
325
|
+
vault_client = VaultClient.get_instance()
|
|
318
326
|
for spec in resource_specs.values():
|
|
319
327
|
# a secret can be empty if the terraform-integration is not enabled on the cluster
|
|
320
328
|
# the resource is defined on - lets skip vault writes for those right now and
|
|
@@ -559,7 +567,7 @@ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
|
|
|
559
567
|
}
|
|
560
568
|
for ns_info in get_tf_namespaces():
|
|
561
569
|
for spec in get_external_resource_specs(
|
|
562
|
-
ns_info.
|
|
570
|
+
ns_info.model_dump(by_alias=True), provision_provider=PROVIDER_AWS
|
|
563
571
|
):
|
|
564
572
|
resource_paths = [
|
|
565
573
|
spec.resource.get("defaults"),
|
|
@@ -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] | 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
|
|
@@ -346,7 +347,7 @@ def _populate_tgw_attachments_working_dirs(
|
|
|
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:
|