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
|
@@ -22,7 +22,6 @@ from typing import (
|
|
|
22
22
|
TYPE_CHECKING,
|
|
23
23
|
Any,
|
|
24
24
|
Self,
|
|
25
|
-
TypeAlias,
|
|
26
25
|
cast,
|
|
27
26
|
)
|
|
28
27
|
|
|
@@ -152,6 +151,7 @@ from reconcile.github_org import get_default_config
|
|
|
152
151
|
from reconcile.gql_definitions.terraform_resources.terraform_resources_namespaces import (
|
|
153
152
|
NamespaceTerraformResourceLifecycleV1,
|
|
154
153
|
)
|
|
154
|
+
from reconcile.typed_queries.aws_account_tags import get_aws_account_tags
|
|
155
155
|
from reconcile.utils import gql
|
|
156
156
|
from reconcile.utils.aws_api import (
|
|
157
157
|
AmiTag,
|
|
@@ -178,7 +178,11 @@ from reconcile.utils.external_resources import (
|
|
|
178
178
|
from reconcile.utils.git import is_file_in_git_repo
|
|
179
179
|
from reconcile.utils.gitlab_api import GitLabApi
|
|
180
180
|
from reconcile.utils.jenkins_api import JenkinsApi
|
|
181
|
-
from reconcile.utils.jinja2.utils import
|
|
181
|
+
from reconcile.utils.jinja2.utils import (
|
|
182
|
+
process_extracurlyjinja2_template,
|
|
183
|
+
process_jinja2_template,
|
|
184
|
+
)
|
|
185
|
+
from reconcile.utils.json import json_dumps
|
|
182
186
|
from reconcile.utils.password_validator import (
|
|
183
187
|
PasswordPolicy,
|
|
184
188
|
PasswordValidator,
|
|
@@ -202,7 +206,7 @@ if TYPE_CHECKING:
|
|
|
202
206
|
from reconcile.utils.ocm import OCMMap
|
|
203
207
|
|
|
204
208
|
|
|
205
|
-
TFResource
|
|
209
|
+
type TFResource = type[
|
|
206
210
|
Resource | Data | Module | Provider | Variable | Output | Locals | Terraform
|
|
207
211
|
]
|
|
208
212
|
|
|
@@ -267,6 +271,8 @@ VARIABLE_KEYS = [
|
|
|
267
271
|
"extra_tags",
|
|
268
272
|
"lifecycle",
|
|
269
273
|
"max_session_duration",
|
|
274
|
+
"secret_format",
|
|
275
|
+
"policy",
|
|
270
276
|
]
|
|
271
277
|
|
|
272
278
|
EMAIL_REGEX = re.compile(r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")
|
|
@@ -282,15 +288,10 @@ SUPPORTED_ALB_LISTENER_RULE_CONDITION_TYPE_MAPPING = {
|
|
|
282
288
|
"host-header": "host_header",
|
|
283
289
|
"http-request-method": "http_request_method",
|
|
284
290
|
"path-pattern": "path_pattern",
|
|
291
|
+
"query-string": "query_string",
|
|
285
292
|
"source-ip": "source_ip",
|
|
286
293
|
}
|
|
287
294
|
|
|
288
|
-
DEFAULT_TAGS = {
|
|
289
|
-
"tags": {
|
|
290
|
-
"app": "app-sre-infra",
|
|
291
|
-
},
|
|
292
|
-
}
|
|
293
|
-
|
|
294
295
|
AWS_ELB_ACCOUNT_IDS = {
|
|
295
296
|
"us-east-1": "127311923021",
|
|
296
297
|
"us-east-2": "033677994240",
|
|
@@ -373,6 +374,10 @@ class aws_s3_bucket_logging(Resource):
|
|
|
373
374
|
pass
|
|
374
375
|
|
|
375
376
|
|
|
377
|
+
class aws_kinesis_resource_policy(Resource):
|
|
378
|
+
pass
|
|
379
|
+
|
|
380
|
+
|
|
376
381
|
class aws_cloudfront_log_delivery_canonical_user_id(Data):
|
|
377
382
|
pass
|
|
378
383
|
|
|
@@ -474,6 +479,7 @@ class TerrascriptClient:
|
|
|
474
479
|
integration_prefix: str,
|
|
475
480
|
thread_pool_size: int,
|
|
476
481
|
accounts: Iterable[MutableMapping[str, Any]],
|
|
482
|
+
default_tags: Mapping[str, str] | None,
|
|
477
483
|
settings: Mapping[str, Any] | None = None,
|
|
478
484
|
prefetch_resources_by_schemas: Iterable[str] | None = None,
|
|
479
485
|
secret_reader: SecretReaderBase | None = None,
|
|
@@ -487,6 +493,7 @@ class TerrascriptClient:
|
|
|
487
493
|
else:
|
|
488
494
|
self.secret_reader = SecretReader(settings=settings)
|
|
489
495
|
self.configs: dict[str, dict] = {}
|
|
496
|
+
self.default_tags = default_tags or {"app": "app-sre-infra"}
|
|
490
497
|
self.populate_configs(filtered_accounts)
|
|
491
498
|
self.versions: dict[str, str] = {
|
|
492
499
|
a["name"]: a["providerVersion"] for a in filtered_accounts
|
|
@@ -507,7 +514,7 @@ class TerrascriptClient:
|
|
|
507
514
|
region=region,
|
|
508
515
|
alias=region,
|
|
509
516
|
skip_region_validation=True,
|
|
510
|
-
default_tags=
|
|
517
|
+
default_tags={"tags": config["tags"]},
|
|
511
518
|
)
|
|
512
519
|
|
|
513
520
|
# Add default region, which will be in resourcesDefaultRegion
|
|
@@ -516,7 +523,7 @@ class TerrascriptClient:
|
|
|
516
523
|
secret_key=config["aws_secret_access_key"],
|
|
517
524
|
region=config["resourcesDefaultRegion"],
|
|
518
525
|
skip_region_validation=True,
|
|
519
|
-
default_tags=
|
|
526
|
+
default_tags={"tags": config["tags"]},
|
|
520
527
|
)
|
|
521
528
|
|
|
522
529
|
ts += Terraform(
|
|
@@ -799,6 +806,9 @@ class TerrascriptClient:
|
|
|
799
806
|
config["supportedDeploymentRegions"] = account["supportedDeploymentRegions"]
|
|
800
807
|
config["resourcesDefaultRegion"] = account["resourcesDefaultRegion"]
|
|
801
808
|
config["terraformState"] = account["terraformState"]
|
|
809
|
+
config["tags"] = dict(self.default_tags) | get_aws_account_tags(
|
|
810
|
+
account.get("organization", None)
|
|
811
|
+
)
|
|
802
812
|
self.configs[account_name] = config
|
|
803
813
|
|
|
804
814
|
def _get_partition(self, account: str) -> str:
|
|
@@ -1053,7 +1063,9 @@ class TerrascriptClient:
|
|
|
1053
1063
|
ignore_changes = (
|
|
1054
1064
|
"all" if "all" in lifecycle.ignore_changes else lifecycle.ignore_changes
|
|
1055
1065
|
)
|
|
1056
|
-
return lifecycle.
|
|
1066
|
+
return lifecycle.model_dump(by_alias=True) | {
|
|
1067
|
+
"ignore_changes": ignore_changes
|
|
1068
|
+
}
|
|
1057
1069
|
return None
|
|
1058
1070
|
|
|
1059
1071
|
def populate_additional_providers(
|
|
@@ -1068,25 +1080,15 @@ class TerrascriptClient:
|
|
|
1068
1080
|
config = self.configs[account_name]
|
|
1069
1081
|
existing_provider_aliases = {p.get("alias") for p in ts["provider"]["aws"]}
|
|
1070
1082
|
if alias not in existing_provider_aliases:
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
)
|
|
1081
|
-
else:
|
|
1082
|
-
ts += provider.aws(
|
|
1083
|
-
access_key=config["aws_access_key_id"],
|
|
1084
|
-
secret_key=config["aws_secret_access_key"],
|
|
1085
|
-
region=region,
|
|
1086
|
-
alias=alias,
|
|
1087
|
-
skip_region_validation=True,
|
|
1088
|
-
default_tags=DEFAULT_TAGS,
|
|
1089
|
-
)
|
|
1083
|
+
ts += provider.aws(
|
|
1084
|
+
access_key=config["aws_access_key_id"],
|
|
1085
|
+
secret_key=config["aws_secret_access_key"],
|
|
1086
|
+
region=region,
|
|
1087
|
+
alias=alias,
|
|
1088
|
+
skip_region_validation=True,
|
|
1089
|
+
default_tags={"tags": config["tags"]},
|
|
1090
|
+
**{"assume_role": {"role_arn": assume_role}} if assume_role else {},
|
|
1091
|
+
)
|
|
1090
1092
|
|
|
1091
1093
|
def populate_route53(
|
|
1092
1094
|
self, desired_state: Iterable[Mapping[str, Any]], default_ttl: int = 300
|
|
@@ -1343,13 +1345,13 @@ class TerrascriptClient:
|
|
|
1343
1345
|
vpc_module_values["public_subnets"] = request.subnets.public
|
|
1344
1346
|
vpc_module_values["public_subnet_tags"] = (
|
|
1345
1347
|
VPC_REQUEST_DEFAULT_PUBLIC_SUBNET_TAGS
|
|
1346
|
-
| (request.subnets.public_subnet_tags or {})
|
|
1348
|
+
| (request.subnets.public_subnet_tags or {})
|
|
1347
1349
|
)
|
|
1348
1350
|
if request.subnets.private:
|
|
1349
1351
|
vpc_module_values["private_subnets"] = request.subnets.private
|
|
1350
1352
|
vpc_module_values["private_subnet_tags"] = (
|
|
1351
1353
|
VPC_REQUEST_DEFAULT_PRIVATE_SUBNET_TAGS
|
|
1352
|
-
| (request.subnets.private_subnet_tags or {})
|
|
1354
|
+
| (request.subnets.private_subnet_tags or {})
|
|
1353
1355
|
)
|
|
1354
1356
|
if request.subnets.availability_zones:
|
|
1355
1357
|
vpc_module_values["azs"] = request.subnets.availability_zones
|
|
@@ -1429,7 +1431,7 @@ class TerrascriptClient:
|
|
|
1429
1431
|
req_account_name = req_account.name
|
|
1430
1432
|
# Accepter's side of the connection - the cluster's account
|
|
1431
1433
|
acc_account = accepter.account
|
|
1432
|
-
acc_alias = self.get_provider_alias(acc_account.
|
|
1434
|
+
acc_alias = self.get_provider_alias(acc_account.model_dump(by_alias=True))
|
|
1433
1435
|
acc_uid = acc_account.uid
|
|
1434
1436
|
if acc_account.assume_role:
|
|
1435
1437
|
acc_uid = awsh.get_account_uid_from_arn(acc_account.assume_role)
|
|
@@ -1946,7 +1948,7 @@ class TerrascriptClient:
|
|
|
1946
1948
|
em_identifier = f"{identifier}-enhanced-monitoring"
|
|
1947
1949
|
em_values = {
|
|
1948
1950
|
"name": em_identifier,
|
|
1949
|
-
"assume_role_policy":
|
|
1951
|
+
"assume_role_policy": json_dumps(assume_role_policy),
|
|
1950
1952
|
}
|
|
1951
1953
|
role_tf_resource = aws_iam_role(em_identifier, **em_values)
|
|
1952
1954
|
tf_resources.append(role_tf_resource)
|
|
@@ -2215,6 +2217,43 @@ class TerrascriptClient:
|
|
|
2215
2217
|
letters_and_digits = string.ascii_letters + string.digits
|
|
2216
2218
|
return "".join(random.choice(letters_and_digits) for i in range(string_length))
|
|
2217
2219
|
|
|
2220
|
+
@staticmethod
|
|
2221
|
+
def _build_tf_resource_s3_lifecycle_rules(
|
|
2222
|
+
versioning: bool,
|
|
2223
|
+
common_values: Mapping[str, Any],
|
|
2224
|
+
) -> list[dict]:
|
|
2225
|
+
lifecycle_rules = common_values.get("lifecycle_rules") or []
|
|
2226
|
+
if versioning and not any(
|
|
2227
|
+
"noncurrent_version_expiration" in lr for lr in lifecycle_rules
|
|
2228
|
+
):
|
|
2229
|
+
# Add a default noncurrent object expiration rule
|
|
2230
|
+
# if one isn't already set
|
|
2231
|
+
rule = {
|
|
2232
|
+
"id": "expire_noncurrent_versions",
|
|
2233
|
+
"enabled": True,
|
|
2234
|
+
"noncurrent_version_expiration": {"days": 30},
|
|
2235
|
+
"expiration": {"expired_object_delete_marker": True},
|
|
2236
|
+
"abort_incomplete_multipart_upload_days": 3,
|
|
2237
|
+
}
|
|
2238
|
+
lifecycle_rules.append(rule)
|
|
2239
|
+
|
|
2240
|
+
if storage_class := common_values.get("storage_class"):
|
|
2241
|
+
sc = storage_class.upper()
|
|
2242
|
+
days = "1"
|
|
2243
|
+
if sc.endswith("_IA"):
|
|
2244
|
+
# Infrequent Access storage class has minimum 30 days
|
|
2245
|
+
# before transition
|
|
2246
|
+
days = "30"
|
|
2247
|
+
rule = {
|
|
2248
|
+
"id": sc + "_storage_class",
|
|
2249
|
+
"enabled": True,
|
|
2250
|
+
"transition": {"days": days, "storage_class": sc},
|
|
2251
|
+
"noncurrent_version_transition": {"days": days, "storage_class": sc},
|
|
2252
|
+
}
|
|
2253
|
+
lifecycle_rules.append(rule)
|
|
2254
|
+
|
|
2255
|
+
return lifecycle_rules
|
|
2256
|
+
|
|
2218
2257
|
def populate_tf_resource_s3(self, spec: ExternalResourceSpec) -> aws_s3_bucket:
|
|
2219
2258
|
account = spec.provisioner_name
|
|
2220
2259
|
identifier = spec.identifier
|
|
@@ -2254,47 +2293,11 @@ class TerrascriptClient:
|
|
|
2254
2293
|
request_payer = common_values.get("request_payer")
|
|
2255
2294
|
if request_payer:
|
|
2256
2295
|
values["request_payer"] = request_payer
|
|
2257
|
-
lifecycle_rules
|
|
2258
|
-
|
|
2259
|
-
|
|
2296
|
+
if lifecycle_rules := self._build_tf_resource_s3_lifecycle_rules(
|
|
2297
|
+
versioning=versioning,
|
|
2298
|
+
common_values=common_values,
|
|
2299
|
+
):
|
|
2260
2300
|
values["lifecycle_rule"] = lifecycle_rules
|
|
2261
|
-
if versioning:
|
|
2262
|
-
lrs = values.get("lifecycle_rule", [])
|
|
2263
|
-
expiration_rule = False
|
|
2264
|
-
for lr in lrs:
|
|
2265
|
-
if "noncurrent_version_expiration" in lr:
|
|
2266
|
-
expiration_rule = True
|
|
2267
|
-
break
|
|
2268
|
-
if not expiration_rule:
|
|
2269
|
-
# Add a default noncurrent object expiration rule if
|
|
2270
|
-
# if one isn't already set
|
|
2271
|
-
rule = {
|
|
2272
|
-
"id": "expire_noncurrent_versions",
|
|
2273
|
-
"enabled": "true",
|
|
2274
|
-
"noncurrent_version_expiration": {"days": 30},
|
|
2275
|
-
}
|
|
2276
|
-
if len(lrs) > 0:
|
|
2277
|
-
lrs.append(rule)
|
|
2278
|
-
else:
|
|
2279
|
-
lrs = rule
|
|
2280
|
-
sc = common_values.get("storage_class")
|
|
2281
|
-
if sc:
|
|
2282
|
-
sc = sc.upper()
|
|
2283
|
-
days = "1"
|
|
2284
|
-
if sc.endswith("_IA"):
|
|
2285
|
-
# Infrequent Access storage class has minimum 30 days
|
|
2286
|
-
# before transition
|
|
2287
|
-
days = "30"
|
|
2288
|
-
rule = {
|
|
2289
|
-
"id": sc + "_storage_class",
|
|
2290
|
-
"enabled": "true",
|
|
2291
|
-
"transition": {"days": days, "storage_class": sc},
|
|
2292
|
-
"noncurrent_version_transition": {"days": days, "storage_class": sc},
|
|
2293
|
-
}
|
|
2294
|
-
if values.get("lifecycle_rule"):
|
|
2295
|
-
values["lifecycle_rule"].append(rule)
|
|
2296
|
-
else:
|
|
2297
|
-
values["lifecycle_rule"] = rule
|
|
2298
2301
|
cors_rules = common_values.get("cors_rules")
|
|
2299
2302
|
if cors_rules:
|
|
2300
2303
|
# common_values['cors_rules'] is a list of cors_rules
|
|
@@ -2344,7 +2347,7 @@ class TerrascriptClient:
|
|
|
2344
2347
|
}
|
|
2345
2348
|
],
|
|
2346
2349
|
}
|
|
2347
|
-
rc_values["assume_role_policy"] =
|
|
2350
|
+
rc_values["assume_role_policy"] = json_dumps(role)
|
|
2348
2351
|
role_resource = aws_iam_role(id, **rc_values)
|
|
2349
2352
|
tf_resources.append(role_resource)
|
|
2350
2353
|
|
|
@@ -2382,7 +2385,7 @@ class TerrascriptClient:
|
|
|
2382
2385
|
},
|
|
2383
2386
|
],
|
|
2384
2387
|
}
|
|
2385
|
-
rc_values["policy"] =
|
|
2388
|
+
rc_values["policy"] = json_dumps(policy)
|
|
2386
2389
|
policy_resource = aws_iam_policy(id, **rc_values)
|
|
2387
2390
|
tf_resources.append(policy_resource)
|
|
2388
2391
|
|
|
@@ -2597,7 +2600,7 @@ class TerrascriptClient:
|
|
|
2597
2600
|
},
|
|
2598
2601
|
],
|
|
2599
2602
|
}
|
|
2600
|
-
values["policy"] =
|
|
2603
|
+
values["policy"] = json_dumps(policy)
|
|
2601
2604
|
values["depends_on"] = self.get_dependencies([user_tf_resource])
|
|
2602
2605
|
|
|
2603
2606
|
tf_aws_iam_policy = aws_iam_policy(identifier, **values)
|
|
@@ -2876,7 +2879,7 @@ class TerrascriptClient:
|
|
|
2876
2879
|
values: dict[str, Any] = {
|
|
2877
2880
|
"name": identifier,
|
|
2878
2881
|
"tags": common_values["tags"],
|
|
2879
|
-
"assume_role_policy":
|
|
2882
|
+
"assume_role_policy": json_dumps(assume_role_policy),
|
|
2880
2883
|
}
|
|
2881
2884
|
|
|
2882
2885
|
inline_policy = common_values.get("inline_policy")
|
|
@@ -2930,7 +2933,7 @@ class TerrascriptClient:
|
|
|
2930
2933
|
self, account: str, name: str, policy: Mapping[str, Any]
|
|
2931
2934
|
) -> None:
|
|
2932
2935
|
tf_aws_iam_policy = aws_iam_policy(
|
|
2933
|
-
f"{account}-{name}", name=name, policy=
|
|
2936
|
+
f"{account}-{name}", name=name, policy=json_dumps(policy)
|
|
2934
2937
|
)
|
|
2935
2938
|
self.add_resource(account, tf_aws_iam_policy)
|
|
2936
2939
|
|
|
@@ -2972,7 +2975,7 @@ class TerrascriptClient:
|
|
|
2972
2975
|
role_tf_resource = aws_iam_role(
|
|
2973
2976
|
f"{account}-{name}",
|
|
2974
2977
|
name=name,
|
|
2975
|
-
assume_role_policy=
|
|
2978
|
+
assume_role_policy=json_dumps(assume_role_policy),
|
|
2976
2979
|
managed_policy_arns=managed_policy_arns,
|
|
2977
2980
|
max_session_duration=max_session_duration_hours * 3600,
|
|
2978
2981
|
)
|
|
@@ -3016,7 +3019,7 @@ class TerrascriptClient:
|
|
|
3016
3019
|
all_queues.append(queue_name)
|
|
3017
3020
|
sqs_policy = values.pop("sqs_policy", None)
|
|
3018
3021
|
if sqs_policy is not None:
|
|
3019
|
-
values["policy"] =
|
|
3022
|
+
values["policy"] = json_dumps(sqs_policy)
|
|
3020
3023
|
dl_queue = values.pop("dl_queue", None)
|
|
3021
3024
|
if dl_queue is not None:
|
|
3022
3025
|
max_receive_count = int(values.pop("max_receive_count", 10))
|
|
@@ -3030,9 +3033,7 @@ class TerrascriptClient:
|
|
|
3030
3033
|
"deadLetterTargetArn": "${" + dl_data.arn + "}",
|
|
3031
3034
|
"maxReceiveCount": max_receive_count,
|
|
3032
3035
|
}
|
|
3033
|
-
values["redrive_policy"] =
|
|
3034
|
-
redrive_policy, sort_keys=True
|
|
3035
|
-
)
|
|
3036
|
+
values["redrive_policy"] = json_dumps(redrive_policy)
|
|
3036
3037
|
kms_master_key_id = values.pop("kms_master_key_id", None)
|
|
3037
3038
|
if kms_master_key_id is not None:
|
|
3038
3039
|
if kms_master_key_id.startswith("arn:"):
|
|
@@ -3105,7 +3106,7 @@ class TerrascriptClient:
|
|
|
3105
3106
|
"Resource": list(kms_keys),
|
|
3106
3107
|
}
|
|
3107
3108
|
policy["Statement"].append(kms_statement)
|
|
3108
|
-
values["policy"] =
|
|
3109
|
+
values["policy"] = json_dumps(policy)
|
|
3109
3110
|
policy_tf_resource = aws_iam_policy(policy_identifier, **values)
|
|
3110
3111
|
tf_resources.append(policy_tf_resource)
|
|
3111
3112
|
|
|
@@ -3255,7 +3256,7 @@ class TerrascriptClient:
|
|
|
3255
3256
|
}
|
|
3256
3257
|
],
|
|
3257
3258
|
}
|
|
3258
|
-
values["policy"] =
|
|
3259
|
+
values["policy"] = json_dumps(policy)
|
|
3259
3260
|
values["depends_on"] = self.get_dependencies([user_tf_resource])
|
|
3260
3261
|
|
|
3261
3262
|
tf_aws_iam_policy = aws_iam_policy(identifier, **values)
|
|
@@ -3365,7 +3366,7 @@ class TerrascriptClient:
|
|
|
3365
3366
|
},
|
|
3366
3367
|
],
|
|
3367
3368
|
}
|
|
3368
|
-
values_policy["policy"] =
|
|
3369
|
+
values_policy["policy"] = json_dumps(policy)
|
|
3369
3370
|
values_policy["depends_on"] = self.get_dependencies([user_tf_resource])
|
|
3370
3371
|
|
|
3371
3372
|
tf_aws_iam_policy = aws_iam_policy(identifier, **values_policy)
|
|
@@ -3415,7 +3416,7 @@ class TerrascriptClient:
|
|
|
3415
3416
|
}
|
|
3416
3417
|
],
|
|
3417
3418
|
}
|
|
3418
|
-
values_policy["policy"] =
|
|
3419
|
+
values_policy["policy"] = json_dumps(policy)
|
|
3419
3420
|
values_policy["depends_on"] = self.get_dependencies([bucket_tf_resource])
|
|
3420
3421
|
region = common_values.get("region") or self.default_regions.get(account)
|
|
3421
3422
|
assert region # make mypy happy
|
|
@@ -3561,7 +3562,7 @@ class TerrascriptClient:
|
|
|
3561
3562
|
}
|
|
3562
3563
|
],
|
|
3563
3564
|
}
|
|
3564
|
-
sqs_values["policy"] =
|
|
3565
|
+
sqs_values["policy"] = json_dumps(sqs_policy)
|
|
3565
3566
|
|
|
3566
3567
|
kms_encryption = common_values.get("kms_encryption", False)
|
|
3567
3568
|
if kms_encryption:
|
|
@@ -3597,7 +3598,7 @@ class TerrascriptClient:
|
|
|
3597
3598
|
},
|
|
3598
3599
|
],
|
|
3599
3600
|
}
|
|
3600
|
-
kms_values["policy"] =
|
|
3601
|
+
kms_values["policy"] = json_dumps(kms_policy)
|
|
3601
3602
|
if provider:
|
|
3602
3603
|
kms_values["provider"] = provider
|
|
3603
3604
|
|
|
@@ -3695,7 +3696,7 @@ class TerrascriptClient:
|
|
|
3695
3696
|
"Resource": [sqs_values["kms_master_key_id"]],
|
|
3696
3697
|
}
|
|
3697
3698
|
policy["Statement"].append(kms_statement)
|
|
3698
|
-
values_policy["policy"] =
|
|
3699
|
+
values_policy["policy"] = json_dumps(policy)
|
|
3699
3700
|
policy_tf_resource = aws_iam_policy(sqs_identifier, **values_policy)
|
|
3700
3701
|
tf_resources.append(policy_tf_resource)
|
|
3701
3702
|
|
|
@@ -3766,7 +3767,7 @@ class TerrascriptClient:
|
|
|
3766
3767
|
role_identifier = f"{identifier}-lambda-execution-role"
|
|
3767
3768
|
role_values = {
|
|
3768
3769
|
"name": role_identifier,
|
|
3769
|
-
"assume_role_policy":
|
|
3770
|
+
"assume_role_policy": json_dumps(assume_role_policy),
|
|
3770
3771
|
}
|
|
3771
3772
|
|
|
3772
3773
|
role_tf_resource = aws_iam_role(role_identifier, **role_values)
|
|
@@ -3798,7 +3799,7 @@ class TerrascriptClient:
|
|
|
3798
3799
|
|
|
3799
3800
|
policy_values = {
|
|
3800
3801
|
"role": "${" + role_tf_resource.id + "}",
|
|
3801
|
-
"policy":
|
|
3802
|
+
"policy": json_dumps(policy),
|
|
3802
3803
|
}
|
|
3803
3804
|
policy_tf_resource = aws_iam_role_policy(policy_identifier, **policy_values)
|
|
3804
3805
|
tf_resources.append(policy_tf_resource)
|
|
@@ -3926,7 +3927,7 @@ class TerrascriptClient:
|
|
|
3926
3927
|
}
|
|
3927
3928
|
values = {
|
|
3928
3929
|
"name": identifier,
|
|
3929
|
-
"policy":
|
|
3930
|
+
"policy": json_dumps(policy),
|
|
3930
3931
|
"depends_on": self.get_dependencies([user_tf_resource]),
|
|
3931
3932
|
}
|
|
3932
3933
|
|
|
@@ -4023,6 +4024,22 @@ class TerrascriptClient:
|
|
|
4023
4024
|
kinesis_tf_resource = aws_kinesis_stream(identifier, **kinesis_values)
|
|
4024
4025
|
tf_resources.append(kinesis_tf_resource)
|
|
4025
4026
|
|
|
4027
|
+
# kinesis resource policy (optional)
|
|
4028
|
+
# Terraform resource reference:
|
|
4029
|
+
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kinesis_resource_policy
|
|
4030
|
+
if policy := common_values.get("policy"):
|
|
4031
|
+
policy_identifier = f"{identifier}-policy"
|
|
4032
|
+
policy_values: dict[str, Any] = {
|
|
4033
|
+
"resource_arn": "${" + kinesis_tf_resource.arn + "}",
|
|
4034
|
+
"policy": policy,
|
|
4035
|
+
}
|
|
4036
|
+
if provider:
|
|
4037
|
+
policy_values["provider"] = provider
|
|
4038
|
+
kinesis_policy_tf_resource = aws_kinesis_resource_policy(
|
|
4039
|
+
policy_identifier, **policy_values
|
|
4040
|
+
)
|
|
4041
|
+
tf_resources.append(kinesis_policy_tf_resource)
|
|
4042
|
+
|
|
4026
4043
|
es_identifier = common_values.get("es_identifier", None)
|
|
4027
4044
|
if es_identifier:
|
|
4028
4045
|
es_resource = self._find_resource_spec(
|
|
@@ -4047,7 +4064,7 @@ class TerrascriptClient:
|
|
|
4047
4064
|
role_identifier = f"{identifier}-lambda-execution-role"
|
|
4048
4065
|
role_values = {
|
|
4049
4066
|
"name": role_identifier,
|
|
4050
|
-
"assume_role_policy":
|
|
4067
|
+
"assume_role_policy": json_dumps(assume_role_policy),
|
|
4051
4068
|
"tags": tags,
|
|
4052
4069
|
}
|
|
4053
4070
|
|
|
@@ -4084,7 +4101,7 @@ class TerrascriptClient:
|
|
|
4084
4101
|
policy_tf_resource = aws_iam_policy(
|
|
4085
4102
|
policy_identifier,
|
|
4086
4103
|
name=policy_identifier,
|
|
4087
|
-
policy=
|
|
4104
|
+
policy=json_dumps(policy),
|
|
4088
4105
|
tags=tags,
|
|
4089
4106
|
)
|
|
4090
4107
|
tf_resources.append(policy_tf_resource)
|
|
@@ -4299,7 +4316,7 @@ class TerrascriptClient:
|
|
|
4299
4316
|
# iam user policy
|
|
4300
4317
|
values_policy: dict[str, Any] = {
|
|
4301
4318
|
"name": identifier,
|
|
4302
|
-
"policy":
|
|
4319
|
+
"policy": json_dumps(policy),
|
|
4303
4320
|
"depends_on": self.get_dependencies([user_tf_resource]),
|
|
4304
4321
|
}
|
|
4305
4322
|
|
|
@@ -4417,10 +4434,7 @@ class TerrascriptClient:
|
|
|
4417
4434
|
|
|
4418
4435
|
:return: key is AWS account name and value is terraform configuration
|
|
4419
4436
|
"""
|
|
4420
|
-
return {
|
|
4421
|
-
name: json.dumps(ts, indent=2, sort_keys=True)
|
|
4422
|
-
for name, ts in self.tss.items()
|
|
4423
|
-
}
|
|
4437
|
+
return {name: json_dumps(ts, indent=2) for name, ts in self.tss.items()}
|
|
4424
4438
|
|
|
4425
4439
|
def init_values(
|
|
4426
4440
|
self, spec: ExternalResourceSpec, init_tags: bool = True
|
|
@@ -4532,7 +4546,7 @@ class TerrascriptClient:
|
|
|
4532
4546
|
output_name = output_format.format(
|
|
4533
4547
|
spec.output_prefix, self.integration_prefix, "annotations"
|
|
4534
4548
|
)
|
|
4535
|
-
anno_json =
|
|
4549
|
+
anno_json = json_dumps(spec.annotations()).encode("utf-8")
|
|
4536
4550
|
output_value = base64.b64encode(anno_json).decode()
|
|
4537
4551
|
tf_resources.append(Output(output_name, value=output_value))
|
|
4538
4552
|
|
|
@@ -4672,7 +4686,7 @@ class TerrascriptClient:
|
|
|
4672
4686
|
}
|
|
4673
4687
|
log_groups_policy_values = {
|
|
4674
4688
|
"policy_name": "es-log-publishing-permissions",
|
|
4675
|
-
"policy_document":
|
|
4689
|
+
"policy_document": json_dumps(log_groups_policy),
|
|
4676
4690
|
}
|
|
4677
4691
|
resource_policy = aws_cloudwatch_log_resource_policy(
|
|
4678
4692
|
"es_log_publishing_resource_policy",
|
|
@@ -5004,7 +5018,7 @@ class TerrascriptClient:
|
|
|
5004
5018
|
}
|
|
5005
5019
|
],
|
|
5006
5020
|
}
|
|
5007
|
-
es_values["access_policies"] =
|
|
5021
|
+
es_values["access_policies"] = json_dumps(access_policies)
|
|
5008
5022
|
|
|
5009
5023
|
region = values.get("region") or self.default_regions.get(account)
|
|
5010
5024
|
assert region # make mypy happy
|
|
@@ -5060,7 +5074,7 @@ class TerrascriptClient:
|
|
|
5060
5074
|
|
|
5061
5075
|
version_values = {
|
|
5062
5076
|
"secret_id": "${" + aws_secret_resource.id + "}",
|
|
5063
|
-
"secret_string":
|
|
5077
|
+
"secret_string": json_dumps(master_user),
|
|
5064
5078
|
}
|
|
5065
5079
|
if provider:
|
|
5066
5080
|
version_values["provider"] = provider
|
|
@@ -5087,7 +5101,7 @@ class TerrascriptClient:
|
|
|
5087
5101
|
iam_policy_resource = aws_iam_policy(
|
|
5088
5102
|
secret_identifier,
|
|
5089
5103
|
name=f"{identifier}-secretsmanager-policy",
|
|
5090
|
-
policy=
|
|
5104
|
+
policy=json_dumps(policy),
|
|
5091
5105
|
tags=tags,
|
|
5092
5106
|
)
|
|
5093
5107
|
tf_resources.append(iam_policy_resource)
|
|
@@ -5346,6 +5360,11 @@ class TerrascriptClient:
|
|
|
5346
5360
|
)
|
|
5347
5361
|
if condition_type_key is None:
|
|
5348
5362
|
raise KeyError(f"unknown alb rule condition type {condition_type}")
|
|
5363
|
+
|
|
5364
|
+
# Query string conditions use a different structure than other condition types
|
|
5365
|
+
if condition_type == "query-string":
|
|
5366
|
+
return {condition_type_key: condition[condition_type_key]}
|
|
5367
|
+
|
|
5349
5368
|
return {condition_type_key: {"values": condition[condition_type_key]}}
|
|
5350
5369
|
|
|
5351
5370
|
@staticmethod
|
|
@@ -5494,7 +5513,7 @@ class TerrascriptClient:
|
|
|
5494
5513
|
lb_access_logs_s3_bucket_policy_values = {
|
|
5495
5514
|
"provider": provider,
|
|
5496
5515
|
"bucket": f"${{{lb_access_logs_s3_bucket_tf_resource.id}}}",
|
|
5497
|
-
"policy":
|
|
5516
|
+
"policy": json_dumps(policy),
|
|
5498
5517
|
}
|
|
5499
5518
|
lb_access_logs_s3_bucket_policy_tf_resource = aws_s3_bucket_policy(
|
|
5500
5519
|
policy_identifier, **lb_access_logs_s3_bucket_policy_values
|
|
@@ -5807,9 +5826,13 @@ class TerrascriptClient:
|
|
|
5807
5826
|
assert secret # make mypy happy
|
|
5808
5827
|
secret_data = self.secret_reader.read_all(secret)
|
|
5809
5828
|
|
|
5829
|
+
secret_format = common_values.get("secret_format")
|
|
5830
|
+
if secret_format is not None:
|
|
5831
|
+
secret_data = self._apply_secret_format(str(secret_format), secret_data)
|
|
5832
|
+
|
|
5810
5833
|
version_values: dict[str, Any] = {
|
|
5811
5834
|
"secret_id": "${" + aws_secret_resource.id + "}",
|
|
5812
|
-
"secret_string":
|
|
5835
|
+
"secret_string": json_dumps(secret_data),
|
|
5813
5836
|
}
|
|
5814
5837
|
|
|
5815
5838
|
if self._multiregion_account(account):
|
|
@@ -5830,6 +5853,66 @@ class TerrascriptClient:
|
|
|
5830
5853
|
|
|
5831
5854
|
self.add_resources(account, tf_resources)
|
|
5832
5855
|
|
|
5856
|
+
@staticmethod
|
|
5857
|
+
def _unflatten_dotted_keys_dict(flat_dict: dict[str, str]) -> dict[str, Any]:
|
|
5858
|
+
"""Convert a flat dictionary with dotted keys to a nested dictionary.
|
|
5859
|
+
|
|
5860
|
+
Example:
|
|
5861
|
+
{"db.host": "localhost", "db.port": "5432"} ->
|
|
5862
|
+
{"db": {"host": "localhost", "port": "5432"}}
|
|
5863
|
+
|
|
5864
|
+
Raises:
|
|
5865
|
+
ValueError: If there are conflicting keys (e.g., "a.b" and "a.b.c")
|
|
5866
|
+
"""
|
|
5867
|
+
result: dict[str, Any] = {}
|
|
5868
|
+
for key, value in flat_dict.items():
|
|
5869
|
+
parts = key.split(".")
|
|
5870
|
+
current = result
|
|
5871
|
+
for i, part in enumerate(parts[:-1]):
|
|
5872
|
+
if part not in current:
|
|
5873
|
+
current[part] = {}
|
|
5874
|
+
elif not isinstance(current[part], dict):
|
|
5875
|
+
# Conflict: trying to traverse through a non-dict value
|
|
5876
|
+
conflicting_path = ".".join(parts[: i + 1])
|
|
5877
|
+
raise ValueError(
|
|
5878
|
+
f"Conflicting keys detected: '{conflicting_path}' is both a "
|
|
5879
|
+
f"value and a nested path in key '{key}'"
|
|
5880
|
+
)
|
|
5881
|
+
current = current[part]
|
|
5882
|
+
|
|
5883
|
+
# Check if we're trying to set a value where a dict already exists
|
|
5884
|
+
if parts[-1] in current and isinstance(current[parts[-1]], dict):
|
|
5885
|
+
raise ValueError(
|
|
5886
|
+
f"Conflicting keys detected: '{key}' conflicts with nested keys"
|
|
5887
|
+
)
|
|
5888
|
+
|
|
5889
|
+
current[parts[-1]] = value
|
|
5890
|
+
|
|
5891
|
+
return result
|
|
5892
|
+
|
|
5893
|
+
@staticmethod
|
|
5894
|
+
def _apply_secret_format(
|
|
5895
|
+
secret_format: str, secret_data: dict[str, str]
|
|
5896
|
+
) -> dict[str, str]:
|
|
5897
|
+
# Convert flat dict with dotted keys to nested dict for Jinja2
|
|
5898
|
+
nested_secret_data = TerrascriptClient._unflatten_dotted_keys_dict(secret_data)
|
|
5899
|
+
rendered_data = process_jinja2_template(secret_format, nested_secret_data)
|
|
5900
|
+
|
|
5901
|
+
parsed_data = json.loads(rendered_data)
|
|
5902
|
+
|
|
5903
|
+
if not isinstance(parsed_data, dict):
|
|
5904
|
+
raise ValueError("secret_format must be a dictionary")
|
|
5905
|
+
|
|
5906
|
+
# validate secret is a dict[str, str]
|
|
5907
|
+
for k, v in parsed_data.items():
|
|
5908
|
+
if not isinstance(k, str):
|
|
5909
|
+
raise ValueError(f"key '{k}' is not a string")
|
|
5910
|
+
|
|
5911
|
+
if not isinstance(v, str):
|
|
5912
|
+
raise ValueError(f"dictionary value '{v}' under '{k}' is not a string")
|
|
5913
|
+
|
|
5914
|
+
return parsed_data
|
|
5915
|
+
|
|
5833
5916
|
def get_commit_sha(self, repo_info: Mapping) -> str:
|
|
5834
5917
|
url = repo_info["url"]
|
|
5835
5918
|
ref = repo_info["ref"]
|
|
@@ -5848,7 +5931,8 @@ class TerrascriptClient:
|
|
|
5848
5931
|
return commit.sha
|
|
5849
5932
|
case "gitlab":
|
|
5850
5933
|
gitlab = self.init_gitlab()
|
|
5851
|
-
project
|
|
5934
|
+
if not (project := gitlab.get_project(url)):
|
|
5935
|
+
raise ValueError(f"could not find gitlab project for url {url}")
|
|
5852
5936
|
commits = project.commits.list(ref_name=ref, per_page=1, page=1)
|
|
5853
5937
|
return commits[0].id
|
|
5854
5938
|
case _:
|
|
@@ -6129,7 +6213,7 @@ class TerrascriptClient:
|
|
|
6129
6213
|
lambda_iam_role_resource = aws_iam_role(
|
|
6130
6214
|
"lambda_role",
|
|
6131
6215
|
name=f"ocm-{identifier}-cognito-lambda-role",
|
|
6132
|
-
assume_role_policy=
|
|
6216
|
+
assume_role_policy=json_dumps(lambda_role_policy),
|
|
6133
6217
|
managed_policy_arns=[lambda_managed_policy_arn],
|
|
6134
6218
|
force_detach_policies=False,
|
|
6135
6219
|
max_session_duration=3600,
|
|
@@ -6804,7 +6888,7 @@ class TerrascriptClient:
|
|
|
6804
6888
|
)
|
|
6805
6889
|
tf_resources.append(api_gateway_stage_resource)
|
|
6806
6890
|
|
|
6807
|
-
rest_api_policy =
|
|
6891
|
+
rest_api_policy = json_dumps({
|
|
6808
6892
|
"Version": "2012-10-17",
|
|
6809
6893
|
"Statement": [
|
|
6810
6894
|
{
|
|
@@ -6908,7 +6992,7 @@ class TerrascriptClient:
|
|
|
6908
6992
|
},
|
|
6909
6993
|
],
|
|
6910
6994
|
}
|
|
6911
|
-
cloudwatch_assume_role_policy =
|
|
6995
|
+
cloudwatch_assume_role_policy = json_dumps(policy)
|
|
6912
6996
|
|
|
6913
6997
|
cloudwatch_iam_role_resource = aws_iam_role(
|
|
6914
6998
|
"cloudwatch_assume_role",
|
|
@@ -6936,7 +7020,7 @@ class TerrascriptClient:
|
|
|
6936
7020
|
],
|
|
6937
7021
|
}
|
|
6938
7022
|
|
|
6939
|
-
cloudwatch_iam_policy_document =
|
|
7023
|
+
cloudwatch_iam_policy_document = json_dumps(policy)
|
|
6940
7024
|
|
|
6941
7025
|
cloudwatch_iam_policy_resource = aws_iam_policy(
|
|
6942
7026
|
"cloudwatch",
|
|
@@ -7181,7 +7265,7 @@ class TerrascriptClient:
|
|
|
7181
7265
|
|
|
7182
7266
|
version_values = {
|
|
7183
7267
|
"secret_id": "${" + secret_resource.arn + "}",
|
|
7184
|
-
"secret_string":
|
|
7268
|
+
"secret_string": json_dumps(secret),
|
|
7185
7269
|
}
|
|
7186
7270
|
version_resource = aws_secretsmanager_secret_version(
|
|
7187
7271
|
secret_identifier, **version_values
|
|
@@ -7190,7 +7274,7 @@ class TerrascriptClient:
|
|
|
7190
7274
|
|
|
7191
7275
|
secret_policy_values = {
|
|
7192
7276
|
"secret_arn": "${" + secret_resource.arn + "}",
|
|
7193
|
-
"policy":
|
|
7277
|
+
"policy": json_dumps({
|
|
7194
7278
|
"Version": "2012-10-17",
|
|
7195
7279
|
"Statement": [
|
|
7196
7280
|
{
|